1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   *
13   */
14  
15  package com.liferay.portlet.tags.service.impl;
16  
17  import com.liferay.portal.PortalException;
18  import com.liferay.portal.SystemException;
19  import com.liferay.portal.kernel.json.JSONArray;
20  import com.liferay.portal.kernel.search.Indexer;
21  import com.liferay.portal.kernel.search.IndexerRegistryUtil;
22  import com.liferay.portal.kernel.util.ArrayUtil;
23  import com.liferay.portal.kernel.util.GetterUtil;
24  import com.liferay.portal.kernel.util.ListUtil;
25  import com.liferay.portal.kernel.util.StringPool;
26  import com.liferay.portal.kernel.util.StringUtil;
27  import com.liferay.portal.kernel.util.Validator;
28  import com.liferay.portal.model.ResourceConstants;
29  import com.liferay.portal.model.User;
30  import com.liferay.portal.service.ServiceContext;
31  import com.liferay.portal.util.PortalUtil;
32  import com.liferay.portal.util.PropsValues;
33  import com.liferay.portlet.tags.DuplicateEntryException;
34  import com.liferay.portlet.tags.NoSuchEntryException;
35  import com.liferay.portlet.tags.NoSuchVocabularyException;
36  import com.liferay.portlet.tags.TagsEntryException;
37  import com.liferay.portlet.tags.model.TagsAsset;
38  import com.liferay.portlet.tags.model.TagsEntry;
39  import com.liferay.portlet.tags.model.TagsEntryConstants;
40  import com.liferay.portlet.tags.model.TagsProperty;
41  import com.liferay.portlet.tags.model.TagsVocabulary;
42  import com.liferay.portlet.tags.service.base.TagsEntryLocalServiceBaseImpl;
43  import com.liferay.portlet.tags.util.TagsUtil;
44  import com.liferay.util.Autocomplete;
45  
46  import java.util.ArrayList;
47  import java.util.Date;
48  import java.util.List;
49  
50  /**
51   * <a href="TagsEntryLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
52   *
53   * @author Brian Wing Shun Chan
54   * @author Alvaro del Castillo
55   * @author Jorge Ferrer
56   * @author Bruno Farache
57   */
58  public class TagsEntryLocalServiceImpl extends TagsEntryLocalServiceBaseImpl {
59  
60      public TagsEntry addEntry(
61              long userId, String parentEntryName, String name,
62              String vocabularyName, String[] properties,
63              ServiceContext serviceContext)
64          throws PortalException, SystemException {
65  
66          // Entry
67  
68          User user = userPersistence.findByPrimaryKey(userId);
69          long groupId = serviceContext.getScopeGroupId();
70  
71          if (Validator.isNull(vocabularyName)) {
72              vocabularyName = PropsValues.TAGS_VOCABULARY_DEFAULT;
73          }
74  
75          if (properties == null) {
76              properties = new String[0];
77          }
78  
79          Date now = new Date();
80  
81          long entryId = counterLocalService.increment();
82  
83          TagsEntry entry = tagsEntryPersistence.create(entryId);
84  
85          entry.setGroupId(groupId);
86          entry.setCompanyId(user.getCompanyId());
87          entry.setUserId(user.getUserId());
88          entry.setUserName(user.getFullName());
89          entry.setCreateDate(now);
90          entry.setModifiedDate(now);
91  
92          TagsVocabulary vocabulary = null;
93  
94          try {
95              vocabulary = tagsVocabularyPersistence.findByG_N(
96                  groupId, vocabularyName);
97          }
98          catch (NoSuchVocabularyException nsve) {
99              if (vocabularyName.equals(PropsValues.TAGS_VOCABULARY_DEFAULT)) {
100                 ServiceContext vocabularyServiceContext = new ServiceContext();
101 
102                 vocabularyServiceContext.setAddCommunityPermissions(true);
103                 vocabularyServiceContext.setAddGuestPermissions(true);
104                 vocabularyServiceContext.setScopeGroupId(groupId);
105 
106                 vocabulary = tagsVocabularyLocalService.addVocabulary(
107                     userId, vocabularyName, TagsEntryConstants.FOLKSONOMY_TAG,
108                     vocabularyServiceContext);
109             }
110             else {
111                 throw nsve;
112             }
113         }
114 
115         entry.setVocabularyId(vocabulary.getVocabularyId());
116 
117         boolean folksonomy = vocabulary.isFolksonomy();
118 
119         name = name.trim();
120 
121         if (folksonomy) {
122             name = name.toLowerCase();
123         }
124 
125         if (hasEntry(groupId, name, folksonomy)) {
126             throw new DuplicateEntryException(
127                 "A tag entry with the name " + name + " already exists");
128         }
129 
130         validate(name);
131 
132         entry.setName(name);
133 
134         if (Validator.isNotNull(parentEntryName)) {
135             TagsEntry parentEntry = getEntry(
136                 groupId, parentEntryName, folksonomy);
137 
138             entry.setParentEntryId(parentEntry.getEntryId());
139         }
140         else {
141             entry.setParentEntryId(TagsEntryConstants.DEFAULT_PARENT_ENTRY_ID);
142         }
143 
144         tagsEntryPersistence.update(entry, false);
145 
146         // Resources
147 
148         if (serviceContext.getAddCommunityPermissions() ||
149             serviceContext.getAddGuestPermissions()) {
150 
151             addEntryResources(
152                 entry, serviceContext.getAddCommunityPermissions(),
153                 serviceContext.getAddGuestPermissions());
154         }
155         else {
156             addEntryResources(
157                 entry, serviceContext.getCommunityPermissions(),
158                 serviceContext.getGuestPermissions());
159         }
160 
161         // Properties
162 
163         for (int i = 0; i < properties.length; i++) {
164             String[] property = StringUtil.split(
165                 properties[i], StringPool.COLON);
166 
167             String key = StringPool.BLANK;
168 
169             if (property.length > 1) {
170                 key = GetterUtil.getString(property[1]);
171             }
172 
173             String value = StringPool.BLANK;
174 
175             if (property.length > 2) {
176                 value = GetterUtil.getString(property[2]);
177             }
178 
179             if (Validator.isNotNull(key)) {
180                 tagsPropertyLocalService.addProperty(
181                     userId, entryId, key, value);
182             }
183         }
184 
185         return entry;
186     }
187 
188     public void addEntryResources(
189             TagsEntry entry, boolean addCommunityPermissions,
190             boolean addGuestPermissions)
191         throws PortalException, SystemException {
192 
193         resourceLocalService.addResources(
194             entry.getCompanyId(), entry.getGroupId(), entry.getUserId(),
195             TagsEntry.class.getName(), entry.getEntryId(), false,
196             addCommunityPermissions, addGuestPermissions);
197     }
198 
199     public void addEntryResources(
200             TagsEntry entry, String[] communityPermissions,
201             String[] guestPermissions)
202         throws PortalException, SystemException {
203 
204         resourceLocalService.addModelResources(
205             entry.getCompanyId(), entry.getGroupId(), entry.getUserId(),
206             TagsEntry.class.getName(), entry.getEntryId(), communityPermissions,
207             guestPermissions);
208     }
209 
210     public void checkEntries(long userId, long groupId, String[] names)
211         throws PortalException, SystemException {
212 
213         for (String name : names) {
214             try {
215                 getEntry(groupId, name, TagsEntryConstants.FOLKSONOMY_TAG);
216             }
217             catch (NoSuchEntryException nsee) {
218                 ServiceContext serviceContext = new ServiceContext();
219 
220                 serviceContext.setAddCommunityPermissions(true);
221                 serviceContext.setAddGuestPermissions(true);
222                 serviceContext.setScopeGroupId(groupId);
223 
224                 addEntry(
225                     userId, null, name, null,
226                     PropsValues.TAGS_PROPERTIES_DEFAULT, serviceContext);
227             }
228         }
229     }
230 
231     public void deleteEntry(long entryId)
232         throws PortalException, SystemException {
233 
234         TagsEntry entry = tagsEntryPersistence.findByPrimaryKey(entryId);
235 
236         deleteEntry(entry);
237     }
238 
239     public void deleteEntry(TagsEntry entry)
240         throws PortalException, SystemException {
241 
242         // Assets
243 
244         List<TagsAsset> assets =  tagsEntryPersistence.getTagsAssets(
245             entry.getEntryId());
246 
247         // Entry
248 
249         tagsEntryPersistence.remove(entry);
250 
251         // Resources
252 
253         resourceLocalService.deleteResource(
254             entry.getCompanyId(), TagsEntry.class.getName(),
255             ResourceConstants.SCOPE_INDIVIDUAL, entry.getEntryId());
256 
257         // Entries
258 
259         List<TagsEntry> childEntries = tagsEntryPersistence.findByP_V(
260             entry.getEntryId(), entry.getVocabularyId());
261 
262         for (TagsEntry childEntry : childEntries) {
263             deleteEntry(childEntry);
264         }
265 
266         // Properties
267 
268         tagsPropertyLocalService.deleteProperties(entry.getEntryId());
269 
270         // Indexer
271 
272         reIndex(assets);
273     }
274 
275     public void deleteVocabularyEntries(long vocabularyId)
276         throws PortalException, SystemException {
277 
278         List<TagsEntry> entries = tagsEntryPersistence.findByVocabularyId(
279             vocabularyId);
280 
281         for (TagsEntry entry : entries) {
282             deleteEntry(entry);
283         }
284     }
285 
286     public List<TagsEntry> getAssetEntries(long assetId, boolean folksonomy)
287         throws SystemException {
288 
289         return tagsEntryFinder.findByA_F(assetId, folksonomy);
290     }
291 
292     public List<TagsEntry> getEntries() throws SystemException {
293         return getEntries(TagsEntryConstants.FOLKSONOMY_TAG);
294     }
295 
296     public List<TagsEntry> getEntries(boolean folksonomy)
297         throws SystemException {
298 
299         return tagsEntryFinder.findByFolksonomy(folksonomy);
300     }
301 
302     public List<TagsEntry> getEntries(long classNameId, long classPK)
303         throws SystemException {
304 
305         return getEntries(
306             classNameId, classPK, TagsEntryConstants.FOLKSONOMY_TAG);
307     }
308 
309     public List<TagsEntry> getEntries(
310             long classNameId, long classPK, boolean folksonomy)
311         throws SystemException {
312 
313         return tagsEntryFinder.findByC_C_F(classNameId, classPK, folksonomy);
314     }
315 
316     public List<TagsEntry> getEntries(
317             long groupId, long classNameId, String name)
318         throws SystemException {
319 
320         return tagsEntryFinder.findByG_C_N_F(
321             groupId, classNameId, name, TagsEntryConstants.FOLKSONOMY_TAG);
322     }
323 
324     public List<TagsEntry> getEntries(
325             long groupId, long classNameId, String name, int start, int end)
326         throws SystemException {
327 
328         return tagsEntryFinder.findByG_C_N_F(
329             groupId, classNameId, name,
330             TagsEntryConstants.FOLKSONOMY_TAG, start, end);
331     }
332 
333     public List<TagsEntry> getEntries(String className, long classPK)
334         throws SystemException {
335 
336         return getEntries(
337             className, classPK, TagsEntryConstants.FOLKSONOMY_TAG);
338     }
339 
340     public List<TagsEntry> getEntries(
341             String className, long classPK, boolean folksonomy)
342         throws SystemException {
343 
344         long classNameId = PortalUtil.getClassNameId(className);
345 
346         return getEntries(classNameId, classPK, folksonomy);
347     }
348 
349     public int getEntriesSize(long groupId, long classNameId, String name)
350         throws SystemException {
351 
352         return tagsEntryFinder.countByG_C_N_F(
353             groupId, classNameId, name, TagsEntryConstants.FOLKSONOMY_TAG);
354     }
355 
356     public TagsEntry getEntry(long entryId)
357         throws PortalException, SystemException {
358 
359         return tagsEntryPersistence.findByPrimaryKey(entryId);
360     }
361 
362     public TagsEntry getEntry(long groupId, String name)
363         throws PortalException, SystemException {
364 
365         return getEntry(groupId, name, TagsEntryConstants.FOLKSONOMY_TAG);
366     }
367 
368     public TagsEntry getEntry(long groupId, String name, boolean folksonomy)
369         throws PortalException, SystemException {
370 
371         return tagsEntryFinder.findByG_N_F(groupId, name, folksonomy);
372     }
373 
374     public long[] getEntryIds(long groupId, String[] names)
375         throws PortalException, SystemException {
376 
377         return getEntryIds(groupId, names, TagsEntryConstants.FOLKSONOMY_TAG);
378     }
379 
380     public long[] getEntryIds(long groupId, String[] names, boolean folksonomy)
381         throws PortalException, SystemException {
382 
383         List<Long> entryIds = new ArrayList<Long>(names.length);
384 
385         for (String name : names) {
386             try {
387                 TagsEntry entry = getEntry(groupId, name, folksonomy);
388 
389                 entryIds.add(entry.getEntryId());
390             }
391             catch (NoSuchEntryException nsee) {
392             }
393         }
394 
395         return ArrayUtil.toArray(entryIds.toArray(new Long[entryIds.size()]));
396     }
397 
398     public String[] getEntryNames() throws SystemException {
399         return getEntryNames(TagsEntryConstants.FOLKSONOMY_TAG);
400     }
401 
402     public String[] getEntryNames(boolean folksonomy) throws SystemException {
403         return getEntryNames(getEntries(folksonomy));
404     }
405 
406     public String[] getEntryNames(long classNameId, long classPK)
407         throws SystemException {
408 
409         return getEntryNames(
410             classNameId, classPK, TagsEntryConstants.FOLKSONOMY_TAG);
411     }
412 
413     public String[] getEntryNames(
414             long classNameId, long classPK, boolean folksonomy)
415         throws SystemException {
416 
417         return getEntryNames(getEntries(classNameId, classPK, folksonomy));
418     }
419 
420     public String[] getEntryNames(String className, long classPK)
421         throws SystemException {
422 
423         return getEntryNames(
424             className, classPK, TagsEntryConstants.FOLKSONOMY_TAG);
425     }
426 
427     public String[] getEntryNames(
428             String className, long classPK, boolean folksonomy)
429         throws SystemException {
430 
431         return getEntryNames(getEntries(className, classPK, folksonomy));
432     }
433 
434     public List<TagsEntry> getGroupVocabularyEntries(
435             long groupId, String vocabularyName)
436         throws PortalException, SystemException {
437 
438         TagsVocabulary vocabulary =
439             tagsVocabularyLocalService.getGroupVocabulary(
440                 groupId, vocabularyName);
441 
442         return tagsEntryPersistence.findByVocabularyId(
443             vocabulary.getVocabularyId());
444     }
445 
446     public List<TagsEntry> getGroupVocabularyEntries(
447             long groupId, String parentEntryName, String vocabularyName)
448         throws PortalException, SystemException {
449 
450         TagsVocabulary vocabulary =
451             tagsVocabularyLocalService.getGroupVocabulary(
452                 groupId, vocabularyName);
453 
454         TagsEntry entry = getEntry(
455             groupId, parentEntryName, vocabulary.isFolksonomy());
456 
457         return tagsEntryPersistence.findByP_V(
458             entry.getEntryId(), vocabulary.getVocabularyId());
459     }
460 
461     public List<TagsEntry> getGroupVocabularyRootEntries(
462             long groupId, String vocabularyName)
463         throws PortalException, SystemException {
464 
465         TagsVocabulary vocabulary =
466             tagsVocabularyLocalService.getGroupVocabulary(
467                 groupId, vocabularyName);
468 
469         return tagsEntryPersistence.findByP_V(
470             TagsEntryConstants.DEFAULT_PARENT_ENTRY_ID,
471             vocabulary.getVocabularyId());
472     }
473 
474     public boolean hasEntry(long groupId, String name, boolean folksonomy)
475         throws PortalException, SystemException {
476 
477         try {
478             getEntry(groupId, name, folksonomy);
479 
480             return true;
481         }
482         catch (NoSuchEntryException nsee) {
483             return false;
484         }
485     }
486 
487     public void mergeEntries(long fromEntryId, long toEntryId)
488         throws PortalException, SystemException {
489 
490         List<TagsAsset> assets = tagsEntryPersistence.getTagsAssets(
491             fromEntryId);
492 
493         tagsEntryPersistence.addTagsAssets(toEntryId, assets);
494 
495         List<TagsProperty> properties = tagsPropertyPersistence.findByEntryId(
496             fromEntryId);
497 
498         for (TagsProperty fromProperty : properties) {
499             TagsProperty toProperty = tagsPropertyPersistence.fetchByE_K(
500                 toEntryId, fromProperty.getKey());
501 
502             if (toProperty == null) {
503                 fromProperty.setEntryId(toEntryId);
504 
505                 tagsPropertyPersistence.update(fromProperty, false);
506             }
507         }
508 
509         deleteEntry(fromEntryId);
510     }
511 
512     public JSONArray search(
513             long groupId, String name, String[] properties, int start, int end)
514         throws SystemException {
515 
516         List<TagsEntry> list = tagsEntryFinder.findByG_N_F_P(
517             groupId, name, TagsEntryConstants.FOLKSONOMY_TAG, properties, start,
518             end);
519 
520         return Autocomplete.listToJson(list, "name", "name");
521     }
522 
523     public TagsEntry updateEntry(
524             long userId, long entryId, String parentEntryName, String name,
525             String vocabularyName, String[] properties)
526         throws PortalException, SystemException {
527 
528         // Entry
529 
530         if (Validator.isNull(vocabularyName)) {
531             vocabularyName = PropsValues.TAGS_VOCABULARY_DEFAULT;
532         }
533 
534         TagsEntry entry = tagsEntryPersistence.findByPrimaryKey(entryId);
535 
536         String oldName = entry.getName();
537 
538         entry.setModifiedDate(new Date());
539 
540         TagsVocabulary vocabulary = null;
541 
542         try {
543             vocabulary = tagsVocabularyPersistence.findByG_N(
544                 entry.getGroupId(), vocabularyName);
545         }
546         catch (NoSuchVocabularyException nsve) {
547             if (vocabularyName.equals(PropsValues.TAGS_VOCABULARY_DEFAULT)) {
548                 ServiceContext vocabularyServiceContext = new ServiceContext();
549 
550                 vocabularyServiceContext.setAddCommunityPermissions(true);
551                 vocabularyServiceContext.setAddGuestPermissions(true);
552                 vocabularyServiceContext.setScopeGroupId(entry.getGroupId());
553 
554                 vocabulary = tagsVocabularyLocalService.addVocabulary(
555                     userId, vocabularyName, TagsEntryConstants.FOLKSONOMY_TAG,
556                     vocabularyServiceContext);
557             }
558             else {
559                 throw nsve;
560             }
561         }
562 
563         entry.setVocabularyId(vocabulary.getVocabularyId());
564 
565         boolean folksonomy = vocabulary.isFolksonomy();
566 
567         name = name.trim();
568 
569         if (folksonomy) {
570             name = name.toLowerCase();
571 
572             if (!entry.getName().equals(name) &&
573                 hasEntry(entry.getGroupId(), name, folksonomy)) {
574 
575                 throw new DuplicateEntryException(
576                     "A tag entry with the name " + name + " already exists");
577             }
578         }
579 
580         if (!entry.getName().equals(name)) {
581             try {
582                 TagsEntry existingEntry = getEntry(
583                     entry.getGroupId(), name, folksonomy);
584 
585                 if (existingEntry.getEntryId() != entryId) {
586                     throw new DuplicateEntryException(
587                         "A tag entry with the name " + name +
588                             " already exists");
589                 }
590             }
591             catch (NoSuchEntryException nsee) {
592             }
593         }
594 
595         validate(name);
596 
597         entry.setName(name);
598 
599         if (Validator.isNotNull(parentEntryName)) {
600             TagsEntry parentEntry = getEntry(
601                 entry.getGroupId(), parentEntryName, folksonomy);
602 
603             entry.setParentEntryId(parentEntry.getEntryId());
604         }
605         else {
606             entry.setParentEntryId(TagsEntryConstants.DEFAULT_PARENT_ENTRY_ID);
607         }
608 
609         tagsEntryPersistence.update(entry, false);
610 
611         // Properties
612 
613         List<TagsProperty> oldProperties =
614             tagsPropertyPersistence.findByEntryId(entryId);
615 
616         for (TagsProperty property : oldProperties) {
617             tagsPropertyLocalService.deleteProperty(property);
618         }
619 
620         for (int i = 0; i < properties.length; i++) {
621             String[] property = StringUtil.split(
622                 properties[i], StringPool.COLON);
623 
624             String key = StringPool.BLANK;
625 
626             if (property.length > 0) {
627                 key = GetterUtil.getString(property[0]);
628             }
629 
630             String value = StringPool.BLANK;
631 
632             if (property.length > 1) {
633                 value = GetterUtil.getString(property[1]);
634             }
635 
636             if (Validator.isNotNull(key)) {
637                 tagsPropertyLocalService.addProperty(
638                     userId, entryId, key, value);
639             }
640         }
641 
642         // Indexer
643 
644         if (!oldName.equals(name)) {
645             List<TagsAsset> assets =  tagsEntryPersistence.getTagsAssets(
646                 entry.getEntryId());
647 
648             reIndex(assets);
649         }
650 
651         return entry;
652     }
653 
654     protected String[] getEntryNames(List <TagsEntry>entries) {
655         return StringUtil.split(ListUtil.toString(entries, "name"));
656     }
657 
658     protected void reIndex(List<TagsAsset> assets) throws PortalException {
659         for (TagsAsset asset : assets) {
660             String className = PortalUtil.getClassName(asset.getClassNameId());
661 
662             Indexer indexer = IndexerRegistryUtil.getIndexer(className);
663 
664             indexer.reIndex(className, asset.getClassPK());
665         }
666     }
667 
668     protected void validate(String name) throws PortalException {
669         if (!TagsUtil.isValidWord(name)) {
670             throw new TagsEntryException(TagsEntryException.INVALID_CHARACTER);
671         }
672     }
673 
674 }