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