1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portlet.asset.service.impl;
16  
17  import com.liferay.portal.kernel.cache.ThreadLocalCachable;
18  import com.liferay.portal.kernel.exception.PortalException;
19  import com.liferay.portal.kernel.exception.SystemException;
20  import com.liferay.portal.kernel.json.JSONArray;
21  import com.liferay.portal.kernel.search.Indexer;
22  import com.liferay.portal.kernel.search.IndexerRegistryUtil;
23  import com.liferay.portal.kernel.util.ArrayUtil;
24  import com.liferay.portal.kernel.util.GetterUtil;
25  import com.liferay.portal.kernel.util.ListUtil;
26  import com.liferay.portal.kernel.util.StringPool;
27  import com.liferay.portal.kernel.util.StringUtil;
28  import com.liferay.portal.kernel.util.Validator;
29  import com.liferay.portal.model.ResourceConstants;
30  import com.liferay.portal.model.User;
31  import com.liferay.portal.service.ServiceContext;
32  import com.liferay.portal.util.PortalUtil;
33  import com.liferay.portal.util.PropsValues;
34  import com.liferay.portlet.asset.AssetTagException;
35  import com.liferay.portlet.asset.DuplicateTagException;
36  import com.liferay.portlet.asset.NoSuchTagException;
37  import com.liferay.portlet.asset.model.AssetEntry;
38  import com.liferay.portlet.asset.model.AssetTag;
39  import com.liferay.portlet.asset.model.AssetTagProperty;
40  import com.liferay.portlet.asset.service.base.AssetTagLocalServiceBaseImpl;
41  import com.liferay.portlet.asset.util.AssetUtil;
42  import com.liferay.util.Autocomplete;
43  
44  import java.util.ArrayList;
45  import java.util.Date;
46  import java.util.List;
47  
48  /**
49   * <a href="AssetTagLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
50   *
51   * @author Brian Wing Shun Chan
52   * @author Alvaro del Castillo
53   * @author Jorge Ferrer
54   * @author Bruno Farache
55   */
56  public class AssetTagLocalServiceImpl extends AssetTagLocalServiceBaseImpl {
57  
58      public AssetTag addTag(
59              long userId, String name, String[] tagProperties,
60              ServiceContext serviceContext)
61          throws PortalException, SystemException {
62  
63          // Tag
64  
65          User user = userPersistence.findByPrimaryKey(userId);
66          long groupId = serviceContext.getScopeGroupId();
67  
68          if (tagProperties == null) {
69              tagProperties = new String[0];
70          }
71  
72          Date now = new Date();
73  
74          long tagId = counterLocalService.increment();
75  
76          AssetTag tag = assetTagPersistence.create(tagId);
77  
78          tag.setGroupId(groupId);
79          tag.setCompanyId(user.getCompanyId());
80          tag.setUserId(user.getUserId());
81          tag.setUserName(user.getFullName());
82          tag.setCreateDate(now);
83          tag.setModifiedDate(now);
84  
85          name = name.trim();
86          name = name.toLowerCase();
87  
88          if (hasTag(groupId, name)) {
89              throw new DuplicateTagException(
90                  "A tag with the name " + name + " already exists");
91          }
92  
93          validate(name);
94  
95          tag.setName(name);
96  
97          assetTagPersistence.update(tag, false);
98  
99          // Resources
100 
101         if (serviceContext.getAddCommunityPermissions() ||
102             serviceContext.getAddGuestPermissions()) {
103 
104             addTagResources(
105                 tag, serviceContext.getAddCommunityPermissions(),
106                 serviceContext.getAddGuestPermissions());
107         }
108         else {
109             addTagResources(
110                 tag, serviceContext.getCommunityPermissions(),
111                 serviceContext.getGuestPermissions());
112         }
113 
114         // Properties
115 
116         for (int i = 0; i < tagProperties.length; i++) {
117             String[] tagProperty = StringUtil.split(
118                 tagProperties[i], StringPool.COLON);
119 
120             String key = StringPool.BLANK;
121 
122             if (tagProperty.length > 1) {
123                 key = GetterUtil.getString(tagProperty[1]);
124             }
125 
126             String value = StringPool.BLANK;
127 
128             if (tagProperty.length > 2) {
129                 value = GetterUtil.getString(tagProperty[2]);
130             }
131 
132             if (Validator.isNotNull(key)) {
133                 assetTagPropertyLocalService.addTagProperty(
134                     userId, tagId, key, value);
135             }
136         }
137 
138         return tag;
139     }
140 
141     public void addTagResources(
142             AssetTag tag, boolean addCommunityPermissions,
143             boolean addGuestPermissions)
144         throws PortalException, SystemException {
145 
146         resourceLocalService.addResources(
147             tag.getCompanyId(), tag.getGroupId(), tag.getUserId(),
148             AssetTag.class.getName(), tag.getTagId(), false,
149             addCommunityPermissions, addGuestPermissions);
150     }
151 
152     public void addTagResources(
153             AssetTag tag, String[] communityPermissions,
154             String[] guestPermissions)
155         throws PortalException, SystemException {
156 
157         resourceLocalService.addModelResources(
158             tag.getCompanyId(), tag.getGroupId(), tag.getUserId(),
159             AssetTag.class.getName(), tag.getTagId(), communityPermissions,
160             guestPermissions);
161     }
162 
163     public void checkTags(long userId, long groupId, String[] names)
164         throws PortalException, SystemException {
165 
166         for (String name : names) {
167             try {
168                 getTag(groupId, name);
169             }
170             catch (NoSuchTagException nste) {
171                 ServiceContext serviceContext = new ServiceContext();
172 
173                 serviceContext.setAddCommunityPermissions(true);
174                 serviceContext.setAddGuestPermissions(true);
175                 serviceContext.setScopeGroupId(groupId);
176 
177                 addTag(
178                     userId, name, PropsValues.ASSET_TAG_PROPERTIES_DEFAULT,
179                     serviceContext);
180             }
181         }
182     }
183 
184     public AssetTag decrementAssetCount(long tagId, long classNameId)
185         throws PortalException, SystemException {
186 
187         AssetTag tag = assetTagPersistence.findByPrimaryKey(tagId);
188 
189         tag.setAssetCount(Math.max(0, tag.getAssetCount() - 1));
190 
191         assetTagPersistence.update(tag, false);
192 
193         assetTagStatsLocalService.updateTagStats(tagId, classNameId);
194 
195         return tag;
196     }
197 
198     public void deleteTag(AssetTag tag)
199         throws PortalException, SystemException {
200 
201         // Entries
202 
203         List<AssetEntry> entries = assetTagPersistence.getAssetEntries(
204             tag.getTagId());
205 
206         // Tag
207 
208         assetTagPersistence.remove(tag);
209 
210         // Resources
211 
212         resourceLocalService.deleteResource(
213             tag.getCompanyId(), AssetTag.class.getName(),
214             ResourceConstants.SCOPE_INDIVIDUAL, tag.getTagId());
215 
216         // Properties
217 
218         assetTagPropertyLocalService.deleteTagProperties(tag.getTagId());
219 
220         // Indexer
221 
222         reindex(entries);
223     }
224 
225     public void deleteTag(long tagId) throws PortalException, SystemException {
226         AssetTag tag = assetTagPersistence.findByPrimaryKey(tagId);
227 
228         deleteTag(tag);
229     }
230 
231     public List<AssetTag> getEntryTags(long entryId) throws SystemException {
232         return assetTagFinder.findByEntryId(entryId);
233     }
234 
235     public List<AssetTag> getGroupTags(long groupId) throws SystemException {
236         return assetTagPersistence.findByGroupId(groupId);
237     }
238 
239     public AssetTag getTag(long tagId) throws PortalException, SystemException {
240         return assetTagPersistence.findByPrimaryKey(tagId);
241     }
242 
243     public AssetTag getTag(long groupId, String name)
244         throws PortalException, SystemException {
245 
246         return assetTagFinder.findByG_N(groupId, name);
247     }
248 
249     public long[] getTagIds(long groupId, String[] names)
250         throws PortalException, SystemException {
251 
252         List<Long> tagIds = new ArrayList<Long>(names.length);
253 
254         for (String name : names) {
255             try {
256                 AssetTag tag = getTag(groupId, name);
257 
258                 tagIds.add(tag.getTagId());
259             }
260             catch (NoSuchTagException nste) {
261             }
262         }
263 
264         return ArrayUtil.toArray(tagIds.toArray(new Long[tagIds.size()]));
265     }
266 
267     public String[] getTagNames() throws SystemException {
268         return getTagNames(getTags());
269     }
270 
271     public String[] getTagNames(long classNameId, long classPK)
272         throws SystemException {
273 
274         return getTagNames(getTags(classNameId, classPK));
275     }
276 
277     public String[] getTagNames(String className, long classPK)
278         throws SystemException {
279 
280         return getTagNames(getTags(className, classPK));
281     }
282 
283     public List<AssetTag> getTags() throws SystemException {
284         return getTags();
285     }
286 
287     public List<AssetTag> getTags(long classNameId, long classPK)
288         throws SystemException {
289 
290         return assetTagFinder.findByC_C(classNameId, classPK);
291     }
292 
293     public List<AssetTag> getTags(long groupId, long classNameId, String name)
294         throws SystemException {
295 
296         return assetTagFinder.findByG_C_N(groupId, classNameId, name);
297     }
298 
299     public List<AssetTag> getTags(
300             long groupId, long classNameId, String name, int start, int end)
301         throws SystemException {
302 
303         return assetTagFinder.findByG_C_N(
304             groupId, classNameId, name, start, end);
305     }
306 
307     @ThreadLocalCachable
308     public List<AssetTag> getTags(String className, long classPK)
309         throws SystemException {
310 
311         long classNameId = PortalUtil.getClassNameId(className);
312 
313         return getTags(classNameId, classPK);
314     }
315 
316     public int getTagsSize(long groupId, long classNameId, String name)
317         throws SystemException {
318 
319         return assetTagFinder.countByG_C_N(groupId, classNameId, name);
320     }
321 
322     public boolean hasTag(long groupId, String name)
323         throws PortalException, SystemException {
324 
325         try {
326             getTag(groupId, name);
327 
328             return true;
329         }
330         catch (NoSuchTagException nste) {
331             return false;
332         }
333     }
334 
335     public AssetTag incrementAssetCount(long tagId, long classNameId)
336         throws PortalException, SystemException {
337 
338         AssetTag tag = assetTagPersistence.findByPrimaryKey(tagId);
339 
340         tag.setAssetCount(tag.getAssetCount() + 1);
341 
342         assetTagPersistence.update(tag, false);
343 
344         assetTagStatsLocalService.updateTagStats(tagId, classNameId);
345 
346         return tag;
347     }
348 
349     public void mergeTags(long fromTagId, long toTagId)
350         throws PortalException, SystemException {
351 
352         List<AssetEntry> entries = assetTagPersistence.getAssetEntries(
353             fromTagId);
354 
355         assetTagPersistence.addAssetEntries(toTagId, entries);
356 
357         List<AssetTagProperty> tagProperties =
358             assetTagPropertyPersistence.findByTagId(fromTagId);
359 
360         for (AssetTagProperty fromTagProperty : tagProperties) {
361             AssetTagProperty toTagProperty =
362                 assetTagPropertyPersistence.fetchByT_K(
363                     toTagId, fromTagProperty.getKey());
364 
365             if (toTagProperty == null) {
366                 fromTagProperty.setTagId(toTagId);
367 
368                 assetTagPropertyPersistence.update(fromTagProperty, false);
369             }
370         }
371 
372         deleteTag(fromTagId);
373     }
374 
375     public JSONArray search(
376             long groupId, String name, String[] tagProperties, int start,
377             int end)
378         throws SystemException {
379 
380         List<AssetTag> list = assetTagFinder.findByG_N_P(
381             groupId, name, tagProperties, start, end);
382 
383         return Autocomplete.listToJson(list, "name", "name");
384     }
385 
386     public AssetTag updateTag(
387             long userId, long tagId, String name, String[] tagProperties,
388             ServiceContext serviceContext)
389         throws PortalException, SystemException {
390 
391         // Tag
392 
393         AssetTag tag = assetTagPersistence.findByPrimaryKey(tagId);
394 
395         String oldName = tag.getName();
396 
397         tag.setModifiedDate(new Date());
398 
399         name = name.trim();
400         name = name.toLowerCase();
401 
402         if (tagProperties == null) {
403             tagProperties = new String[0];
404         }
405 
406         if (!tag.getName().equals(name) &&
407             hasTag(tag.getGroupId(), name)) {
408 
409             throw new DuplicateTagException(
410                 "A tag with the name " + name + " already exists");
411         }
412 
413         if (!tag.getName().equals(name)) {
414             try {
415                 AssetTag existingAssetTag = getTag(tag.getGroupId(), name);
416 
417                 if (existingAssetTag.getTagId() != tagId) {
418                     throw new DuplicateTagException(
419                         "A tag with the name " + name + " already exists");
420                 }
421             }
422             catch (NoSuchTagException nste) {
423             }
424         }
425 
426         validate(name);
427 
428         tag.setName(name);
429 
430         assetTagPersistence.update(tag, false);
431 
432         // Properties
433 
434         List<AssetTagProperty> oldTagProperties =
435             assetTagPropertyPersistence.findByTagId(tagId);
436 
437         for (AssetTagProperty tagProperty : oldTagProperties) {
438             assetTagPropertyLocalService.deleteTagProperty(tagProperty);
439         }
440 
441         for (int i = 0; i < tagProperties.length; i++) {
442             String[] tagProperty = StringUtil.split(
443                 tagProperties[i], StringPool.COLON);
444 
445             String key = StringPool.BLANK;
446 
447             if (tagProperty.length > 0) {
448                 key = GetterUtil.getString(tagProperty[0]);
449             }
450 
451             String value = StringPool.BLANK;
452 
453             if (tagProperty.length > 1) {
454                 value = GetterUtil.getString(tagProperty[1]);
455             }
456 
457             if (Validator.isNotNull(key)) {
458                 assetTagPropertyLocalService.addTagProperty(
459                     userId, tagId, key, value);
460             }
461         }
462 
463         // Indexer
464 
465         if (!oldName.equals(name)) {
466             List<AssetEntry> entries = assetTagPersistence.getAssetEntries(
467                 tag.getTagId());
468 
469             reindex(entries);
470         }
471 
472         return tag;
473     }
474 
475     protected String[] getTagNames(List <AssetTag>tags) {
476         return StringUtil.split(ListUtil.toString(tags, "name"));
477     }
478 
479     protected void reindex(List<AssetEntry> entries) throws PortalException {
480         for (AssetEntry entry : entries) {
481             String className = PortalUtil.getClassName(entry.getClassNameId());
482 
483             Indexer indexer = IndexerRegistryUtil.getIndexer(className);
484 
485             indexer.reindex(className, entry.getClassPK());
486         }
487     }
488 
489     protected void validate(String name) throws PortalException {
490         if (!AssetUtil.isValidWord(name)) {
491             throw new AssetTagException(AssetTagException.INVALID_CHARACTER);
492         }
493     }
494 
495 }