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