001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.asset.service.impl;
016    
017    import com.liferay.portal.kernel.cache.ThreadLocalCachable;
018    import com.liferay.portal.kernel.exception.PortalException;
019    import com.liferay.portal.kernel.exception.SystemException;
020    import com.liferay.portal.kernel.transaction.TransactionCommitCallbackRegistryUtil;
021    import com.liferay.portal.kernel.util.CharPool;
022    import com.liferay.portal.kernel.util.GetterUtil;
023    import com.liferay.portal.kernel.util.ListUtil;
024    import com.liferay.portal.kernel.util.LocaleUtil;
025    import com.liferay.portal.kernel.util.OrderByComparator;
026    import com.liferay.portal.kernel.util.StringBundler;
027    import com.liferay.portal.kernel.util.StringPool;
028    import com.liferay.portal.kernel.util.StringUtil;
029    import com.liferay.portal.kernel.util.Validator;
030    import com.liferay.portal.model.ModelHintsUtil;
031    import com.liferay.portal.model.ResourceConstants;
032    import com.liferay.portal.model.User;
033    import com.liferay.portal.service.ServiceContext;
034    import com.liferay.portal.util.PortalUtil;
035    import com.liferay.portlet.asset.AssetCategoryNameException;
036    import com.liferay.portlet.asset.DuplicateCategoryException;
037    import com.liferay.portlet.asset.model.AssetCategory;
038    import com.liferay.portlet.asset.model.AssetCategoryConstants;
039    import com.liferay.portlet.asset.model.AssetCategoryProperty;
040    import com.liferay.portlet.asset.model.AssetEntry;
041    import com.liferay.portlet.asset.service.base.AssetCategoryLocalServiceBaseImpl;
042    
043    import java.util.Collections;
044    import java.util.Date;
045    import java.util.HashMap;
046    import java.util.Iterator;
047    import java.util.List;
048    import java.util.Locale;
049    import java.util.Map;
050    import java.util.concurrent.Callable;
051    
052    /**
053     * Provides the local service for accessing, adding, deleting, merging, moving,
054     * and updating asset categories.
055     *
056     * @author Brian Wing Shun Chan
057     * @author Alvaro del Castillo
058     * @author Jorge Ferrer
059     * @author Bruno Farache
060     */
061    public class AssetCategoryLocalServiceImpl
062            extends AssetCategoryLocalServiceBaseImpl {
063    
064            public AssetCategory addCategory(
065                            long userId, long parentCategoryId, Map<Locale, String> titleMap,
066                            Map<Locale, String> descriptionMap, long vocabularyId,
067                            String[] categoryProperties, ServiceContext serviceContext)
068                    throws PortalException, SystemException {
069    
070                    // Category
071    
072                    User user = userPersistence.findByPrimaryKey(userId);
073                    long groupId = serviceContext.getScopeGroupId();
074    
075                    String name = titleMap.get(LocaleUtil.getDefault());
076    
077                    name = ModelHintsUtil.trimString(
078                            AssetCategory.class.getName(), "name", name);
079    
080                    if (categoryProperties == null) {
081                            categoryProperties = new String[0];
082                    }
083    
084                    Date now = new Date();
085    
086                    validate(0, parentCategoryId, name, vocabularyId);
087    
088                    if (parentCategoryId > 0) {
089                            assetCategoryPersistence.findByPrimaryKey(parentCategoryId);
090                    }
091    
092                    assetVocabularyPersistence.findByPrimaryKey(vocabularyId);
093    
094                    long categoryId = counterLocalService.increment();
095    
096                    AssetCategory category = assetCategoryPersistence.create(categoryId);
097    
098                    category.setUuid(serviceContext.getUuid());
099                    category.setGroupId(groupId);
100                    category.setCompanyId(user.getCompanyId());
101                    category.setUserId(user.getUserId());
102                    category.setUserName(user.getFullName());
103                    category.setCreateDate(now);
104                    category.setModifiedDate(now);
105                    category.setParentCategoryId(parentCategoryId);
106                    category.setName(name);
107                    category.setTitleMap(titleMap);
108                    category.setDescriptionMap(descriptionMap);
109                    category.setVocabularyId(vocabularyId);
110    
111                    assetCategoryPersistence.update(category);
112    
113                    // Resources
114    
115                    if (serviceContext.isAddGroupPermissions() ||
116                            serviceContext.isAddGuestPermissions()) {
117    
118                            addCategoryResources(
119                                    category, serviceContext.isAddGroupPermissions(),
120                                    serviceContext.isAddGuestPermissions());
121                    }
122                    else {
123                            addCategoryResources(
124                                    category, serviceContext.getGroupPermissions(),
125                                    serviceContext.getGuestPermissions());
126                    }
127    
128                    // Properties
129    
130                    for (int i = 0; i < categoryProperties.length; i++) {
131                            String[] categoryProperty = StringUtil.split(
132                                    categoryProperties[i], CharPool.COLON);
133    
134                            String key = StringPool.BLANK;
135                            String value = StringPool.BLANK;
136    
137                            if (categoryProperty.length > 1) {
138                                    key = GetterUtil.getString(categoryProperty[0]);
139                                    value = GetterUtil.getString(categoryProperty[1]);
140                            }
141    
142                            if (Validator.isNotNull(key)) {
143                                    assetCategoryPropertyLocalService.addCategoryProperty(
144                                            userId, categoryId, key, value);
145                            }
146                    }
147    
148                    return category;
149            }
150    
151            public AssetCategory addCategory(
152                            long userId, String title, long vocabularyId,
153                            ServiceContext serviceContext)
154                    throws PortalException, SystemException {
155    
156                    Map<Locale, String> titleMap = new HashMap<Locale, String>();
157    
158                    Locale locale = LocaleUtil.getDefault();
159    
160                    titleMap.put(locale, title);
161    
162                    Map<Locale, String> descriptionMap = new HashMap<Locale, String>();
163    
164                    descriptionMap.put(locale, StringPool.BLANK);
165    
166                    return addCategory(
167                            userId, AssetCategoryConstants.DEFAULT_PARENT_CATEGORY_ID, titleMap,
168                            descriptionMap, vocabularyId, null, serviceContext);
169            }
170    
171            public void addCategoryResources(
172                            AssetCategory category, boolean addGroupPermissions,
173                            boolean addGuestPermissions)
174                    throws PortalException, SystemException {
175    
176                    resourceLocalService.addResources(
177                            category.getCompanyId(), category.getGroupId(),
178                            category.getUserId(), AssetCategory.class.getName(),
179                            category.getCategoryId(), false, addGroupPermissions,
180                            addGuestPermissions);
181            }
182    
183            public void addCategoryResources(
184                            AssetCategory category, String[] groupPermissions,
185                            String[] guestPermissions)
186                    throws PortalException, SystemException {
187    
188                    resourceLocalService.addModelResources(
189                            category.getCompanyId(), category.getGroupId(),
190                            category.getUserId(), AssetCategory.class.getName(),
191                            category.getCategoryId(), groupPermissions, guestPermissions);
192            }
193    
194            public void deleteCategory(AssetCategory category)
195                    throws PortalException, SystemException {
196    
197                    deleteCategory(category, false);
198            }
199    
200            public void deleteCategory(long categoryId)
201                    throws PortalException, SystemException {
202    
203                    AssetCategory category = assetCategoryPersistence.findByPrimaryKey(
204                            categoryId);
205    
206                    deleteCategory(category);
207            }
208    
209            public void deleteVocabularyCategories(long vocabularyId)
210                    throws PortalException, SystemException {
211    
212                    List<AssetCategory> categories =
213                            assetCategoryPersistence.findByVocabularyId(vocabularyId);
214    
215                    for (AssetCategory category : categories) {
216                            if (category.getParentCategoryId() ==
217                                            AssetCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
218    
219                                    deleteCategory(category.getCategoryId());
220                            }
221                    }
222            }
223    
224            public AssetCategory fetchCategory(long categoryId) throws SystemException {
225                    return assetCategoryPersistence.fetchByPrimaryKey(categoryId);
226            }
227    
228            public List<AssetCategory> getCategories() throws SystemException {
229                    return assetCategoryPersistence.findAll();
230            }
231    
232            @ThreadLocalCachable
233            public List<AssetCategory> getCategories(long classNameId, long classPK)
234                    throws SystemException {
235    
236                    AssetEntry entry = assetEntryPersistence.fetchByC_C(
237                            classNameId, classPK);
238    
239                    if (entry == null) {
240                            return Collections.emptyList();
241                    }
242    
243                    return assetEntryPersistence.getAssetCategories(entry.getEntryId());
244            }
245    
246            public List<AssetCategory> getCategories(String className, long classPK)
247                    throws SystemException {
248    
249                    long classNameId = PortalUtil.getClassNameId(className);
250    
251                    return getCategories(classNameId, classPK);
252            }
253    
254            public AssetCategory getCategory(long categoryId)
255                    throws PortalException, SystemException {
256    
257                    return assetCategoryPersistence.findByPrimaryKey(categoryId);
258            }
259    
260            public AssetCategory getCategory(String uuid, long groupId)
261                    throws PortalException, SystemException {
262    
263                    return assetCategoryPersistence.findByUUID_G(uuid, groupId);
264            }
265    
266            public long[] getCategoryIds(String className, long classPK)
267                    throws SystemException {
268    
269                    return getCategoryIds(getCategories(className, classPK));
270            }
271    
272            public String[] getCategoryNames() throws SystemException {
273                    return getCategoryNames(getCategories());
274            }
275    
276            public String[] getCategoryNames(long classNameId, long classPK)
277                    throws SystemException {
278    
279                    return getCategoryNames(getCategories(classNameId, classPK));
280            }
281    
282            public String[] getCategoryNames(String className, long classPK)
283                    throws SystemException {
284    
285                    return getCategoryNames(getCategories(className, classPK));
286            }
287    
288            public List<AssetCategory> getChildCategories(long parentCategoryId)
289                    throws SystemException {
290    
291                    return assetCategoryPersistence.findByParentCategoryId(
292                            parentCategoryId);
293            }
294    
295            public List<AssetCategory> getChildCategories(
296                            long parentCategoryId, int start, int end, OrderByComparator obc)
297                    throws SystemException {
298    
299                    return assetCategoryPersistence.findByParentCategoryId(
300                            parentCategoryId, start, end, obc);
301            }
302    
303            public int getChildCategoriesCount(long parentCategoryId)
304                    throws SystemException {
305    
306                    return assetCategoryPersistence.countByParentCategoryId(
307                            parentCategoryId);
308            }
309    
310            public List<AssetCategory> getEntryCategories(long entryId)
311                    throws SystemException {
312    
313                    return assetEntryPersistence.getAssetCategories(entryId);
314            }
315    
316            public List<Long> getSubcategoryIds(long parentCategoryId)
317                    throws SystemException {
318    
319                    return assetCategoryFinder.findByG_L(parentCategoryId);
320            }
321    
322            public List<AssetCategory> getVocabularyCategories(
323                            long vocabularyId, int start, int end, OrderByComparator obc)
324                    throws SystemException {
325    
326                    return assetCategoryPersistence.findByVocabularyId(
327                            vocabularyId, start, end, obc);
328            }
329    
330            public List<AssetCategory> getVocabularyCategories(
331                            long parentCategoryId, long vocabularyId, int start, int end,
332                            OrderByComparator obc)
333                    throws SystemException {
334    
335                    return assetCategoryPersistence.findByP_V(
336                            parentCategoryId, vocabularyId, start, end, obc);
337            }
338    
339            public int getVocabularyCategoriesCount(long vocabularyId)
340                    throws SystemException {
341    
342                    return assetCategoryPersistence.countByVocabularyId(vocabularyId);
343            }
344    
345            public List<AssetCategory> getVocabularyRootCategories(
346                            long vocabularyId, int start, int end, OrderByComparator obc)
347                    throws SystemException {
348    
349                    return getVocabularyCategories(
350                            AssetCategoryConstants.DEFAULT_PARENT_CATEGORY_ID, vocabularyId,
351                            start, end, obc);
352            }
353    
354            public int getVocabularyRootCategoriesCount(long vocabularyId)
355                    throws SystemException {
356    
357                    return assetCategoryPersistence.countByP_V(
358                            AssetCategoryConstants.DEFAULT_PARENT_CATEGORY_ID, vocabularyId);
359            }
360    
361            public void mergeCategories(long fromCategoryId, long toCategoryId)
362                    throws PortalException, SystemException {
363    
364                    List<AssetEntry> entries = assetCategoryPersistence.getAssetEntries(
365                            fromCategoryId);
366    
367                    assetCategoryPersistence.addAssetEntries(toCategoryId, entries);
368    
369                    List<AssetCategoryProperty> categoryProperties =
370                            assetCategoryPropertyPersistence.findByCategoryId(fromCategoryId);
371    
372                    for (AssetCategoryProperty fromCategoryProperty : categoryProperties) {
373                            AssetCategoryProperty toCategoryProperty =
374                                    assetCategoryPropertyPersistence.fetchByCA_K(
375                                            toCategoryId, fromCategoryProperty.getKey());
376    
377                            if (toCategoryProperty == null) {
378                                    fromCategoryProperty.setCategoryId(toCategoryId);
379    
380                                    assetCategoryPropertyPersistence.update(fromCategoryProperty);
381                            }
382                    }
383    
384                    deleteCategory(fromCategoryId);
385            }
386    
387            public AssetCategory moveCategory(
388                            long categoryId, long parentCategoryId, long vocabularyId,
389                            ServiceContext serviceContext)
390                    throws PortalException, SystemException {
391    
392                    AssetCategory category = assetCategoryPersistence.findByPrimaryKey(
393                            categoryId);
394    
395                    validate(
396                            categoryId, parentCategoryId, category.getName(), vocabularyId);
397    
398                    if (parentCategoryId > 0) {
399                            assetCategoryPersistence.findByPrimaryKey(parentCategoryId);
400                    }
401    
402                    if (vocabularyId != category.getVocabularyId()) {
403                            assetVocabularyPersistence.findByPrimaryKey(vocabularyId);
404    
405                            category.setVocabularyId(vocabularyId);
406    
407                            updateChildrenVocabularyId(category, vocabularyId);
408                    }
409    
410                    category.setModifiedDate(new Date());
411                    category.setParentCategoryId(parentCategoryId);
412    
413                    assetCategoryPersistence.update(category);
414    
415                    return category;
416            }
417    
418            public void rebuildTree(long groupId, boolean force)
419                    throws SystemException {
420    
421                    assetCategoryPersistence.rebuildTree(groupId, force);
422            }
423    
424            public List<AssetCategory> search(
425                            long groupId, String name, String[] categoryProperties, int start,
426                            int end)
427                    throws SystemException {
428    
429                    return assetCategoryFinder.findByG_N_P(
430                            groupId, name, categoryProperties, start, end);
431            }
432    
433            public AssetCategory updateCategory(
434                            long userId, long categoryId, long parentCategoryId,
435                            Map<Locale, String> titleMap, Map<Locale, String> descriptionMap,
436                            long vocabularyId, String[] categoryProperties,
437                            ServiceContext serviceContext)
438                    throws PortalException, SystemException {
439    
440                    // Category
441    
442                    String name = titleMap.get(LocaleUtil.getDefault());
443    
444                    name = ModelHintsUtil.trimString(
445                            AssetCategory.class.getName(), "name", name);
446    
447                    if (categoryProperties == null) {
448                            categoryProperties = new String[0];
449                    }
450    
451                    validate(categoryId, parentCategoryId, name, vocabularyId);
452    
453                    if (parentCategoryId > 0) {
454                            assetCategoryPersistence.findByPrimaryKey(parentCategoryId);
455                    }
456    
457                    AssetCategory category = assetCategoryPersistence.findByPrimaryKey(
458                            categoryId);
459    
460                    String oldName = category.getName();
461    
462                    if (vocabularyId != category.getVocabularyId()) {
463                            assetVocabularyPersistence.findByPrimaryKey(vocabularyId);
464    
465                            parentCategoryId =
466                                    AssetCategoryConstants.DEFAULT_PARENT_CATEGORY_ID;
467    
468                            category.setVocabularyId(vocabularyId);
469    
470                            updateChildrenVocabularyId(category, vocabularyId);
471                    }
472    
473                    category.setModifiedDate(new Date());
474                    category.setParentCategoryId(parentCategoryId);
475                    category.setName(name);
476                    category.setTitleMap(titleMap);
477                    category.setDescriptionMap(descriptionMap);
478    
479                    assetCategoryPersistence.update(category);
480    
481                    // Properties
482    
483                    List<AssetCategoryProperty> oldCategoryProperties =
484                            assetCategoryPropertyPersistence.findByCategoryId(categoryId);
485    
486                    for (int i = 0; i < categoryProperties.length; i++) {
487                            String[] categoryProperty = StringUtil.split(
488                                    categoryProperties[i], CharPool.COLON);
489    
490                            String key = StringPool.BLANK;
491    
492                            if (categoryProperty.length > 0) {
493                                    key = GetterUtil.getString(categoryProperty[0]);
494                            }
495    
496                            String value = StringPool.BLANK;
497    
498                            if (categoryProperty.length > 1) {
499                                    value = GetterUtil.getString(categoryProperty[1]);
500                            }
501    
502                            if (Validator.isNotNull(key)) {
503                                    boolean addCategoryProperty = true;
504    
505                                    Iterator<AssetCategoryProperty> iterator =
506                                            oldCategoryProperties.iterator();
507    
508                                    while (iterator.hasNext()) {
509                                            AssetCategoryProperty oldCategoryProperty = iterator.next();
510    
511                                            if ((userId == oldCategoryProperty.getUserId()) &&
512                                                    (categoryId == oldCategoryProperty.getCategoryId()) &&
513                                                    key.equals(oldCategoryProperty.getKey()) &&
514                                                    value.equals(oldCategoryProperty.getValue())) {
515    
516                                                    addCategoryProperty = false;
517    
518                                                    iterator.remove();
519    
520                                                    break;
521                                            }
522                                    }
523    
524                                    if (addCategoryProperty) {
525                                            assetCategoryPropertyLocalService.addCategoryProperty(
526                                                    userId, categoryId, key, value);
527                                    }
528                            }
529                    }
530    
531                    for (AssetCategoryProperty categoryProperty : oldCategoryProperties) {
532                            assetCategoryPropertyLocalService.deleteAssetCategoryProperty(
533                                    categoryProperty);
534                    }
535    
536                    // Indexer
537    
538                    if (!oldName.equals(name)) {
539                            List<AssetEntry> entries = assetCategoryPersistence.getAssetEntries(
540                                    category.getCategoryId());
541    
542                            assetEntryLocalService.reindex(entries);
543                    }
544    
545                    return category;
546            }
547    
548            protected void deleteCategory(AssetCategory category, boolean childCategory)
549                    throws PortalException, SystemException {
550    
551                    // Categories
552    
553                    List<AssetCategory> categories =
554                            assetCategoryPersistence.findByParentCategoryId(
555                                    category.getCategoryId());
556    
557                    for (AssetCategory curCategory : categories) {
558                            deleteCategory(curCategory, true);
559                    }
560    
561                    if (!categories.isEmpty() && !childCategory) {
562                            final long groupId = category.getGroupId();
563    
564                            TransactionCommitCallbackRegistryUtil.registerCallback(
565                                    new Callable<Void>() {
566    
567                                            public Void call() throws Exception {
568                                                    assetCategoryLocalService.rebuildTree(groupId, true);
569    
570                                                    return null;
571                                            }
572    
573                                    });
574                    }
575    
576                    // Category
577    
578                    assetCategoryPersistence.remove(category);
579    
580                    // Resources
581    
582                    resourceLocalService.deleteResource(
583                            category.getCompanyId(), AssetCategory.class.getName(),
584                            ResourceConstants.SCOPE_INDIVIDUAL, category.getCategoryId());
585    
586                    // Entries
587    
588                    List<AssetEntry> entries = assetTagPersistence.getAssetEntries(
589                            category.getCategoryId());
590    
591                    // Properties
592    
593                    assetCategoryPropertyLocalService.deleteCategoryProperties(
594                            category.getCategoryId());
595    
596                    // Indexer
597    
598                    assetEntryLocalService.reindex(entries);
599            }
600    
601            protected long[] getCategoryIds(List<AssetCategory> categories) {
602                    return StringUtil.split(
603                            ListUtil.toString(categories, AssetCategory.CATEGORY_ID_ACCESSOR),
604                            0L);
605            }
606    
607            protected String[] getCategoryNames(List<AssetCategory> categories) {
608                    return StringUtil.split(
609                            ListUtil.toString(categories, AssetCategory.NAME_ACCESSOR));
610            }
611    
612            protected void updateChildrenVocabularyId(
613                            AssetCategory category, long vocabularyId)
614                    throws SystemException {
615    
616                    List<AssetCategory> childrenCategories =
617                            assetCategoryPersistence.findByParentCategoryId(
618                                    category.getCategoryId());
619    
620                    if (!childrenCategories.isEmpty()) {
621                            for (AssetCategory childCategory : childrenCategories) {
622                                    childCategory.setVocabularyId(vocabularyId);
623                                    childCategory.setModifiedDate(new Date());
624    
625                                    assetCategoryPersistence.update(childCategory);
626    
627                                    updateChildrenVocabularyId (childCategory, vocabularyId);
628                            }
629                    }
630            }
631    
632            protected void validate(
633                            long categoryId, long parentCategoryId, String name,
634                            long vocabularyId)
635                    throws PortalException, SystemException {
636    
637                    if (Validator.isNull(name)) {
638                            throw new AssetCategoryNameException();
639                    }
640    
641                    AssetCategory category = assetCategoryPersistence.fetchByP_N_V(
642                            parentCategoryId, name, vocabularyId);
643    
644                    if ((category != null) && (category.getCategoryId() != categoryId)) {
645                            StringBundler sb = new StringBundler(4);
646    
647                            sb.append("There is another category named ");
648                            sb.append(name);
649                            sb.append(" as a child of category ");
650                            sb.append(parentCategoryId);
651    
652                            throw new DuplicateCategoryException(sb.toString());
653                    }
654            }
655    
656    }