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