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