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