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