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