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