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