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