protected SocialActivityCounter addActivityCounter(
      final long groupId,
      final User user,
      final SocialActivity activity,
      final SocialActivityCounterDefinition activityCounterDefinition)
      throws PortalException {

    int ownerType = activityCounterDefinition.getOwnerType();

    long classNameId = getClassNameId(activity.getAssetEntry(), ownerType);
    long classPK = getClassPK(user, activity.getAssetEntry(), ownerType);

    SocialActivityCounter activityCounter =
        fetchLatestActivityCounter(
            groupId, classNameId, classPK, activityCounterDefinition.getName(), ownerType);

    if (activityCounter == null) {
      activityCounter =
          lockProtectedAddActivityCounter(
              groupId,
              classNameId,
              classPK,
              activityCounterDefinition.getName(),
              ownerType,
              0,
              0,
              activityCounterDefinition.getPeriodLength());
    } else if (!activityCounter.isActivePeriod(activityCounterDefinition.getPeriodLength())) {

      activityCounter =
          lockProtectedAddActivityCounter(
              groupId,
              classNameId,
              classPK,
              activityCounterDefinition.getName(),
              ownerType,
              activityCounter.getTotalValue(),
              activityCounter.getActivityCounterId(),
              activityCounterDefinition.getPeriodLength());
    }

    if (activityCounterDefinition.getLimitValue() > 0) {
      SocialActivityLimit activityLimit =
          socialActivityLimitPersistence.fetchByG_U_C_C_A_A(
              groupId,
              user.getUserId(),
              activity.getClassNameId(),
              getLimitClassPK(activity, activityCounterDefinition),
              activity.getType(),
              activityCounterDefinition.getName());

      if (activityLimit == null) {
        lockProtectedGetActivityLimit(groupId, user, activity, activityCounterDefinition);
      }
    }

    return activityCounter;
  }
  /**
   * Adds or increments activity counters related to an activity. This method is called
   * asynchronously from the social activity service when the user performs an activity defined in
   * </code>liferay-social.xml</code>.
   *
   * <p>This method first calls the activity processor class, if there is one defined for the
   * activity, checks for limits and increments all the counters that belong to the activity.
   * Afterwards, it processes the activity with respect to achievement classes, if any. Lastly it
   * increments the built-in <code>user.activities</code> and <code>asset.activities</code>
   * counters.
   *
   * @param activity the social activity
   * @throws PortalException if an expected group or expected previous activity counters could not
   *     be found
   */
  @Override
  public void addActivityCounters(SocialActivity activity) throws PortalException {

    if (!socialActivitySettingLocalService.isEnabled(
        activity.getGroupId(), activity.getClassNameId())) {

      return;
    }

    if (!socialActivitySettingLocalService.isEnabled(
        activity.getGroupId(), activity.getClassNameId(), activity.getClassPK())) {

      return;
    }

    if ((activity.getType() == SocialActivityConstants.TYPE_MOVE_ATTACHMENT_TO_TRASH)
        || (activity.getType() == SocialActivityConstants.TYPE_MOVE_TO_TRASH)) {

      disableActivityCounters(activity.getClassNameId(), activity.getClassPK());

      return;
    }

    if ((activity.getType() == SocialActivityConstants.TYPE_RESTORE_ATTACHMENT_FROM_TRASH)
        || (activity.getType() == SocialActivityConstants.TYPE_RESTORE_FROM_TRASH)) {

      enableActivityCounters(activity.getClassNameId(), activity.getClassPK());

      return;
    }

    User user = userPersistence.findByPrimaryKey(activity.getUserId());

    SocialActivityDefinition activityDefinition =
        socialActivitySettingLocalService.getActivityDefinition(
            activity.getGroupId(), activity.getClassName(), activity.getType());

    if ((activityDefinition == null) || !activityDefinition.isCountersEnabled()) {

      return;
    }

    SocialActivityProcessor activityProcessor = activityDefinition.getActivityProcessor();

    if (activityProcessor != null) {
      activityProcessor.processActivity(activity);
    }

    AssetEntry assetEntry = activity.getAssetEntry();

    User assetEntryUser = userPersistence.findByPrimaryKey(assetEntry.getUserId());

    List<SocialActivityCounter> activityCounters = new ArrayList<>();

    for (SocialActivityCounterDefinition activityCounterDefinition :
        activityDefinition.getActivityCounterDefinitions()) {

      if (isAddActivityCounter(user, assetEntryUser, assetEntry, activityCounterDefinition)) {

        SocialActivityCounter activityCounter =
            addActivityCounter(activity.getGroupId(), user, activity, activityCounterDefinition);

        activityCounters.add(activityCounter);
      }
    }

    SocialActivityCounter assetActivitiesCounter = null;

    if (!assetEntryUser.isDefaultUser() && assetEntryUser.isActive() && assetEntry.isVisible()) {

      assetActivitiesCounter = addAssetActivitiesCounter(activity);
    }

    SocialActivityCounter userActivitiesCounter = null;

    if (!user.isDefaultUser() && user.isActive()) {
      userActivitiesCounter = addUserActivitiesCounter(activity);
    }

    for (SocialActivityCounter activityCounter : activityCounters) {
      SocialActivityCounterDefinition activityCounterDefinition =
          activityDefinition.getActivityCounterDefinition(activityCounter.getName());

      if (checkActivityLimit(user, activity, activityCounterDefinition)) {
        incrementActivityCounter(activityCounter, activityCounterDefinition);
      }
    }

    if (assetActivitiesCounter != null) {
      incrementActivityCounter(assetActivitiesCounter, _assetActivitiesActivityCounterDefinition);
    }

    if (userActivitiesCounter != null) {
      incrementActivityCounter(userActivitiesCounter, _userActivitiesActivityCounterDefinition);
    }

    for (SocialAchievement achievement : activityDefinition.getAchievements()) {

      achievement.processActivity(activity);
    }
  }