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