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