001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.social.service.impl;
016    
017    import com.liferay.portal.kernel.cache.MultiVMPoolUtil;
018    import com.liferay.portal.kernel.cache.PortalCache;
019    import com.liferay.portal.kernel.dao.orm.QueryUtil;
020    import com.liferay.portal.kernel.exception.PortalException;
021    import com.liferay.portal.kernel.lock.LockProtectedAction;
022    import com.liferay.portal.kernel.transaction.Propagation;
023    import com.liferay.portal.kernel.transaction.Transactional;
024    import com.liferay.portal.kernel.util.StringPool;
025    import com.liferay.portal.kernel.util.StringUtil;
026    import com.liferay.portal.kernel.util.Tuple;
027    import com.liferay.portal.model.Group;
028    import com.liferay.portal.model.User;
029    import com.liferay.portal.util.PortalUtil;
030    import com.liferay.portal.util.PropsValues;
031    import com.liferay.portlet.asset.model.AssetEntry;
032    import com.liferay.portlet.social.model.SocialAchievement;
033    import com.liferay.portlet.social.model.SocialActivity;
034    import com.liferay.portlet.social.model.SocialActivityConstants;
035    import com.liferay.portlet.social.model.SocialActivityCounter;
036    import com.liferay.portlet.social.model.SocialActivityCounterConstants;
037    import com.liferay.portlet.social.model.SocialActivityCounterDefinition;
038    import com.liferay.portlet.social.model.SocialActivityDefinition;
039    import com.liferay.portlet.social.model.SocialActivityLimit;
040    import com.liferay.portlet.social.model.SocialActivityProcessor;
041    import com.liferay.portlet.social.model.impl.SocialActivityImpl;
042    import com.liferay.portlet.social.service.base.SocialActivityCounterLocalServiceBaseImpl;
043    import com.liferay.portlet.social.service.persistence.SocialActivityCounterFinder;
044    import com.liferay.portlet.social.util.SocialCounterPeriodUtil;
045    
046    import java.util.ArrayList;
047    import java.util.Arrays;
048    import java.util.Collections;
049    import java.util.HashMap;
050    import java.util.List;
051    import java.util.Map;
052    
053    /**
054     * The social activity counter local service. This service is responsible for
055     * creating and/or incrementing counters in response to an activity. It also
056     * provides methods for querying activity counters within a time period.
057     *
058     * <p>
059     * Under normal circumstances only the {@link
060     * #addActivityCounters(SocialActivity)} should be called directly and even that
061     * is usually not necessary as it is automatically called by the social activity
062     * service.
063     * </p>
064     *
065     * @author Zsolt Berentey
066     * @author Shuyang Zhou
067     */
068    public class SocialActivityCounterLocalServiceImpl
069            extends SocialActivityCounterLocalServiceBaseImpl {
070    
071            /**
072             * Adds an activity counter with a default period length.
073             *
074             * <p>
075             * This method uses the lock service to guard against multiple threads
076             * trying to insert the same counter because this service is called
077             * asynchronously from the social activity service.
078             * </p>
079             *
080             * @param      groupId the primary key of the group
081             * @param      classNameId the primary key of the entity's class this
082             *             counter belongs to
083             * @param      classPK the primary key of the entity this counter belongs to
084             * @param      name the counter's name
085             * @param      ownerType the counter's owner type. Acceptable values are
086             *             <code>TYPE_ACTOR</code>, <code>TYPE_ASSET</code> and
087             *             <code>TYPE_CREATOR</code> defined in {@link
088             *             com.liferay.portlet.social.model.SocialActivityCounterConstants}.
089             * @param      currentValue the counter's current value (optionally
090             *             <code>0</code>)
091             * @param      totalValue the counter's total value (optionally
092             *             <code>0</code>)
093             * @param      startPeriod the counter's start period
094             * @param      endPeriod the counter's end period
095             * @return     the added activity counter
096             * @throws     PortalException if the group or the previous activity counter
097             *             could not be found
098             * @deprecated As of 6.2.0, replaced by {@link #addActivityCounter(long,
099             *             long, long, String, int, int, long, int)}
100             */
101            @Deprecated
102            @Override
103            public SocialActivityCounter addActivityCounter(
104                            long groupId, long classNameId, long classPK, String name,
105                            int ownerType, int currentValue, int totalValue, int startPeriod,
106                            int endPeriod)
107                    throws PortalException {
108    
109                    return addActivityCounter(
110                            groupId, classNameId, classPK, name, ownerType, totalValue, 0, 0);
111            }
112    
113            /**
114             * Adds an activity counter specifying a previous activity and period
115             * length.
116             *
117             * <p>
118             * This method uses the lock service to guard against multiple threads
119             * trying to insert the same counter because this service is called
120             * asynchronously from the social activity service.
121             * </p>
122             *
123             * @param      groupId the primary key of the group
124             * @param      classNameId the primary key of the entity's class this
125             *             counter belongs to
126             * @param      classPK the primary key of the entity this counter belongs to
127             * @param      name the counter name
128             * @param      ownerType the counter's owner type. Acceptable values are
129             *             <code>TYPE_ACTOR</code>, <code>TYPE_ASSET</code> and
130             *             <code>TYPE_CREATOR</code> defined in {@link
131             *             com.liferay.portlet.social.model.SocialActivityCounterConstants}.
132             * @param      currentValue the current value of the counter (optionally
133             *             <code>0</code>)
134             * @param      totalValue the counter's total value (optionally
135             *             <code>0</code>)
136             * @param      startPeriod the counter's start period
137             * @param      endPeriod the counter's end period
138             * @param      previousActivityCounterId the primary key of the activity
139             *             counter for the previous time period (optionally
140             *             <code>0</code>, if this is the first)
141             * @param      periodLength the period length in days,
142             *             <code>PERIOD_LENGTH_INFINITE</code> for never ending counters
143             *             or <code>PERIOD_LENGTH_SYSTEM</code> for the period length
144             *             defined in <code>portal-ext.properties</code>. For more
145             *             information see {@link
146             *             com.liferay.portlet.social.model.SocialActivityCounterConstants}.
147             * @return     the added activity counter
148             * @throws     PortalException if the group or the previous activity counter
149             *             could not be found
150             * @deprecated As of 6.2.0, replaced by {@link #addActivityCounter(long,
151             *             long, long, String, int, int, long, int)}
152             */
153            @Deprecated
154            @Override
155            public SocialActivityCounter addActivityCounter(
156                            long groupId, long classNameId, long classPK, String name,
157                            int ownerType, int currentValue, int totalValue, int startPeriod,
158                            int endPeriod, long previousActivityCounterId, int periodLength)
159                    throws PortalException {
160    
161                    return addActivityCounter(
162                            groupId, classNameId, classPK, name, ownerType, totalValue,
163                            previousActivityCounterId, periodLength);
164            }
165    
166            /**
167             * Adds an activity counter specifying a previous activity and period
168             * length.
169             *
170             * <p>
171             * This method uses the lock service to guard against multiple threads
172             * trying to insert the same counter because this service is called
173             * asynchronously from the social activity service.
174             * </p>
175             *
176             * @param  groupId the primary key of the group
177             * @param  classNameId the primary key of the entity's class this counter
178             *         belongs to
179             * @param  classPK the primary key of the entity this counter belongs to
180             * @param  name the counter name
181             * @param  ownerType the counter's owner type. Acceptable values are
182             *         <code>TYPE_ACTOR</code>, <code>TYPE_ASSET</code> and
183             *         <code>TYPE_CREATOR</code> defined in {@link
184             *         com.liferay.portlet.social.model.SocialActivityCounterConstants}.
185             * @param  totalValue the counter's total value (optionally <code>0</code>)
186             * @param  previousActivityCounterId the primary key of the activity counter
187             *         for the previous time period (optionally <code>0</code>, if this
188             *         is the first)
189             * @param  periodLength the period length in days,
190             *         <code>PERIOD_LENGTH_INFINITE</code> for never ending counters or
191             *         <code>PERIOD_LENGTH_SYSTEM</code> for the period length defined
192             *         in <code>portal-ext.properties</code>. For more information see
193             *         {@link
194             *         com.liferay.portlet.social.model.SocialActivityCounterConstants}.
195             * @return the added activity counter
196             * @throws PortalException if the group or the previous activity counter
197             *         could not be found
198             */
199            @Override
200            @Transactional(propagation = Propagation.REQUIRES_NEW)
201            public SocialActivityCounter addActivityCounter(
202                            long groupId, long classNameId, long classPK, String name,
203                            int ownerType, int totalValue, long previousActivityCounterId,
204                            int periodLength)
205                    throws PortalException {
206    
207                    SocialActivityCounter activityCounter = null;
208    
209                    if (previousActivityCounterId != 0) {
210                            activityCounter = socialActivityCounterPersistence.findByPrimaryKey(
211                                    previousActivityCounterId);
212    
213                            if (periodLength ==
214                                            SocialActivityCounterConstants.PERIOD_LENGTH_SYSTEM) {
215    
216                                    activityCounter.setEndPeriod(
217                                            SocialCounterPeriodUtil.getStartPeriod() - 1);
218                            }
219                            else {
220                                    activityCounter.setEndPeriod(
221                                            activityCounter.getStartPeriod() + periodLength - 1);
222                            }
223    
224                            socialActivityCounterPersistence.update(activityCounter);
225                    }
226    
227                    activityCounter = socialActivityCounterPersistence.fetchByG_C_C_N_O_E(
228                            groupId, classNameId, classPK, name, ownerType,
229                            SocialActivityCounterConstants.END_PERIOD_UNDEFINED, false);
230    
231                    if (activityCounter != null) {
232                            return activityCounter;
233                    }
234    
235                    Group group = groupPersistence.findByPrimaryKey(groupId);
236    
237                    long activityCounterId = counterLocalService.increment();
238    
239                    activityCounter = socialActivityCounterPersistence.create(
240                            activityCounterId);
241    
242                    activityCounter.setGroupId(groupId);
243                    activityCounter.setCompanyId(group.getCompanyId());
244                    activityCounter.setClassNameId(classNameId);
245                    activityCounter.setClassPK(classPK);
246                    activityCounter.setName(name);
247                    activityCounter.setOwnerType(ownerType);
248                    activityCounter.setTotalValue(totalValue);
249    
250                    if (periodLength ==
251                                    SocialActivityCounterConstants.PERIOD_LENGTH_SYSTEM) {
252    
253                            activityCounter.setStartPeriod(
254                                    SocialCounterPeriodUtil.getStartPeriod());
255                    }
256                    else {
257                            activityCounter.setStartPeriod(
258                                    SocialCounterPeriodUtil.getActivityDay());
259                    }
260    
261                    activityCounter.setEndPeriod(
262                            SocialActivityCounterConstants.END_PERIOD_UNDEFINED);
263                    activityCounter.setActive(true);
264    
265                    socialActivityCounterPersistence.update(activityCounter);
266    
267                    return activityCounter;
268            }
269    
270            /**
271             * Adds or increments activity counters related to an activity.
272             *
273             * </p>
274             * This method is called asynchronously from the social activity service
275             * when the user performs an activity defined in
276             * </code>liferay-social.xml</code>.
277             * </p>
278             *
279             * <p>
280             * This method first calls the activity processor class, if there is one
281             * defined for the activity, checks for limits and increments all the
282             * counters that belong to the activity. Afterwards, it processes the
283             * activity with respect to achievement classes, if any. Lastly it
284             * increments the built-in <code>user.activities</code> and
285             * <code>asset.activities</code> counters.
286             * </p>
287             *
288             * @param  activity the social activity
289             * @throws PortalException if an expected group or expected previous
290             *         activity counters could not be found
291             */
292            @Override
293            public void addActivityCounters(SocialActivity activity)
294                    throws PortalException {
295    
296                    if (!socialActivitySettingLocalService.isEnabled(
297                                    activity.getGroupId(), activity.getClassNameId())) {
298    
299                            return;
300                    }
301    
302                    if (!socialActivitySettingLocalService.isEnabled(
303                                    activity.getGroupId(), activity.getClassNameId(),
304                                    activity.getClassPK())) {
305    
306                            return;
307                    }
308    
309                    if ((activity.getType() ==
310                                    SocialActivityConstants.TYPE_MOVE_ATTACHMENT_TO_TRASH) ||
311                            (activity.getType() ==
312                                    SocialActivityConstants.TYPE_MOVE_TO_TRASH)) {
313    
314                            disableActivityCounters(
315                                    activity.getClassNameId(), activity.getClassPK());
316    
317                            return;
318                    }
319    
320                    if ((activity.getType() ==
321                                    SocialActivityConstants.TYPE_RESTORE_ATTACHMENT_FROM_TRASH) ||
322                            (activity.getType() ==
323                                    SocialActivityConstants.TYPE_RESTORE_FROM_TRASH)) {
324    
325                            enableActivityCounters(
326                                    activity.getClassNameId(), activity.getClassPK());
327    
328                            return;
329                    }
330    
331                    User user = userPersistence.findByPrimaryKey(activity.getUserId());
332    
333                    SocialActivityDefinition activityDefinition =
334                            socialActivitySettingLocalService.getActivityDefinition(
335                                    activity.getGroupId(), activity.getClassName(),
336                                    activity.getType());
337    
338                    if ((activityDefinition == null) ||
339                            !activityDefinition.isCountersEnabled()) {
340    
341                            return;
342                    }
343    
344                    SocialActivityProcessor activityProcessor =
345                            activityDefinition.getActivityProcessor();
346    
347                    if (activityProcessor != null) {
348                            activityProcessor.processActivity(activity);
349                    }
350    
351                    AssetEntry assetEntry = activity.getAssetEntry();
352    
353                    User assetEntryUser = userPersistence.findByPrimaryKey(
354                            assetEntry.getUserId());
355    
356                    List<SocialActivityCounter> activityCounters = new ArrayList<>();
357    
358                    for (SocialActivityCounterDefinition activityCounterDefinition :
359                                    activityDefinition.getActivityCounterDefinitions()) {
360    
361                            if (isAddActivityCounter(
362                                            user, assetEntryUser, assetEntry,
363                                            activityCounterDefinition)) {
364    
365                                    SocialActivityCounter activityCounter = addActivityCounter(
366                                            activity.getGroupId(), user, activity,
367                                            activityCounterDefinition);
368    
369                                    activityCounters.add(activityCounter);
370                            }
371                    }
372    
373                    SocialActivityCounter assetActivitiesCounter = null;
374    
375                    if (!assetEntryUser.isDefaultUser() && assetEntryUser.isActive() &&
376                            assetEntry.isVisible()) {
377    
378                            assetActivitiesCounter = addAssetActivitiesCounter(activity);
379                    }
380    
381                    SocialActivityCounter userActivitiesCounter = null;
382    
383                    if (!user.isDefaultUser() && user.isActive()) {
384                            userActivitiesCounter = addUserActivitiesCounter(activity);
385                    }
386    
387                    for (SocialActivityCounter activityCounter : activityCounters) {
388                            SocialActivityCounterDefinition activityCounterDefinition =
389                                    activityDefinition.getActivityCounterDefinition(
390                                            activityCounter.getName());
391    
392                            if (checkActivityLimit(user, activity, activityCounterDefinition)) {
393                                    incrementActivityCounter(
394                                            activityCounter, activityCounterDefinition);
395                            }
396                    }
397    
398                    if (assetActivitiesCounter != null) {
399                            incrementActivityCounter(
400                                    assetActivitiesCounter,
401                                    _assetActivitiesActivityCounterDefinition);
402                    }
403    
404                    if (userActivitiesCounter != null) {
405                            incrementActivityCounter(
406                                    userActivitiesCounter,
407                                    _userActivitiesActivityCounterDefinition);
408                    }
409    
410                    for (SocialAchievement achievement :
411                                    activityDefinition.getAchievements()) {
412    
413                            achievement.processActivity(activity);
414                    }
415            }
416    
417            /**
418             * Creates an activity counter with a default period length, adding it into
419             * the database.
420             *
421             * @param      groupId the primary key of the group
422             * @param      classNameId the primary key of the entity's class this
423             *             counter belongs to
424             * @param      classPK the primary key of the entity this counter belongs to
425             * @param      name the counter's name
426             * @param      ownerType the counter's owner type. Acceptable values are
427             *             <code>TYPE_ACTOR</code>, <code>TYPE_ASSET</code> and
428             *             <code>TYPE_CREATOR</code> defined in {@link
429             *             com.liferay.portlet.social.model.SocialActivityCounterConstants}.
430             * @param      currentValue the counter's current value (optionally
431             *             <code>0</code>)
432             * @param      totalValue the counter's total value (optionally
433             *             <code>0</code>)
434             * @param      startPeriod the counter's start period
435             * @param      endPeriod the counter's end period
436             * @return     the created activity counter
437             * @throws     PortalException if the group or a previous activity counter
438             *             could not be found
439             * @deprecated As of 6.2.0, replaced by {@link #addActivityCounter(long,
440             *             long, long, String, int, int, long, int)}
441             */
442            @Deprecated
443            @Override
444            @Transactional(propagation = Propagation.REQUIRES_NEW)
445            public SocialActivityCounter createActivityCounter(
446                            long groupId, long classNameId, long classPK, String name,
447                            int ownerType, int currentValue, int totalValue, int startPeriod,
448                            int endPeriod)
449                    throws PortalException {
450    
451                    return addActivityCounter(
452                            groupId, classNameId, classPK, name, ownerType, totalValue, 0, 0);
453            }
454    
455            /**
456             * Creates an activity counter, adding it into the database.
457             *
458             * <p>
459             * This method actually creates the counter in the database. It requires a
460             * new transaction so that other threads can find the new counter when the
461             * lock in the calling method is released.
462             * </p>
463             *
464             * @param      groupId the primary key of the group
465             * @param      classNameId the primary key of the entity's class this
466             *             counter belongs to
467             * @param      classPK the primary key of the entity this counter belongs to
468             * @param      name the counter's name
469             * @param      ownerType the counter's owner type. Acceptable values are
470             *             <code>TYPE_ACTOR</code>, <code>TYPE_ASSET</code> and
471             *             <code>TYPE_CREATOR</code> defined in {@link
472             *             com.liferay.portlet.social.model.SocialActivityCounterConstants}.
473             * @param      currentValue the counter's current value (optionally
474             *             <code>0</code>)
475             * @param      totalValue the counter's total value of the counter
476             *             (optionally <code>0</code>)
477             * @param      startPeriod the counter's start period
478             * @param      endPeriod the counter's end period
479             * @param      previousActivityCounterId the primary key of the activity
480             *             counter for the previous time period (optionally
481             *             <code>0</code>, if this is the first)
482             * @param      periodLength the period length in days,
483             *             <code>PERIOD_LENGTH_INFINITE</code> for never ending counters
484             *             or <code>PERIOD_LENGTH_SYSTEM</code> for the period length
485             *             defined in <code>portal-ext.properties</code>. For more
486             *             information see {@link
487             *             com.liferay.portlet.social.model.SocialActivityConstants}.
488             * @return     the created activity counter
489             * @throws     PortalException if the group or the previous activity counter
490             *             could not be found
491             * @deprecated As of 6.2.0, replaced by {@link #addActivityCounter(long,
492             *             long, long, String, int, int, long, int)}
493             */
494            @Deprecated
495            @Override
496            @Transactional(propagation = Propagation.REQUIRES_NEW)
497            public SocialActivityCounter createActivityCounter(
498                            long groupId, long classNameId, long classPK, String name,
499                            int ownerType, int currentValue, int totalValue, int startPeriod,
500                            int endPeriod, long previousActivityCounterId, int periodLength)
501                    throws PortalException {
502    
503                    return addActivityCounter(
504                            groupId, classNameId, classPK, name, ownerType, totalValue,
505                            previousActivityCounterId, periodLength);
506            }
507    
508            /**
509             * Deletes all activity counters, limits, and settings related to the asset.
510             *
511             * <p>
512             * This method subtracts the asset's popularity from the owner's
513             * contribution points. It also creates a new contribution period if the
514             * latest one does not belong to the current period.
515             * </p>
516             *
517             * @param  assetEntry the asset entry
518             * @throws PortalException if the new contribution counter could not be
519             *         created
520             */
521            @Override
522            public void deleteActivityCounters(AssetEntry assetEntry)
523                    throws PortalException {
524    
525                    if (assetEntry == null) {
526                            return;
527                    }
528    
529                    adjustUserContribution(assetEntry, false);
530    
531                    socialActivityCounterPersistence.removeByC_C(
532                            assetEntry.getClassNameId(), assetEntry.getClassPK());
533    
534                    socialActivityLimitPersistence.removeByC_C(
535                            assetEntry.getClassNameId(), assetEntry.getClassPK());
536    
537                    socialActivitySettingLocalService.deleteActivitySetting(
538                            assetEntry.getGroupId(), assetEntry.getClassName(),
539                            assetEntry.getClassPK());
540    
541                    clearFinderCache();
542            }
543    
544            /**
545             * Deletes all activity counters, limits, and settings related to the entity
546             * identified by the class name ID and class primary key.
547             *
548             * @param  classNameId the primary key of the entity's class
549             * @param  classPK the primary key of the entity
550             * @throws PortalException if the entity is an asset and its owner's
551             *         contribution counter could not be updated
552             */
553            @Override
554            public void deleteActivityCounters(long classNameId, long classPK)
555                    throws PortalException {
556    
557                    String className = PortalUtil.getClassName(classNameId);
558    
559                    if (!className.equals(User.class.getName())) {
560                            AssetEntry assetEntry = assetEntryLocalService.fetchEntry(
561                                    className, classPK);
562    
563                            deleteActivityCounters(assetEntry);
564                    }
565                    else {
566                            socialActivityCounterPersistence.removeByC_C(classNameId, classPK);
567    
568                            socialActivityLimitPersistence.removeByUserId(classPK);
569                    }
570    
571                    clearFinderCache();
572            }
573    
574            /**
575             * Deletes all activity counters for the entity identified by the class name
576             * and class primary key.
577             *
578             * @param  className the entity's class name
579             * @param  classPK the primary key of the entity
580             * @throws PortalException if the entity is an asset and its owner's
581             *         contribution counter could not be updated
582             */
583            @Override
584            public void deleteActivityCounters(String className, long classPK)
585                    throws PortalException {
586    
587                    if (!className.equals(User.class.getName())) {
588                            AssetEntry assetEntry = assetEntryLocalService.fetchEntry(
589                                    className, classPK);
590    
591                            deleteActivityCounters(assetEntry);
592                    }
593                    else {
594                            long classNameId = classNameLocalService.getClassNameId(className);
595    
596                            socialActivityCounterPersistence.removeByC_C(classNameId, classPK);
597    
598                            socialActivityLimitPersistence.removeByUserId(classPK);
599                    }
600    
601                    clearFinderCache();
602            }
603    
604            /**
605             * Disables all the counters of an asset identified by the class name ID and
606             * class primary key.
607             *
608             * <p>
609             * This method is used by the recycle bin to disable all counters of assets
610             * put into the recycle bin. It adjusts the owner's contribution score.
611             * </p>
612             *
613             * @param  classNameId the primary key of the asset's class
614             * @param  classPK the primary key of the asset
615             * @throws PortalException if the asset owner's contribution counter could
616             *         not be updated
617             */
618            @Override
619            public void disableActivityCounters(long classNameId, long classPK)
620                    throws PortalException {
621    
622                    String className = PortalUtil.getClassName(classNameId);
623    
624                    disableActivityCounters(className, classPK);
625            }
626    
627            /**
628             * Disables all the counters of an asset identified by the class name and
629             * class primary key.
630             *
631             * <p>
632             * This method is used by the recycle bin to disable all counters of assets
633             * put into the recycle bin. It adjusts the owner's contribution score.
634             * </p>
635             *
636             * @param  className the asset's class name
637             * @param  classPK the primary key of the asset
638             * @throws PortalException if the asset owner's contribution counter could
639             *         not be updated
640             */
641            @Override
642            public void disableActivityCounters(String className, long classPK)
643                    throws PortalException {
644    
645                    AssetEntry assetEntry = assetEntryLocalService.fetchEntry(
646                            className, classPK);
647    
648                    if (assetEntry == null) {
649                            return;
650                    }
651    
652                    List<SocialActivityCounter> activityCounters =
653                            socialActivityCounterPersistence.findByC_C(
654                                    assetEntry.getClassNameId(), classPK);
655    
656                    adjustUserContribution(assetEntry, false);
657    
658                    for (SocialActivityCounter activityCounter : activityCounters) {
659                            if (activityCounter.isActive()) {
660                                    activityCounter.setActive(false);
661    
662                                    socialActivityCounterPersistence.update(activityCounter);
663                            }
664                    }
665    
666                    clearFinderCache();
667            }
668    
669            /**
670             * Enables all activity counters of an asset identified by the class name ID
671             * and class primary key.
672             *
673             * <p>
674             * This method is used by the recycle bin to enable all counters of assets
675             * restored from the recycle bin. It adjusts the owner's contribution score.
676             * </p>
677             *
678             * @param  classNameId the primary key of the asset's class
679             * @param  classPK the primary key of the asset
680             * @throws PortalException if the asset owner's contribution counter could
681             *         not be updated
682             */
683            @Override
684            public void enableActivityCounters(long classNameId, long classPK)
685                    throws PortalException {
686    
687                    String className = PortalUtil.getClassName(classNameId);
688    
689                    enableActivityCounters(className, classPK);
690            }
691    
692            /**
693             * Enables all the counters of an asset identified by the class name and
694             * class primary key.
695             *
696             * <p>
697             * This method is used by the recycle bin to enable all counters of assets
698             * restored from the recycle bin. It adjusts the owner's contribution score.
699             * </p>
700             *
701             * @param  className the asset's class name
702             * @param  classPK the primary key of the asset
703             * @throws PortalException if the asset owner's contribution counter could
704             *         not be updated
705             */
706            @Override
707            public void enableActivityCounters(String className, long classPK)
708                    throws PortalException {
709    
710                    AssetEntry assetEntry = assetEntryLocalService.fetchEntry(
711                            className, classPK);
712    
713                    if (assetEntry == null) {
714                            return;
715                    }
716    
717                    List<SocialActivityCounter> activityCounters =
718                            socialActivityCounterPersistence.findByC_C(
719                                    assetEntry.getClassNameId(), classPK);
720    
721                    adjustUserContribution(assetEntry, true);
722    
723                    for (SocialActivityCounter activityCounter : activityCounters) {
724                            if (!activityCounter.isActive()) {
725                                    activityCounter.setActive(true);
726    
727                                    socialActivityCounterPersistence.update(activityCounter);
728                            }
729                    }
730    
731                    clearFinderCache();
732            }
733    
734            /**
735             * Returns the activity counter with the given name, owner, and end period
736             * that belong to the given entity.
737             *
738             * @param  groupId the primary key of the group
739             * @param  classNameId the primary key of the entity's class
740             * @param  classPK the primary key of the entity
741             * @param  name the counter name
742             * @param  ownerType the owner type
743             * @param  endPeriod the end period, <code>-1</code> for the latest one
744             * @return the matching activity counter
745             */
746            @Override
747            public SocialActivityCounter fetchActivityCounterByEndPeriod(
748                    long groupId, long classNameId, long classPK, String name,
749                    int ownerType, int endPeriod) {
750    
751                    return socialActivityCounterPersistence.fetchByG_C_C_N_O_E(
752                            groupId, classNameId, classPK, name, ownerType, endPeriod);
753            }
754    
755            /**
756             * Returns the activity counter with the given name, owner, and start period
757             * that belong to the given entity.
758             *
759             * @param  groupId the primary key of the group
760             * @param  classNameId the primary key of the entity's class
761             * @param  classPK the primary key of the entity
762             * @param  name the counter name
763             * @param  ownerType the owner type
764             * @param  startPeriod the start period
765             * @return the matching activity counter
766             */
767            @Override
768            public SocialActivityCounter fetchActivityCounterByStartPeriod(
769                    long groupId, long classNameId, long classPK, String name,
770                    int ownerType, int startPeriod) {
771    
772                    return socialActivityCounterPersistence.fetchByG_C_C_N_O_S(
773                            groupId, classNameId, classPK, name, ownerType, startPeriod);
774            }
775    
776            /**
777             * Returns the latest activity counter with the given name and owner that
778             * belong to the given entity.
779             *
780             * @param  groupId the primary key of the group
781             * @param  classNameId the primary key of the entity's class
782             * @param  classPK the primary key of the entity
783             * @param  name the counter name
784             * @param  ownerType the owner type
785             * @return the matching activity counter
786             */
787            @Override
788            public SocialActivityCounter fetchLatestActivityCounter(
789                    long groupId, long classNameId, long classPK, String name,
790                    int ownerType) {
791    
792                    return socialActivityCounterPersistence.fetchByG_C_C_N_O_E(
793                            groupId, classNameId, classPK, name, ownerType,
794                            SocialActivityCounterConstants.END_PERIOD_UNDEFINED);
795            }
796    
797            /**
798             * Returns all the activity counters with the given name and period offsets.
799             *
800             * <p>
801             * The start and end offsets can belong to different periods. This method
802             * groups the counters by name and returns the sum of their current values.
803             * </p>
804             *
805             * @param  groupId the primary key of the group
806             * @param  name the counter name
807             * @param  startOffset the offset for the start period
808             * @param  endOffset the offset for the end period
809             * @return the matching activity counters
810             */
811            @Override
812            public List<SocialActivityCounter> getOffsetActivityCounters(
813                    long groupId, String name, int startOffset, int endOffset) {
814    
815                    int startPeriod = SocialCounterPeriodUtil.getStartPeriod(startOffset);
816                    int endPeriod = SocialCounterPeriodUtil.getEndPeriod(endOffset);
817    
818                    return getPeriodActivityCounters(groupId, name, startPeriod, endPeriod);
819            }
820    
821            /**
822             * Returns the distribution of the activity counters with the given name and
823             * period offsets.
824             *
825             * <p>
826             * The start and end offsets can belong to different periods. This method
827             * groups the counters by their owner entity (usually some asset) and
828             * returns a counter for each entity class with the sum of the counters'
829             * current values.
830             * </p>
831             *
832             * @param  groupId the primary key of the group
833             * @param  name the counter name
834             * @param  startOffset the offset for the start period
835             * @param  endOffset the offset for the end period
836             * @return the distribution of matching activity counters
837             */
838            @Override
839            public List<SocialActivityCounter> getOffsetDistributionActivityCounters(
840                    long groupId, String name, int startOffset, int endOffset) {
841    
842                    int startPeriod = SocialCounterPeriodUtil.getStartPeriod(startOffset);
843                    int endPeriod = SocialCounterPeriodUtil.getEndPeriod(endOffset);
844    
845                    return getPeriodDistributionActivityCounters(
846                            groupId, name, startPeriod, endPeriod);
847            }
848    
849            /**
850             * Returns all the activity counters with the given name and time period.
851             *
852             * <p>
853             * The start and end period values can belong to different periods. This
854             * method groups the counters by name and returns the sum of their current
855             * values.
856             * </p>
857             *
858             * @param  groupId the primary key of the group
859             * @param  name the counter name
860             * @param  startPeriod the start period
861             * @param  endPeriod the end period
862             * @return the matching activity counters
863             */
864            @Override
865            public List<SocialActivityCounter> getPeriodActivityCounters(
866                    long groupId, String name, int startPeriod, int endPeriod) {
867    
868                    if (endPeriod == SocialActivityCounterConstants.END_PERIOD_UNDEFINED) {
869                            endPeriod = SocialCounterPeriodUtil.getEndPeriod();
870                    }
871    
872                    int offset = SocialCounterPeriodUtil.getOffset(endPeriod);
873    
874                    int periodLength = SocialCounterPeriodUtil.getPeriodLength(offset);
875    
876                    return socialActivityCounterFinder.findAC_ByG_N_S_E_1(
877                            groupId, name, startPeriod, endPeriod, periodLength);
878            }
879    
880            /**
881             * Returns the distribution of activity counters with the given name and
882             * time period.
883             *
884             * <p>
885             * The start and end period values can belong to different periods. This
886             * method groups the counters by their owner entity (usually some asset) and
887             * returns a counter for each entity class with the sum of the counters'
888             * current values.
889             * </p>
890             *
891             * @param  groupId the primary key of the group
892             * @param  name the counter name
893             * @param  startPeriod the start period
894             * @param  endPeriod the end period
895             * @return the distribution of matching activity counters
896             */
897            @Override
898            public List<SocialActivityCounter> getPeriodDistributionActivityCounters(
899                    long groupId, String name, int startPeriod, int endPeriod) {
900    
901                    int offset = SocialCounterPeriodUtil.getOffset(endPeriod);
902    
903                    int periodLength = SocialCounterPeriodUtil.getPeriodLength(offset);
904    
905                    return socialActivityCounterFinder.findAC_ByG_N_S_E_2(
906                            groupId, name, startPeriod, endPeriod, periodLength);
907            }
908    
909            /**
910             * Returns the range of tuples that contain users and a list of activity
911             * counters.
912             *
913             * <p>
914             * The counters returned for each user are passed to this method in the
915             * selectedNames array. The method also accepts an array of counter names
916             * that are used to rank the users.
917             * </p>
918             *
919             * <p>
920             * Useful when paginating results. Returns a maximum of <code>end -
921             * start</code> instances. <code>start</code> and <code>end</code> are not
922             * primary keys, they are indexes in the result set. Thus, <code>0</code>
923             * refers to the first result in the set. Setting both <code>start</code>
924             * and <code>end</code> to {@link
925             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
926             * result set.
927             * </p>
928             *
929             * @param  groupId the primary key of the group
930             * @param  rankingNames the ranking counter names
931             * @param  selectedNames the counter names that will be returned with each
932             *         user
933             * @param  start the lower bound of the range of results
934             * @param  end the upper bound of the range of results (not inclusive)
935             * @return the range of matching tuples
936             */
937            @Override
938            public List<Tuple> getUserActivityCounters(
939                    long groupId, String[] rankingNames, String[] selectedNames, int start,
940                    int end) {
941    
942                    List<Long> userIds = socialActivityCounterFinder.findU_ByG_N(
943                            groupId, rankingNames, start, end);
944    
945                    if (userIds.isEmpty()) {
946                            return Collections.emptyList();
947                    }
948    
949                    Tuple[] userActivityCounters = new Tuple[userIds.size()];
950    
951                    List<SocialActivityCounter> activityCounters =
952                            socialActivityCounterFinder.findAC_By_G_C_C_N_S_E(
953                                    groupId, userIds, selectedNames, QueryUtil.ALL_POS,
954                                    QueryUtil.ALL_POS);
955    
956                    long userId = 0;
957                    Map<String, SocialActivityCounter> activityCountersMap = null;
958    
959                    for (SocialActivityCounter activityCounter : activityCounters) {
960                            if (userId != activityCounter.getClassPK()) {
961                                    userId = activityCounter.getClassPK();
962                                    activityCountersMap = new HashMap<>();
963    
964                                    Tuple userActivityCounter = new Tuple(
965                                            userId, activityCountersMap);
966    
967                                    for (int i = 0; i < userIds.size(); i++) {
968                                            long curUserId = userIds.get(i);
969    
970                                            if (userId == curUserId) {
971                                                    userActivityCounters[i] = userActivityCounter;
972    
973                                                    break;
974                                            }
975                                    }
976                            }
977    
978                            activityCountersMap.put(activityCounter.getName(), activityCounter);
979                    }
980    
981                    return Arrays.asList(userActivityCounters);
982            }
983    
984            /**
985             * Returns the number of users having a rank based on the given counters.
986             *
987             * @param  groupId the primary key of the group
988             * @param  rankingNames the ranking counter names
989             * @return the number of matching users
990             */
991            @Override
992            public int getUserActivityCountersCount(
993                    long groupId, String[] rankingNames) {
994    
995                    return socialActivityCounterFinder.countU_ByG_N(groupId, rankingNames);
996            }
997    
998            /**
999             * Increments the <code>user.achievements</code> counter for a user.
1000             *
1001             * <p>
1002             * This method should be used by an external achievement class when the
1003             * users unlocks an achievement.
1004             * </p>
1005             *
1006             * @param  userId the primary key of the user
1007             * @param  groupId the primary key of the group
1008             * @throws PortalException if the group or an expected previous activity
1009             *         counter could not be found
1010             */
1011            @Override
1012            public void incrementUserAchievementCounter(long userId, long groupId)
1013                    throws PortalException {
1014    
1015                    User user = userPersistence.findByPrimaryKey(userId);
1016    
1017                    SocialActivityCounter activityCounter = addActivityCounter(
1018                            groupId, user, new SocialActivityImpl(),
1019                            _userAchievementsActivityCounterDefinition);
1020    
1021                    incrementActivityCounter(
1022                            activityCounter, _userAchievementsActivityCounterDefinition);
1023            }
1024    
1025            protected SocialActivityCounter addActivityCounter(
1026                            final long groupId, final User user, final SocialActivity activity,
1027                            final SocialActivityCounterDefinition activityCounterDefinition)
1028                    throws PortalException {
1029    
1030                    int ownerType = activityCounterDefinition.getOwnerType();
1031    
1032                    long classNameId = getClassNameId(activity.getAssetEntry(), ownerType);
1033                    long classPK = getClassPK(user, activity.getAssetEntry(), ownerType);
1034    
1035                    SocialActivityCounter activityCounter = fetchLatestActivityCounter(
1036                            groupId, classNameId, classPK, activityCounterDefinition.getName(),
1037                            ownerType);
1038    
1039                    if (activityCounter == null) {
1040                            activityCounter = lockProtectedAddActivityCounter(
1041                                    groupId, classNameId, classPK,
1042                                    activityCounterDefinition.getName(), ownerType, 0, 0,
1043                                    activityCounterDefinition.getPeriodLength());
1044                    }
1045                    else if (!activityCounter.isActivePeriod(
1046                                            activityCounterDefinition.getPeriodLength())) {
1047    
1048                            activityCounter = lockProtectedAddActivityCounter(
1049                                    groupId, classNameId, classPK,
1050                                    activityCounterDefinition.getName(), ownerType,
1051                                    activityCounter.getTotalValue(),
1052                                    activityCounter.getActivityCounterId(),
1053                                    activityCounterDefinition.getPeriodLength());
1054                    }
1055    
1056                    if (activityCounterDefinition.getLimitValue() > 0) {
1057                            SocialActivityLimit activityLimit =
1058                                    socialActivityLimitPersistence.fetchByG_U_C_C_A_A(
1059                                            groupId, user.getUserId(), activity.getClassNameId(),
1060                                            getLimitClassPK(activity, activityCounterDefinition),
1061                                            activity.getType(), activityCounterDefinition.getName());
1062    
1063                            if (activityLimit == null) {
1064                                    lockProtectedGetActivityLimit(
1065                                            groupId, user, activity, activityCounterDefinition);
1066                            }
1067                    }
1068    
1069                    return activityCounter;
1070            }
1071    
1072            protected SocialActivityCounter addAssetActivitiesCounter(
1073                            SocialActivity activity)
1074                    throws PortalException {
1075    
1076                    User user = userPersistence.findByPrimaryKey(activity.getUserId());
1077    
1078                    return addActivityCounter(
1079                            activity.getGroupId(), user, activity,
1080                            _assetActivitiesActivityCounterDefinition);
1081            }
1082    
1083            protected SocialActivityCounter addUserActivitiesCounter(
1084                            SocialActivity activity)
1085                    throws PortalException {
1086    
1087                    User user = userPersistence.findByPrimaryKey(activity.getUserId());
1088    
1089                    return addActivityCounter(
1090                            activity.getGroupId(), user, activity,
1091                            _userActivitiesActivityCounterDefinition);
1092            }
1093    
1094            protected void adjustUserContribution(AssetEntry assetEntry, boolean enable)
1095                    throws PortalException {
1096    
1097                    if (assetEntry == null) {
1098                            return;
1099                    }
1100    
1101                    SocialActivityCounter latestPopularityActivityCounter =
1102                            fetchLatestActivityCounter(
1103                                    assetEntry.getGroupId(), assetEntry.getClassNameId(),
1104                                    assetEntry.getClassPK(),
1105                                    SocialActivityCounterConstants.NAME_POPULARITY,
1106                                    SocialActivityCounterConstants.TYPE_ASSET);
1107    
1108                    if ((latestPopularityActivityCounter == null) ||
1109                            (enable && latestPopularityActivityCounter.isActive()) ||
1110                            (!enable && !latestPopularityActivityCounter.isActive())) {
1111    
1112                            return;
1113                    }
1114    
1115                    int factor = -1;
1116    
1117                    if (enable) {
1118                            factor = 1;
1119                    }
1120    
1121                    SocialActivityCounter latestContributionActivityCounter =
1122                            fetchLatestActivityCounter(
1123                                    assetEntry.getGroupId(),
1124                                    classNameLocalService.getClassNameId(User.class.getName()),
1125                                    assetEntry.getUserId(),
1126                                    SocialActivityCounterConstants.NAME_CONTRIBUTION,
1127                                    SocialActivityCounterConstants.TYPE_CREATOR);
1128    
1129                    if (latestContributionActivityCounter == null) {
1130                            return;
1131                    }
1132    
1133                    int startPeriod = SocialCounterPeriodUtil.getStartPeriod();
1134    
1135                    if (latestContributionActivityCounter.getStartPeriod() != startPeriod) {
1136                            latestContributionActivityCounter = addActivityCounter(
1137                                    latestContributionActivityCounter.getGroupId(),
1138                                    latestContributionActivityCounter.getClassNameId(),
1139                                    latestContributionActivityCounter.getClassPK(),
1140                                    latestContributionActivityCounter.getName(),
1141                                    latestContributionActivityCounter.getOwnerType(), 0,
1142                                    latestContributionActivityCounter.getTotalValue(),
1143                                    SocialCounterPeriodUtil.getStartPeriod(),
1144                                    SocialActivityCounterConstants.END_PERIOD_UNDEFINED,
1145                                    latestContributionActivityCounter.getActivityCounterId(),
1146                                    SocialActivityCounterConstants.PERIOD_LENGTH_SYSTEM);
1147                    }
1148    
1149                    if (latestPopularityActivityCounter.getStartPeriod() == startPeriod) {
1150                            latestContributionActivityCounter.setCurrentValue(
1151                                    latestContributionActivityCounter.getCurrentValue() +
1152                                            (latestPopularityActivityCounter.getCurrentValue() *
1153                                                    factor));
1154                    }
1155    
1156                    latestContributionActivityCounter.setTotalValue(
1157                            latestContributionActivityCounter.getTotalValue() +
1158                                    (latestPopularityActivityCounter.getTotalValue() * factor));
1159    
1160                    socialActivityCounterPersistence.update(
1161                            latestContributionActivityCounter);
1162            }
1163    
1164            protected boolean checkActivityLimit(
1165                            User user, SocialActivity activity,
1166                            SocialActivityCounterDefinition activityCounterDefinition)
1167                    throws PortalException {
1168    
1169                    if (activityCounterDefinition.getLimitValue() == 0) {
1170                            return true;
1171                    }
1172    
1173                    long classPK = activity.getClassPK();
1174    
1175                    String name = activityCounterDefinition.getName();
1176    
1177                    if (name.equals(SocialActivityCounterConstants.NAME_PARTICIPATION)) {
1178                            classPK = 0;
1179                    }
1180    
1181                    SocialActivityLimit activityLimit =
1182                            socialActivityLimitPersistence.findByG_U_C_C_A_A(
1183                                    activity.getGroupId(), user.getUserId(),
1184                                    activity.getClassNameId(), classPK, activity.getType(), name);
1185    
1186                    int count = activityLimit.getCount(
1187                            activityCounterDefinition.getLimitPeriod());
1188    
1189                    if (count < activityCounterDefinition.getLimitValue()) {
1190                            activityLimit.setCount(
1191                                    activityCounterDefinition.getLimitPeriod(), count + 1);
1192    
1193                            socialActivityLimitPersistence.update(activityLimit);
1194    
1195                            return true;
1196                    }
1197    
1198                    return false;
1199            }
1200    
1201            protected void clearFinderCache() {
1202                    PortalCache<String, SocialActivityCounter> portalCache =
1203                            MultiVMPoolUtil.getCache(
1204                                    SocialActivityCounterFinder.class.getName());
1205    
1206                    portalCache.removeAll();
1207            }
1208    
1209            protected long getClassNameId(AssetEntry assetEntry, int ownerType) {
1210                    if (ownerType == SocialActivityCounterConstants.TYPE_ASSET) {
1211                            return assetEntry.getClassNameId();
1212                    }
1213    
1214                    return classNameLocalService.getClassNameId(User.class.getName());
1215            }
1216    
1217            protected long getClassPK(User user, AssetEntry assetEntry, int ownerType) {
1218                    if (ownerType == SocialActivityCounterConstants.TYPE_ACTOR) {
1219                            return user.getUserId();
1220                    }
1221    
1222                    if (ownerType == SocialActivityCounterConstants.TYPE_ASSET) {
1223                            return assetEntry.getClassPK();
1224                    }
1225    
1226                    return assetEntry.getUserId();
1227            }
1228    
1229            protected long getLimitClassPK(
1230                    SocialActivity activity,
1231                    SocialActivityCounterDefinition activityCounterDefinition) {
1232    
1233                    String name = activityCounterDefinition.getName();
1234    
1235                    if (name.equals(SocialActivityCounterConstants.NAME_PARTICIPATION)) {
1236                            return 0;
1237                    }
1238    
1239                    return activity.getClassPK();
1240            }
1241    
1242            protected void incrementActivityCounter(
1243                    SocialActivityCounter activityCounter,
1244                    SocialActivityCounterDefinition activityCounterDefinition) {
1245    
1246                    activityCounter.setCurrentValue(
1247                            activityCounter.getCurrentValue() +
1248                                    activityCounterDefinition.getIncrement());
1249                    activityCounter.setTotalValue(
1250                            activityCounter.getTotalValue() +
1251                                    activityCounterDefinition.getIncrement());
1252    
1253                    socialActivityCounterPersistence.update(activityCounter);
1254    
1255                    socialActivityCounterPersistence.clearCache(activityCounter);
1256            }
1257    
1258            protected boolean isAddActivityCounter(
1259                    User user, User assetEntryUser, AssetEntry assetEntry,
1260                    SocialActivityCounterDefinition activityCounterDefinition) {
1261    
1262                    if ((user.isDefaultUser() || !user.isActive()) &&
1263                            (activityCounterDefinition.getOwnerType() !=
1264                                    SocialActivityCounterConstants.TYPE_ASSET)) {
1265    
1266                            return false;
1267                    }
1268    
1269                    if ((assetEntryUser.isDefaultUser() || !assetEntryUser.isActive()) &&
1270                            (activityCounterDefinition.getOwnerType() !=
1271                                    SocialActivityCounterConstants.TYPE_ACTOR)) {
1272    
1273                            return false;
1274                    }
1275    
1276                    if (!activityCounterDefinition.isEnabled() ||
1277                            (activityCounterDefinition.getIncrement() == 0)) {
1278    
1279                            return false;
1280                    }
1281    
1282                    String name = activityCounterDefinition.getName();
1283    
1284                    if ((user.getUserId() == assetEntryUser.getUserId()) &&
1285                            (name.equals(SocialActivityCounterConstants.NAME_CONTRIBUTION) ||
1286                             name.equals(SocialActivityCounterConstants.NAME_POPULARITY))) {
1287    
1288                            return false;
1289                    }
1290    
1291                    if ((activityCounterDefinition.getOwnerType() ==
1292                                    SocialActivityCounterConstants.TYPE_ASSET) &&
1293                            !assetEntry.isVisible()) {
1294    
1295                            return false;
1296                    }
1297    
1298                    return true;
1299            }
1300    
1301            protected SocialActivityCounter lockProtectedAddActivityCounter(
1302                            final long groupId, final long classNameId, final long classPK,
1303                            final String name, final int ownerType, final int totalValue,
1304                            final long previousActivityCounterId, final int periodLength)
1305                    throws PortalException {
1306    
1307                    String lockKey = StringUtil.merge(
1308                            new Object[] {groupId, classNameId, classPK, name, ownerType},
1309                            StringPool.POUND);
1310    
1311                    LockProtectedAction<SocialActivityCounter> lockProtectedAction =
1312                            new LockProtectedAction<SocialActivityCounter>(
1313                                    SocialActivityCounter.class, lockKey,
1314                                    PropsValues.SOCIAL_ACTIVITY_LOCK_TIMEOUT,
1315                                    PropsValues.SOCIAL_ACTIVITY_LOCK_RETRY_DELAY) {
1316    
1317                            @Override
1318                            protected SocialActivityCounter performProtectedAction()
1319                                    throws PortalException {
1320    
1321                                    SocialActivityCounter activityCounter =
1322                                            socialActivityCounterLocalService.addActivityCounter(
1323                                                    groupId, classNameId, classPK, name, ownerType,
1324                                                    totalValue, previousActivityCounterId, periodLength);
1325    
1326                                    return activityCounter;
1327                            }
1328    
1329                    };
1330    
1331                    lockProtectedAction.performAction();
1332    
1333                    return lockProtectedAction.getReturnValue();
1334            }
1335    
1336            protected void lockProtectedGetActivityLimit(
1337                            final long groupId, final User user, final SocialActivity activity,
1338                            final SocialActivityCounterDefinition activityCounterDefinition)
1339                    throws PortalException {
1340    
1341                    final long classPK = getLimitClassPK(
1342                            activity, activityCounterDefinition);
1343    
1344                    String lockKey = StringUtil.merge(
1345                            new Object[] {
1346                                    groupId, user.getUserId(), activity.getClassNameId(), classPK,
1347                                    activity.getType(), activityCounterDefinition.getName()
1348                            },
1349                            StringPool.POUND);
1350    
1351                    LockProtectedAction<SocialActivityLimit> lockProtectedAction =
1352                            new LockProtectedAction<SocialActivityLimit>(
1353                                    SocialActivityLimit.class, lockKey,
1354                                    PropsValues.SOCIAL_ACTIVITY_LOCK_TIMEOUT,
1355                                    PropsValues.SOCIAL_ACTIVITY_LOCK_RETRY_DELAY) {
1356    
1357                            @Override
1358                            protected SocialActivityLimit performProtectedAction()
1359                                    throws PortalException {
1360    
1361                                    SocialActivityLimit activityLimit =
1362                                            socialActivityLimitPersistence.fetchByG_U_C_C_A_A(
1363                                                    groupId, user.getUserId(), activity.getClassNameId(),
1364                                                    classPK, activity.getType(),
1365                                                    activityCounterDefinition.getName());
1366    
1367                                    if (activityLimit == null) {
1368                                            activityLimit =
1369                                                    socialActivityLimitLocalService.addActivityLimit(
1370                                                            user.getUserId(), activity.getGroupId(),
1371                                                            activity.getClassNameId(), classPK,
1372                                                            activity.getType(),
1373                                                            activityCounterDefinition.getName(),
1374                                                            activityCounterDefinition.getLimitPeriod());
1375                                    }
1376    
1377                                    return activityLimit;
1378                            }
1379                    };
1380    
1381                    lockProtectedAction.performAction();
1382    
1383                    socialActivityLimitPersistence.cacheResult(
1384                            lockProtectedAction.getReturnValue());
1385            }
1386    
1387            private final SocialActivityCounterDefinition
1388                    _assetActivitiesActivityCounterDefinition =
1389                            new SocialActivityCounterDefinition(
1390                                    SocialActivityCounterConstants.NAME_ASSET_ACTIVITIES,
1391                                    SocialActivityCounterConstants.TYPE_ASSET);
1392            private final SocialActivityCounterDefinition
1393                    _userAchievementsActivityCounterDefinition =
1394                            new SocialActivityCounterDefinition(
1395                                    SocialActivityCounterConstants.NAME_USER_ACHIEVEMENTS,
1396                                    SocialActivityCounterConstants.TYPE_ACTOR);
1397            private final SocialActivityCounterDefinition
1398                    _userActivitiesActivityCounterDefinition =
1399                            new SocialActivityCounterDefinition(
1400                                    SocialActivityCounterConstants.NAME_USER_ACTIVITIES,
1401                                    SocialActivityCounterConstants.TYPE_ACTOR);
1402    
1403    }