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