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.asset.service.impl;
016    
017    import com.liferay.portal.kernel.cache.ThreadLocalCachable;
018    import com.liferay.portal.kernel.dao.orm.QueryUtil;
019    import com.liferay.portal.kernel.exception.PortalException;
020    import com.liferay.portal.kernel.systemevent.SystemEvent;
021    import com.liferay.portal.kernel.util.ArrayUtil;
022    import com.liferay.portal.kernel.util.ListUtil;
023    import com.liferay.portal.kernel.util.StringPool;
024    import com.liferay.portal.kernel.util.StringUtil;
025    import com.liferay.portal.model.Group;
026    import com.liferay.portal.model.SystemEventConstants;
027    import com.liferay.portal.model.User;
028    import com.liferay.portal.service.ServiceContext;
029    import com.liferay.portlet.asset.AssetTagException;
030    import com.liferay.portlet.asset.DuplicateTagException;
031    import com.liferay.portlet.asset.model.AssetEntry;
032    import com.liferay.portlet.asset.model.AssetTag;
033    import com.liferay.portlet.asset.service.base.AssetTagLocalServiceBaseImpl;
034    import com.liferay.portlet.asset.util.AssetUtil;
035    import com.liferay.portlet.asset.util.comparator.AssetTagNameComparator;
036    import com.liferay.portlet.social.util.SocialCounterPeriodUtil;
037    
038    import java.util.ArrayList;
039    import java.util.Collections;
040    import java.util.List;
041    
042    /**
043     * Provides the local service for accessing, adding, checking, deleting,
044     * merging, and updating asset tags.
045     *
046     * @author Brian Wing Shun Chan
047     * @author Alvaro del Castillo
048     * @author Jorge Ferrer
049     * @author Bruno Farache
050     */
051    public class AssetTagLocalServiceImpl extends AssetTagLocalServiceBaseImpl {
052    
053            /**
054             * Adds an asset tag.
055             *
056             * @param  userId the primary key of the user adding the asset tag
057             * @param  groupId the primary key of the group in which the asset tag is to
058             *         be added
059             * @param  name the asset tag's name
060             * @param  serviceContext the service context to be applied
061             * @return the asset tag that was added
062             * @throws PortalException if a user with the primary key could not be found
063             *         or if a portal exception occurred
064             */
065            @Override
066            public AssetTag addTag(
067                            long userId, long groupId, String name,
068                            ServiceContext serviceContext)
069                    throws PortalException {
070    
071                    // Tag
072    
073                    User user = userPersistence.findByPrimaryKey(userId);
074    
075                    long tagId = counterLocalService.increment();
076    
077                    AssetTag tag = assetTagPersistence.create(tagId);
078    
079                    tag.setUuid(serviceContext.getUuid());
080                    tag.setGroupId(groupId);
081                    tag.setCompanyId(user.getCompanyId());
082                    tag.setUserId(user.getUserId());
083                    tag.setUserName(user.getFullName());
084    
085                    name = name.trim();
086                    name = StringUtil.toLowerCase(name);
087    
088                    if (hasTag(groupId, name)) {
089                            throw new DuplicateTagException(
090                                    "A tag with the name " + name + " already exists");
091                    }
092    
093                    validate(name);
094    
095                    tag.setName(name);
096    
097                    assetTagPersistence.update(tag);
098    
099                    return tag;
100            }
101    
102            /**
103             * Returns the asset tags matching the group and names, creating new asset
104             * tags matching the names if the group doesn't already have them.
105             *
106             * <p>
107             * For each name, if an asset tag with the name doesn't already exist in the
108             * group, this method creates a new asset tag with the name in the group.
109             * </p>
110             *
111             * @param  userId the primary key of the user checking the asset tags
112             * @param  group the group in which to check the asset tags
113             * @param  names the asset tag names
114             * @return the asset tags matching the group and names and new asset tags
115             *         matching the names that don't already exist in the group
116             * @throws PortalException if a matching group could not be found or if a
117             *         portal exception occurred
118             */
119            @Override
120            public List<AssetTag> checkTags(long userId, Group group, String[] names)
121                    throws PortalException {
122    
123                    List<AssetTag> tags = new ArrayList<>();
124    
125                    for (String name : names) {
126                            AssetTag tag = fetchTag(group.getGroupId(), name);
127    
128                            if (tag == null) {
129                                    ServiceContext serviceContext = new ServiceContext();
130    
131                                    serviceContext.setAddGroupPermissions(true);
132                                    serviceContext.setAddGuestPermissions(true);
133                                    serviceContext.setScopeGroupId(group.getGroupId());
134    
135                                    tag = addTag(userId, group.getGroupId(), name, serviceContext);
136                            }
137    
138                            if (tag != null) {
139                                    tags.add(tag);
140                            }
141                    }
142    
143                    return tags;
144            }
145    
146            /**
147             * Returns the asset tags matching the group and names, creating new asset
148             * tags matching the names if the group doesn't already have them.
149             *
150             * @param  userId the primary key of the user checking the asset tags
151             * @param  groupId the primary key of the group in which check the asset
152             *         tags
153             * @param  names the asset tag names
154             * @return the asset tags matching the group and names and new asset tags
155             *         matching the names that don't already exist in the group
156             * @throws PortalException if a matching group could not be found or if a
157             *         portal exception occurred
158             */
159            @Override
160            public List<AssetTag> checkTags(long userId, long groupId, String[] names)
161                    throws PortalException {
162    
163                    Group group = groupPersistence.findByPrimaryKey(groupId);
164    
165                    return checkTags(userId, group, names);
166            }
167    
168            /**
169             * Decrements the number of assets to which the asset tag has been applied.
170             *
171             * @param  tagId the primary key of the asset tag
172             * @param  classNameId the class name ID of the entity to which the asset
173             *         tag had been applied
174             * @return the asset tag
175             * @throws PortalException if an asset tag with the primary key could not be
176             *         found or if a portal exception occurred
177             */
178            @Override
179            public AssetTag decrementAssetCount(long tagId, long classNameId)
180                    throws PortalException {
181    
182                    AssetTag tag = assetTagPersistence.findByPrimaryKey(tagId);
183    
184                    tag.setAssetCount(Math.max(0, tag.getAssetCount() - 1));
185    
186                    assetTagPersistence.update(tag);
187    
188                    assetTagStatsLocalService.updateTagStats(tagId, classNameId);
189    
190                    return tag;
191            }
192    
193            /**
194             * Deletes all asset tags in the group.
195             *
196             * @param  groupId the primary key of the group in which to delete all asset
197             *         tags
198             * @throws PortalException if a portal exception occurred
199             */
200            @Override
201            public void deleteGroupTags(long groupId) throws PortalException {
202                    List<AssetTag> tags = getGroupTags(groupId);
203    
204                    for (AssetTag tag : tags) {
205                            assetTagLocalService.deleteTag(tag);
206                    }
207            }
208    
209            /**
210             * Deletes the asset tag.
211             *
212             * @param  tag the asset tag to be deleted
213             * @throws PortalException if a portal exception occurred
214             */
215            @Override
216            @SystemEvent(type = SystemEventConstants.TYPE_DELETE)
217            public void deleteTag(AssetTag tag) throws PortalException {
218    
219                    // Entries
220    
221                    List<AssetEntry> entries = assetTagPersistence.getAssetEntries(
222                            tag.getTagId());
223    
224                    // Tag
225    
226                    assetTagPersistence.remove(tag);
227    
228                    // Stats
229    
230                    assetTagStatsLocalService.deleteTagStatsByTagId(tag.getTagId());
231    
232                    // Indexer
233    
234                    assetEntryLocalService.reindex(entries);
235            }
236    
237            /**
238             * Deletes the asset tag.
239             *
240             * @param  tagId the primary key of the asset tag
241             * @throws PortalException if no asset tag could be found with the primary
242             *         key or if a portal exception occurred
243             */
244            @Override
245            public void deleteTag(long tagId) throws PortalException {
246                    AssetTag tag = assetTagPersistence.findByPrimaryKey(tagId);
247    
248                    assetTagLocalService.deleteTag(tag);
249            }
250    
251            /**
252             * Returns the asset tag with the name in the group.
253             *
254             * @param  groupId the primary key of the group
255             * @param  name the asset tag's name
256             * @return the asset tag with the name in the group or <code>null</code> if
257             *         it could not be found
258             */
259            @Override
260            public AssetTag fetchTag(long groupId, String name) {
261                    return assetTagPersistence.fetchByG_N(groupId, name);
262            }
263    
264            /**
265             * Returns the asset tags of the asset entry.
266             *
267             * @param  entryId the primary key of the asset entry
268             * @return the asset tags of the asset entry
269             */
270            @Override
271            public List<AssetTag> getEntryTags(long entryId) {
272                    return assetEntryPersistence.getAssetTags(entryId);
273            }
274    
275            /**
276             * Returns the asset tags in the groups.
277             *
278             * @param  groupIds the primary keys of the groups
279             * @return the asset tags in the groups
280             */
281            @Override
282            public List<AssetTag> getGroupsTags(long[] groupIds) {
283                    List<AssetTag> groupsTags = new ArrayList<>();
284    
285                    for (long groupId : groupIds) {
286                            List<AssetTag> groupTags = getGroupTags(groupId);
287    
288                            groupsTags.addAll(groupTags);
289                    }
290    
291                    return groupsTags;
292            }
293    
294            /**
295             * Returns the asset tags in the group.
296             *
297             * @param  groupId the primary key of the group
298             * @return the asset tags in the group
299             */
300            @Override
301            public List<AssetTag> getGroupTags(long groupId) {
302                    return assetTagPersistence.findByGroupId(groupId);
303            }
304    
305            /**
306             * Returns a range of all the asset tags in the group.
307             *
308             * @param  groupId the primary key of the group
309             * @param  start the lower bound of the range of asset tags
310             * @param  end the upper bound of the range of asset tags (not inclusive)
311             * @return the range of matching asset tags
312             */
313            @Override
314            public List<AssetTag> getGroupTags(long groupId, int start, int end) {
315                    return assetTagPersistence.findByGroupId(groupId, start, end);
316            }
317    
318            /**
319             * Returns the number of asset tags in the group.
320             *
321             * @param  groupId the primary key of the group
322             * @return the number of asset tags in the group
323             */
324            @Override
325            public int getGroupTagsCount(long groupId) {
326                    return assetTagPersistence.countByGroupId(groupId);
327            }
328    
329            @Override
330            public List<AssetTag> getSocialActivityCounterOffsetTags(
331                    long groupId, String socialActivityCounterName, int startOffset,
332                    int endOffset) {
333    
334                    int startPeriod = SocialCounterPeriodUtil.getStartPeriod(startOffset);
335                    int endPeriod = SocialCounterPeriodUtil.getEndPeriod(endOffset);
336    
337                    return getSocialActivityCounterPeriodTags(
338                            groupId, socialActivityCounterName, startPeriod, endPeriod);
339            }
340    
341            @Override
342            public List<AssetTag> getSocialActivityCounterPeriodTags(
343                    long groupId, String socialActivityCounterName, int startPeriod,
344                    int endPeriod) {
345    
346                    int offset = SocialCounterPeriodUtil.getOffset(endPeriod);
347    
348                    int periodLength = SocialCounterPeriodUtil.getPeriodLength(offset);
349    
350                    return assetTagFinder.findByG_N_S_E(
351                            groupId, socialActivityCounterName, startPeriod, endPeriod,
352                            periodLength);
353            }
354    
355            /**
356             * Returns the asset tag with the primary key.
357             *
358             * @param  tagId the primary key of the asset tag
359             * @return the asset tag with the primary key
360             * @throws PortalException if an asset tag with the primary key could not be
361             *         found
362             */
363            @Override
364            public AssetTag getTag(long tagId) throws PortalException {
365                    return assetTagPersistence.findByPrimaryKey(tagId);
366            }
367    
368            /**
369             * Returns the asset tag with the name in the group.
370             *
371             * @param  groupId the primary key of the group
372             * @param  name the name of the asset tag
373             * @return the asset tag with the name in the group
374             * @throws PortalException if a matching asset tag could not be found
375             */
376            @Override
377            public AssetTag getTag(long groupId, String name) throws PortalException {
378                    return assetTagPersistence.findByG_N(groupId, name);
379            }
380    
381            /**
382             * Returns the primary keys of the asset tags with the names in the group.
383             *
384             * @param  groupId the primary key of the group
385             * @param  names the names of the asset tags
386             * @return the primary keys of the asset tags with the names in the group
387             */
388            @Override
389            public long[] getTagIds(long groupId, String[] names) {
390                    List<Long> tagIds = new ArrayList<>(names.length);
391    
392                    for (String name : names) {
393                            AssetTag tag = fetchTag(groupId, name);
394    
395                            if (tag == null) {
396                                    continue;
397                            }
398    
399                            tagIds.add(tag.getTagId());
400                    }
401    
402                    return ArrayUtil.toArray(tagIds.toArray(new Long[tagIds.size()]));
403            }
404    
405            /**
406             * Returns the primary keys of the asset tags with the name in the groups.
407             *
408             * @param  groupIds the primary keys of the groups
409             * @param  name the name of the asset tags
410             * @return the primary keys of the asset tags with the name in the groups
411             */
412            @Override
413            public long[] getTagIds(long[] groupIds, String name) {
414                    List<Long> tagIds = new ArrayList<>(groupIds.length);
415    
416                    for (long groupId : groupIds) {
417                            AssetTag tag = fetchTag(groupId, name);
418    
419                            if (tag == null) {
420                                    continue;
421                            }
422    
423                            tagIds.add(tag.getTagId());
424                    }
425    
426                    return ArrayUtil.toArray(tagIds.toArray(new Long[tagIds.size()]));
427            }
428    
429            /**
430             * Returns the primary keys of the asset tags with the names in the groups.
431             *
432             * @param  groupIds the primary keys of the groups
433             * @param  names the names of the asset tags
434             * @return the primary keys of the asset tags with the names in the groups
435             */
436            @Override
437            public long[] getTagIds(long[] groupIds, String[] names) {
438                    long[] tagsIds = new long[0];
439    
440                    for (long groupId : groupIds) {
441                            tagsIds = ArrayUtil.append(tagsIds, getTagIds(groupId, names));
442                    }
443    
444                    return tagsIds;
445            }
446    
447            /**
448             * Returns the names of all the asset tags.
449             *
450             * @return the names of all the asset tags
451             */
452            @Override
453            public String[] getTagNames() {
454                    return getTagNames(getTags());
455            }
456    
457            /**
458             * Returns the names of the asset tags of the entity.
459             *
460             * @param  classNameId the class name ID of the entity
461             * @param  classPK the primary key of the entity
462             * @return the names of the asset tags of the entity
463             */
464            @Override
465            public String[] getTagNames(long classNameId, long classPK) {
466                    return getTagNames(getTags(classNameId, classPK));
467            }
468    
469            /**
470             * Returns the names of the asset tags of the entity
471             *
472             * @param  className the class name of the entity
473             * @param  classPK the primary key of the entity
474             * @return the names of the asset tags of the entity
475             */
476            @Override
477            public String[] getTagNames(String className, long classPK) {
478                    return getTagNames(getTags(className, classPK));
479            }
480    
481            /**
482             * Returns all the asset tags.
483             *
484             * @return the asset tags
485             */
486            @Override
487            public List<AssetTag> getTags() {
488                    return assetTagPersistence.findAll();
489            }
490    
491            /**
492             * Returns the asset tags of the entity.
493             *
494             * @param  classNameId the class name ID of the entity
495             * @param  classPK the primary key of the entity
496             * @return the asset tags of the entity
497             */
498            @Override
499            public List<AssetTag> getTags(long classNameId, long classPK) {
500                    AssetEntry entry = assetEntryPersistence.fetchByC_C(
501                            classNameId, classPK);
502    
503                    if (entry == null) {
504                            return Collections.emptyList();
505                    }
506    
507                    return assetEntryPersistence.getAssetTags(entry.getEntryId());
508            }
509    
510            @Override
511            public List<AssetTag> getTags(long groupId, long classNameId, String name) {
512                    return assetTagFinder.findByG_C_N(
513                            groupId, classNameId, name, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
514                            null);
515            }
516    
517            @Override
518            public List<AssetTag> getTags(
519                    long groupId, long classNameId, String name, int start, int end) {
520    
521                    return assetTagFinder.findByG_C_N(
522                            groupId, classNameId, name, start, end, null);
523            }
524    
525            /**
526             * Returns the asset tags of the entity.
527             *
528             * @param  className the class name of the entity
529             * @param  classPK the primary key of the entity
530             * @return the asset tags of the entity
531             */
532            @Override
533            @ThreadLocalCachable
534            public List<AssetTag> getTags(String className, long classPK) {
535                    long classNameId = classNameLocalService.getClassNameId(className);
536    
537                    return getTags(classNameId, classPK);
538            }
539    
540            @Override
541            public int getTagsSize(long groupId, long classNameId, String name) {
542                    return assetTagFinder.countByG_C_N(groupId, classNameId, name);
543            }
544    
545            /**
546             * Returns <code>true</code> if the group contains an asset tag with the
547             * name.
548             *
549             * @param  groupId the primary key of the group
550             * @param  name the name of the asset tag
551             * @return <code>true</code> if the group contains an asset tag with the
552             *         name; <code>false</code> otherwise.
553             */
554            @Override
555            public boolean hasTag(long groupId, String name) {
556                    AssetTag tag = fetchTag(groupId, name);
557    
558                    if (tag != null) {
559                            return true;
560                    }
561    
562                    return false;
563            }
564    
565            /**
566             * Increments the number of assets to which the asset tag has been applied.
567             *
568             * @param  tagId the primary key of the asset tag
569             * @param  classNameId the class name ID of the entity to which the asset
570             *         tag is being applied
571             * @return the asset tag
572             * @throws PortalException if a asset tag with the primary key could not be
573             *         found or if a portal exception occurred
574             */
575            @Override
576            public AssetTag incrementAssetCount(long tagId, long classNameId)
577                    throws PortalException {
578    
579                    AssetTag tag = assetTagPersistence.findByPrimaryKey(tagId);
580    
581                    tag.setAssetCount(tag.getAssetCount() + 1);
582    
583                    assetTagPersistence.update(tag);
584    
585                    assetTagStatsLocalService.updateTagStats(tagId, classNameId);
586    
587                    return tag;
588            }
589    
590            /**
591             * Replaces all occurrences of the first asset tag with the second asset tag
592             * and deletes the first asset tag.
593             *
594             * @param  fromTagId the primary key of the asset tag to be replaced
595             * @param  toTagId the primary key of the asset tag to apply to the asset
596             *         entries of the other asset tag
597             * @throws PortalException if a portal exception occurred
598             */
599            @Override
600            public void mergeTags(long fromTagId, long toTagId) throws PortalException {
601                    List<AssetEntry> entries = assetTagPersistence.getAssetEntries(
602                            fromTagId);
603    
604                    assetTagPersistence.addAssetEntries(toTagId, entries);
605    
606                    deleteTag(fromTagId);
607    
608                    for (AssetEntry entry : entries) {
609                            incrementAssetCount(toTagId, entry.getClassNameId());
610                    }
611            }
612    
613            /**
614             * Returns the asset tags in the group whose names match the pattern.
615             *
616             * @param  groupId the primary key of the group
617             * @param  name the pattern to match
618             * @param  start the lower bound of the range of asset tags
619             * @param  end the upper bound of the range of asset tags (not inclusive)
620             * @return the asset tags in the group whose names match the pattern
621             */
622            @Override
623            public List<AssetTag> search(
624                    long groupId, String name, int start, int end) {
625    
626                    return search(new long[] {groupId}, name, start, end);
627            }
628    
629            /**
630             * Returns the asset tags in the groups whose names match the pattern.
631             *
632             * @param  groupIds the primary keys of the groups
633             * @param  name the pattern to match
634             * @param  start the lower bound of the range of asset tags
635             * @param  end the upper bound of the range of asset tags (not inclusive)
636             * @return the asset tags in the groups whose names match the pattern
637             */
638            @Override
639            public List<AssetTag> search(
640                    long[] groupIds, String name, int start, int end) {
641    
642                    return assetTagPersistence.findByG_LikeN(
643                            groupIds, name, start, end, new AssetTagNameComparator());
644            }
645    
646            @Override
647            public AssetTag updateTag(
648                            long userId, long tagId, String name, ServiceContext serviceContext)
649                    throws PortalException {
650    
651                    // Tag
652    
653                    AssetTag tag = assetTagPersistence.findByPrimaryKey(tagId);
654    
655                    String oldName = tag.getName();
656    
657                    name = name.trim();
658                    name = StringUtil.toLowerCase(name);
659    
660                    if (!name.equals(tag.getName()) && hasTag(tag.getGroupId(), name)) {
661                            throw new DuplicateTagException(
662                                    "A tag with the name " + name + " already exists");
663                    }
664    
665                    if (!tag.getName().equals(name)) {
666                            AssetTag existingAssetTag = fetchTag(tag.getGroupId(), name);
667    
668                            if ((existingAssetTag != null) &&
669                                    (existingAssetTag.getTagId() != tagId)) {
670    
671                                    throw new DuplicateTagException(
672                                            "A tag with the name " + name + " already exists");
673                            }
674                    }
675    
676                    validate(name);
677    
678                    tag.setName(name);
679    
680                    assetTagPersistence.update(tag);
681    
682                    // Indexer
683    
684                    if (!oldName.equals(name)) {
685                            List<AssetEntry> entries = assetTagPersistence.getAssetEntries(
686                                    tag.getTagId());
687    
688                            assetEntryLocalService.reindex(entries);
689                    }
690    
691                    return tag;
692            }
693    
694            protected String[] getTagNames(List<AssetTag>tags) {
695                    return ListUtil.toArray(tags, AssetTag.NAME_ACCESSOR);
696            }
697    
698            protected void validate(String name) throws PortalException {
699                    if (!AssetUtil.isValidWord(name)) {
700                            throw new AssetTagException(
701                                    StringUtil.merge(
702                                            AssetUtil.INVALID_CHARACTERS, StringPool.SPACE),
703                                    AssetTagException.INVALID_CHARACTER);
704                    }
705            }
706    
707    }