001
014
015 package com.liferay.portlet.social.service.impl;
016
017 import com.liferay.portal.kernel.dao.orm.QueryUtil;
018 import com.liferay.portal.kernel.exception.PortalException;
019 import com.liferay.portal.kernel.exception.SystemException;
020 import com.liferay.portal.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022 import com.liferay.portal.kernel.transaction.Propagation;
023 import com.liferay.portal.kernel.transaction.Transactional;
024 import com.liferay.portal.kernel.util.PropsKeys;
025 import com.liferay.portal.kernel.util.StringBundler;
026 import com.liferay.portal.kernel.util.StringPool;
027 import com.liferay.portal.kernel.util.StringUtil;
028 import com.liferay.portal.kernel.util.Tuple;
029 import com.liferay.portal.model.Group;
030 import com.liferay.portal.model.Lock;
031 import com.liferay.portal.model.User;
032 import com.liferay.portal.util.PortalUtil;
033 import com.liferay.portal.util.PropsValues;
034 import com.liferay.portlet.asset.model.AssetEntry;
035 import com.liferay.portlet.social.model.SocialAchievement;
036 import com.liferay.portlet.social.model.SocialActivity;
037 import com.liferay.portlet.social.model.SocialActivityCounter;
038 import com.liferay.portlet.social.model.SocialActivityCounterConstants;
039 import com.liferay.portlet.social.model.SocialActivityCounterDefinition;
040 import com.liferay.portlet.social.model.SocialActivityDefinition;
041 import com.liferay.portlet.social.model.SocialActivityLimit;
042 import com.liferay.portlet.social.model.SocialActivityProcessor;
043 import com.liferay.portlet.social.service.SocialActivityCounterLocalService;
044 import com.liferay.portlet.social.service.base.SocialActivityCounterLocalServiceBaseImpl;
045 import com.liferay.portlet.social.service.persistence.SocialActivityCounterFinderUtil;
046 import com.liferay.portlet.social.util.SocialCounterPeriodUtil;
047
048 import java.util.Arrays;
049 import java.util.Collections;
050 import java.util.Date;
051 import java.util.HashMap;
052 import java.util.List;
053 import java.util.Map;
054
055
059 public class SocialActivityCounterLocalServiceImpl
060 extends SocialActivityCounterLocalServiceBaseImpl {
061
062 public SocialActivityCounter addActivityCounter(
063 long groupId, long classNameId, long classPK, String name,
064 int ownerType, int currentValue, int totalValue, int startPeriod,
065 int endPeriod)
066 throws PortalException, SystemException {
067
068 SocialActivityCounter activityCounter = null;
069
070 String lockKey = getLockKey(
071 groupId, classNameId, classPK, name, ownerType);
072
073 Lock lock = null;
074
075 while (true) {
076 try {
077 lock = lockLocalService.lock(
078 SocialActivityCounter.class.getName(), lockKey, lockKey,
079 false);
080 }
081 catch (Exception e) {
082 if (_log.isWarnEnabled()) {
083 _log.warn(
084 "Unable to acquire activity counter lock. Retrying.");
085 }
086
087 continue;
088 }
089
090 if (lock.isNew()) {
091 try {
092 activityCounter =
093 socialActivityCounterLocalService.createActivityCounter(
094 groupId, classNameId, classPK, name, ownerType,
095 currentValue, totalValue, startPeriod, endPeriod);
096 }
097 finally {
098 lockLocalService.unlock(
099 SocialActivityCounter.class.getName(), lockKey, lockKey,
100 false);
101 }
102
103 break;
104 }
105
106 Date createDate = lock.getCreateDate();
107
108 if ((System.currentTimeMillis() - createDate.getTime()) >=
109 PropsValues.SOCIAL_ACTIVITY_COUNTER_LOCK_TIMEOUT) {
110
111 lockLocalService.unlock(
112 SocialActivityCounter.class.getName(), lockKey,
113 lock.getOwner(), false);
114
115 if (_log.isWarnEnabled()) {
116 _log.warn(
117 "Forcibly removed lock " + lock + ". See " +
118 PropsKeys.SOCIAL_ACTIVITY_COUNTER_LOCK_TIMEOUT);
119 }
120 }
121 else {
122 try {
123 Thread.sleep(
124 PropsValues.SOCIAL_ACTIVITY_COUNTER_LOCK_RETRY_DELAY);
125 }
126 catch (InterruptedException ie) {
127 if (_log.isWarnEnabled()) {
128 _log.warn(
129 "Interrupted while waiting to reacquire lock", ie);
130 }
131 }
132 }
133 }
134
135 return activityCounter;
136 }
137
138 public void addActivityCounters(SocialActivity activity)
139 throws PortalException, SystemException {
140
141 if (!socialActivitySettingLocalService.isEnabled(
142 activity.getGroupId(), activity.getClassNameId())) {
143
144 return;
145 }
146
147 User user = userPersistence.findByPrimaryKey(activity.getUserId());
148
149 SocialActivityDefinition activityDefinition =
150 socialActivitySettingLocalService.getActivityDefinition(
151 activity.getGroupId(), activity.getClassName(),
152 activity.getType());
153
154 if ((activityDefinition == null) || !activityDefinition.isEnabled()) {
155 return;
156 }
157
158 SocialActivityProcessor activityProcessor =
159 activityDefinition.getActivityProcessor();
160
161 if (activityProcessor != null) {
162 activityProcessor.processActivity(activity);
163 }
164
165 AssetEntry assetEntry = activity.getAssetEntry();
166
167 User assetEntryUser = userPersistence.findByPrimaryKey(
168 assetEntry.getUserId());
169
170 for (SocialActivityCounterDefinition activityCounterDefinition :
171 activityDefinition.getActivityCounterDefinitions()) {
172
173 if (addActivityCounter(
174 user, assetEntryUser, activityCounterDefinition) &&
175 checkActivityLimit(user, activity, activityCounterDefinition)) {
176
177 incrementActivityCounter(
178 activity.getGroupId(), user, activity.getAssetEntry(),
179 activityCounterDefinition);
180 }
181 }
182
183 for (SocialAchievement achievement :
184 activityDefinition.getAchievements()) {
185
186 achievement.processActivity(activity);
187 }
188
189 if (!user.isDefaultUser() && user.isActive()) {
190 incrementActivityCounter(
191 activity.getGroupId(),
192 PortalUtil.getClassNameId(User.class.getName()),
193 activity.getUserId(),
194 SocialActivityCounterConstants.NAME_USER_ACTIVITIES,
195 SocialActivityCounterConstants.TYPE_ACTOR, 1,
196 SocialActivityCounterConstants.PERIOD_LENGTH_SYSTEM);
197 }
198
199 if (!assetEntryUser.isDefaultUser() && assetEntryUser.isActive()) {
200 incrementActivityCounter(
201 activity.getGroupId(), activity.getClassNameId(),
202 activity.getClassPK(),
203 SocialActivityCounterConstants.NAME_ASSET_ACTIVITIES,
204 SocialActivityCounterConstants.TYPE_ASSET, 1,
205 SocialActivityCounterConstants.PERIOD_LENGTH_SYSTEM);
206 }
207 }
208
209 @Transactional(propagation = Propagation.REQUIRES_NEW)
210 public SocialActivityCounter createActivityCounter(
211 long groupId, long classNameId, long classPK, String name,
212 int ownerType, int currentValue, int totalValue, int startPeriod,
213 int endPeriod)
214 throws PortalException, SystemException {
215
216 SocialActivityCounter activityCounter =
217 socialActivityCounterPersistence.fetchByG_C_C_N_O_E(
218 groupId, classNameId, classPK, name, ownerType, endPeriod,
219 false);
220
221 if (activityCounter != null) {
222 return activityCounter;
223 }
224
225 Group group = groupPersistence.findByPrimaryKey(groupId);
226
227 long activityCounterId = counterLocalService.increment();
228
229 activityCounter = socialActivityCounterPersistence.create(
230 activityCounterId);
231
232 activityCounter.setGroupId(groupId);
233 activityCounter.setCompanyId(group.getCompanyId());
234 activityCounter.setClassNameId(classNameId);
235 activityCounter.setClassPK(classPK);
236 activityCounter.setName(name);
237 activityCounter.setOwnerType(ownerType);
238 activityCounter.setCurrentValue(currentValue);
239 activityCounter.setTotalValue(totalValue);
240 activityCounter.setStartPeriod(startPeriod);
241 activityCounter.setEndPeriod(endPeriod);
242
243 socialActivityCounterPersistence.update(activityCounter, false);
244
245 return activityCounter;
246 }
247
248 public void deleteActivityCounters(AssetEntry assetEntry)
249 throws PortalException, SystemException {
250
251 if (assetEntry == null) {
252 return;
253 }
254
255 SocialActivityCounter latestContributionActivityCounter =
256 fetchLatestActivityCounter(
257 assetEntry.getGroupId(),
258 PortalUtil.getClassNameId(User.class.getName()),
259 assetEntry.getUserId(),
260 SocialActivityCounterConstants.NAME_CONTRIBUTION,
261 SocialActivityCounterConstants.TYPE_CREATOR);
262
263 SocialActivityCounter latestPopularityActivityCounter =
264 fetchLatestActivityCounter(
265 assetEntry.getGroupId(), assetEntry.getClassNameId(),
266 assetEntry.getClassPK(),
267 SocialActivityCounterConstants.NAME_POPULARITY,
268 SocialActivityCounterConstants.TYPE_ASSET);
269
270 if ((latestContributionActivityCounter != null) &&
271 (latestPopularityActivityCounter != null)) {
272
273 int startPeriod = SocialCounterPeriodUtil.getStartPeriod();
274
275 if (latestContributionActivityCounter.getStartPeriod() !=
276 startPeriod) {
277
278 latestContributionActivityCounter = addNewPeriod(
279 latestContributionActivityCounter,
280 SocialActivityCounterConstants.PERIOD_LENGTH_SYSTEM);
281 }
282
283 if (latestPopularityActivityCounter.getStartPeriod() ==
284 startPeriod) {
285
286 latestContributionActivityCounter.setCurrentValue(
287 latestContributionActivityCounter.getCurrentValue() -
288 latestPopularityActivityCounter.getCurrentValue());
289 }
290
291 latestContributionActivityCounter.setTotalValue(
292 latestContributionActivityCounter.getTotalValue() -
293 latestPopularityActivityCounter.getTotalValue());
294
295 socialActivityCounterPersistence.update(
296 latestContributionActivityCounter, false);
297 }
298
299 deleteActivityCounters(
300 assetEntry.getClassNameId(), assetEntry.getClassPK());
301
302 socialActivityLimitPersistence.removeByC_C(
303 assetEntry.getClassNameId(), assetEntry.getClassPK());
304 }
305
306 public void deleteActivityCounters(long classNameId, long classPK)
307 throws SystemException {
308
309 socialActivityCounterPersistence.removeByC_C(classNameId, classPK);
310 }
311
312 public SocialActivityCounter fetchActivityCounterByEndPeriod(
313 long groupId, long classNameId, long classPK, String name,
314 int ownerType, int endPeriod)
315 throws SystemException {
316
317 return socialActivityCounterPersistence.fetchByG_C_C_N_O_E(
318 groupId, classNameId, classPK, name, ownerType, endPeriod);
319 }
320
321 public SocialActivityCounter fetchActivityCounterByStartPeriod(
322 long groupId, long classNameId, long classPK, String name,
323 int ownerType, int startPeriod)
324 throws SystemException {
325
326 return socialActivityCounterPersistence.fetchByG_C_C_N_O_S(
327 groupId, classNameId, classPK, name, ownerType, startPeriod);
328 }
329
330 public SocialActivityCounter fetchLatestActivityCounter(
331 long groupId, long classNameId, long classPK, String name,
332 int ownerType)
333 throws SystemException {
334
335 return socialActivityCounterPersistence.fetchByG_C_C_N_O_E(
336 groupId, classNameId, classPK, name, ownerType,
337 SocialActivityCounterConstants.END_PERIOD_UNDEFINED);
338 }
339
340 public List<SocialActivityCounter> getOffsetActivityCounters(
341 long groupId, String name, int startOffset, int endOffset)
342 throws SystemException {
343
344 int startPeriod = SocialCounterPeriodUtil.getStartPeriod(startOffset);
345 int endPeriod = SocialCounterPeriodUtil.getEndPeriod(endOffset);
346
347 return getPeriodActivityCounters(groupId, name, startPeriod, endPeriod);
348 }
349
350 public List<SocialActivityCounter> getOffsetDistributionActivityCounters(
351 long groupId, String name, int startOffset, int endOffset)
352 throws SystemException {
353
354 int startPeriod = SocialCounterPeriodUtil.getStartPeriod(startOffset);
355 int endPeriod = SocialCounterPeriodUtil.getEndPeriod(endOffset);
356
357 return getPeriodDistributionActivityCounters(
358 groupId, name, startPeriod, endPeriod);
359 }
360
361 public List<SocialActivityCounter> getPeriodActivityCounters(
362 long groupId, String name, int startPeriod, int endPeriod)
363 throws SystemException {
364
365 int offset = SocialCounterPeriodUtil.getOffset(endPeriod);
366
367 int periodLength = SocialCounterPeriodUtil.getPeriodLength(offset);
368
369 return socialActivityCounterFinder.findAC_ByG_N_S_E_1(
370 groupId, name, startPeriod, endPeriod, periodLength);
371 }
372
373 public List<SocialActivityCounter> getPeriodDistributionActivityCounters(
374 long groupId, String name, int startPeriod, int endPeriod)
375 throws SystemException {
376
377 int offset = SocialCounterPeriodUtil.getOffset(endPeriod);
378
379 int periodLength = SocialCounterPeriodUtil.getPeriodLength(offset);
380
381 return socialActivityCounterFinder.findAC_ByG_N_S_E_2(
382 groupId, name, startPeriod, endPeriod, periodLength);
383 }
384
385 public List<Tuple> getUserActivityCounters(
386 long groupId, String[] rankingNames, String[] selectedNames,
387 int start, int end)
388 throws SystemException {
389
390 List<Long> userIds = socialActivityCounterFinder.findU_ByG_N(
391 groupId, rankingNames, start, end);
392
393 if (userIds.isEmpty()) {
394 return Collections.emptyList();
395 }
396
397 Tuple[] userActivityCounters = new Tuple[userIds.size()];
398
399 List<SocialActivityCounter> activityCounters =
400 SocialActivityCounterFinderUtil.findAC_By_G_C_C_N_S_E(
401 groupId, userIds, selectedNames, QueryUtil.ALL_POS,
402 QueryUtil.ALL_POS);
403
404 long userId = 0;
405 Map<String, SocialActivityCounter> activityCountersMap = null;
406
407 for (SocialActivityCounter activityCounter : activityCounters) {
408 if (userId != activityCounter.getClassPK()) {
409 userId = activityCounter.getClassPK();
410 activityCountersMap =
411 new HashMap<String, SocialActivityCounter>();
412
413 Tuple userActivityCounter = new Tuple(
414 userId, activityCountersMap);
415
416 for (int i = 0; i < userIds.size(); i++) {
417 long curUserId = userIds.get(i);
418
419 if (userId == curUserId) {
420 userActivityCounters[i] = userActivityCounter;
421
422 break;
423 }
424 }
425 }
426
427 activityCountersMap.put(activityCounter.getName(), activityCounter);
428 }
429
430 return Arrays.asList(userActivityCounters);
431 }
432
433 public int getUserActivityCountersCount(long groupId, String[] rankingNames)
434 throws SystemException {
435
436 return SocialActivityCounterFinderUtil.countU_ByG_N(
437 groupId, rankingNames);
438 }
439
440 public void incrementUserAchievementCounter(long userId, long groupId)
441 throws PortalException, SystemException {
442
443 incrementActivityCounter(
444 groupId, PortalUtil.getClassNameId(User.class.getName()), userId,
445 SocialActivityCounterConstants.NAME_USER_ACHIEVEMENTS,
446 SocialActivityCounterConstants.TYPE_ACTOR, 1,
447 SocialActivityCounterConstants.PERIOD_LENGTH_SYSTEM);
448 }
449
450 protected boolean addActivityCounter(
451 User user, User assetEntryUser,
452 SocialActivityCounterDefinition activityCounterDefinition) {
453
454 if ((user.isDefaultUser() || !user.isActive()) &&
455 (activityCounterDefinition.getOwnerType() !=
456 SocialActivityCounterConstants.TYPE_ASSET)) {
457
458 return false;
459 }
460
461 if ((assetEntryUser.isDefaultUser() || !assetEntryUser.isActive()) &&
462 (activityCounterDefinition.getOwnerType() !=
463 SocialActivityCounterConstants.TYPE_ACTOR)) {
464
465 return false;
466 }
467
468 if (!activityCounterDefinition.isEnabled() ||
469 (activityCounterDefinition.getIncrement() == 0)) {
470
471 return false;
472 }
473
474 String name = activityCounterDefinition.getName();
475
476 if ((user.getUserId() == assetEntryUser.getUserId()) &&
477 (name.equals(SocialActivityCounterConstants.NAME_CONTRIBUTION) ||
478 name.equals(SocialActivityCounterConstants.NAME_POPULARITY))) {
479
480 return false;
481 }
482
483 return true;
484 }
485
486 protected SocialActivityCounter addNewPeriod(
487 SocialActivityCounter activityCounter, int periodLength)
488 throws PortalException, SystemException {
489
490 if (activityCounter == null) {
491 return null;
492 }
493
494 if (periodLength ==
495 SocialActivityCounterConstants.PERIOD_LENGTH_SYSTEM) {
496
497 activityCounter.setEndPeriod(
498 SocialCounterPeriodUtil.getStartPeriod() - 1);
499 }
500 else {
501 activityCounter.setEndPeriod(
502 activityCounter.getStartPeriod() + periodLength - 1);
503 }
504
505 socialActivityCounterPersistence.update(activityCounter, false);
506
507 return addActivityCounter(
508 activityCounter.getGroupId(), activityCounter.getClassNameId(),
509 activityCounter.getClassPK(), activityCounter.getName(),
510 activityCounter.getOwnerType(), 0, activityCounter.getTotalValue(),
511 SocialCounterPeriodUtil.getStartPeriod(),
512 SocialActivityCounterConstants.END_PERIOD_UNDEFINED);
513 }
514
515 protected boolean checkActivityLimit(
516 User user, SocialActivity activity,
517 SocialActivityCounterDefinition activityCounterDefinition)
518 throws PortalException, SystemException {
519
520 if (activityCounterDefinition.getLimitValue() == 0) {
521 return true;
522 }
523
524 long classPK = activity.getClassPK();
525
526 String name = activityCounterDefinition.getName();
527
528 if (name.equals(SocialActivityCounterConstants.NAME_PARTICIPATION)) {
529 classPK = 0;
530 }
531
532 SocialActivityLimit activityLimit =
533 socialActivityLimitPersistence.fetchByG_U_C_C_A_A(
534 activity.getGroupId(), user.getUserId(),
535 activity.getClassNameId(), classPK, activity.getType(),
536 activityCounterDefinition.getName());
537
538 if (activityLimit == null) {
539 try {
540 activityLimit =
541 socialActivityLimitLocalService.addActivityLimit(
542 user.getUserId(), activity.getGroupId(),
543 activity.getClassNameId(), classPK, activity.getType(),
544 activityCounterDefinition.getName(),
545 activityCounterDefinition.getLimitPeriod());
546 }
547 catch (SystemException se) {
548 activityLimit =
549 socialActivityLimitPersistence.fetchByG_U_C_C_A_A(
550 activity.getGroupId(), user.getUserId(),
551 activity.getClassNameId(), classPK, activity.getType(),
552 activityCounterDefinition.getName());
553
554 if (activityLimit == null) {
555 throw se;
556 }
557 }
558 }
559
560 int count = activityLimit.getCount(
561 activityCounterDefinition.getLimitPeriod());
562
563 if (count < activityCounterDefinition.getLimitValue()) {
564 activityLimit.setCount(
565 activityCounterDefinition.getLimitPeriod(), count + 1);
566
567 socialActivityLimitPersistence.update(activityLimit, false);
568
569 return true;
570 }
571
572 return false;
573 }
574
575 protected String getLockKey(
576 long groupId, long classNameId, long classPK, String name,
577 int ownerType) {
578
579 StringBundler sb = new StringBundler(7);
580
581 sb.append(StringUtil.toHexString(groupId));
582 sb.append(StringPool.POUND);
583 sb.append(StringUtil.toHexString(classNameId));
584 sb.append(StringPool.POUND);
585 sb.append(StringUtil.toHexString(classPK));
586 sb.append(StringPool.POUND);
587 sb.append(name);
588
589 return sb.toString();
590 }
591
592 protected void incrementActivityCounter(
593 long groupId, long classNameId, long classPK, String name,
594 int ownerType, int increment, int periodLength)
595 throws PortalException, SystemException {
596
597 SocialActivityCounter activityCounter = fetchLatestActivityCounter(
598 groupId, classNameId, classPK, name, ownerType);
599
600 if (activityCounter == null) {
601 activityCounter = addActivityCounter(
602 groupId, classNameId, classPK, name, ownerType, 0, 0,
603 SocialCounterPeriodUtil.getStartPeriod(),
604 SocialActivityCounterConstants.END_PERIOD_UNDEFINED);
605
606 if (periodLength > 0) {
607 activityCounter.setStartPeriod(
608 SocialCounterPeriodUtil.getActivityDay());
609 }
610 }
611
612 if (!activityCounter.isActivePeriod(periodLength)) {
613 activityCounter = addNewPeriod(activityCounter, periodLength);
614 }
615
616 activityCounter.setCurrentValue(
617 activityCounter.getCurrentValue() + increment);
618 activityCounter.setTotalValue(
619 activityCounter.getTotalValue() + increment);
620
621 socialActivityCounterPersistence.update(activityCounter, false);
622 }
623
624 protected void incrementActivityCounter(
625 long groupId, User user, AssetEntry assetEntry,
626 SocialActivityCounterDefinition activityCounterDefinition)
627 throws PortalException, SystemException {
628
629 int ownerType = activityCounterDefinition.getOwnerType();
630 long userClassNameId = PortalUtil.getClassNameId(User.class.getName());
631
632 if (ownerType == SocialActivityCounterConstants.TYPE_ACTOR) {
633 incrementActivityCounter(
634 groupId, userClassNameId, user.getUserId(),
635 activityCounterDefinition.getName(), ownerType,
636 activityCounterDefinition.getIncrement(),
637 activityCounterDefinition.getPeriodLength());
638 }
639 else if (ownerType == SocialActivityCounterConstants.TYPE_ASSET) {
640 incrementActivityCounter(
641 groupId, assetEntry.getClassNameId(), assetEntry.getClassPK(),
642 activityCounterDefinition.getName(), ownerType,
643 activityCounterDefinition.getIncrement(),
644 activityCounterDefinition.getPeriodLength());
645 }
646 else {
647 incrementActivityCounter(
648 groupId, userClassNameId, assetEntry.getUserId(),
649 activityCounterDefinition.getName(), ownerType,
650 activityCounterDefinition.getIncrement(),
651 activityCounterDefinition.getPeriodLength());
652 }
653 }
654
655 private static Log _log = LogFactoryUtil.getLog(
656 SocialActivityCounterLocalService.class);
657
658 }