001    /**
002     * Copyright (c) 2000-present 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.dao.orm.QueryUtil;
019    import com.liferay.portal.kernel.exception.PortalException;
020    import com.liferay.portal.kernel.search.BaseModelSearchResult;
021    import com.liferay.portal.kernel.search.Field;
022    import com.liferay.portal.kernel.search.Hits;
023    import com.liferay.portal.kernel.search.Indexable;
024    import com.liferay.portal.kernel.search.IndexableType;
025    import com.liferay.portal.kernel.search.Indexer;
026    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
027    import com.liferay.portal.kernel.search.QueryConfig;
028    import com.liferay.portal.kernel.search.SearchContext;
029    import com.liferay.portal.kernel.search.SearchException;
030    import com.liferay.portal.kernel.systemevent.SystemEvent;
031    import com.liferay.portal.kernel.transaction.TransactionCommitCallbackRegistryUtil;
032    import com.liferay.portal.kernel.util.CharPool;
033    import com.liferay.portal.kernel.util.GetterUtil;
034    import com.liferay.portal.kernel.util.ListUtil;
035    import com.liferay.portal.kernel.util.LocaleUtil;
036    import com.liferay.portal.kernel.util.OrderByComparator;
037    import com.liferay.portal.kernel.util.StringBundler;
038    import com.liferay.portal.kernel.util.StringPool;
039    import com.liferay.portal.kernel.util.StringUtil;
040    import com.liferay.portal.kernel.util.Validator;
041    import com.liferay.portal.model.ModelHintsUtil;
042    import com.liferay.portal.model.ResourceConstants;
043    import com.liferay.portal.model.SystemEventConstants;
044    import com.liferay.portal.model.User;
045    import com.liferay.portal.service.ServiceContext;
046    import com.liferay.portlet.asset.AssetCategoryNameException;
047    import com.liferay.portlet.asset.DuplicateCategoryException;
048    import com.liferay.portlet.asset.model.AssetCategory;
049    import com.liferay.portlet.asset.model.AssetCategoryConstants;
050    import com.liferay.portlet.asset.model.AssetCategoryProperty;
051    import com.liferay.portlet.asset.model.AssetEntry;
052    import com.liferay.portlet.asset.service.base.AssetCategoryLocalServiceBaseImpl;
053    import com.liferay.portlet.asset.util.AssetCategoryUtil;
054    import com.liferay.portlet.asset.util.comparator.AssetCategoryLeftCategoryIdComparator;
055    
056    import java.io.Serializable;
057    
058    import java.util.Collections;
059    import java.util.Date;
060    import java.util.HashMap;
061    import java.util.Iterator;
062    import java.util.List;
063    import java.util.Locale;
064    import java.util.Map;
065    import java.util.concurrent.Callable;
066    
067    /**
068     * Provides the local service for accessing, adding, deleting, merging, moving,
069     * and updating asset categories.
070     *
071     * @author Brian Wing Shun Chan
072     * @author Alvaro del Castillo
073     * @author Jorge Ferrer
074     * @author Bruno Farache
075     */
076    public class AssetCategoryLocalServiceImpl
077            extends AssetCategoryLocalServiceBaseImpl {
078    
079            @Indexable(type = IndexableType.REINDEX)
080            @Override
081            public AssetCategory addCategory(
082                            long userId, long parentCategoryId, Map<Locale, String> titleMap,
083                            Map<Locale, String> descriptionMap, long vocabularyId,
084                            String[] categoryProperties, ServiceContext serviceContext)
085                    throws PortalException {
086    
087                    // Category
088    
089                    User user = userPersistence.findByPrimaryKey(userId);
090                    long groupId = serviceContext.getScopeGroupId();
091    
092                    String name = titleMap.get(LocaleUtil.getSiteDefault());
093    
094                    name = ModelHintsUtil.trimString(
095                            AssetCategory.class.getName(), "name", name);
096    
097                    if (categoryProperties == null) {
098                            categoryProperties = new String[0];
099                    }
100    
101                    Date now = new Date();
102    
103                    validate(0, parentCategoryId, name, vocabularyId);
104    
105                    if (parentCategoryId > 0) {
106                            assetCategoryPersistence.findByPrimaryKey(parentCategoryId);
107                    }
108    
109                    assetVocabularyPersistence.findByPrimaryKey(vocabularyId);
110    
111                    long categoryId = counterLocalService.increment();
112    
113                    AssetCategory category = assetCategoryPersistence.create(categoryId);
114    
115                    category.setUuid(serviceContext.getUuid());
116                    category.setGroupId(groupId);
117                    category.setCompanyId(user.getCompanyId());
118                    category.setUserId(user.getUserId());
119                    category.setUserName(user.getFullName());
120                    category.setCreateDate(now);
121                    category.setModifiedDate(now);
122                    category.setParentCategoryId(parentCategoryId);
123                    category.setName(name);
124                    category.setTitleMap(titleMap);
125                    category.setDescriptionMap(descriptionMap);
126                    category.setVocabularyId(vocabularyId);
127    
128                    assetCategoryPersistence.update(category);
129    
130                    // Resources
131    
132                    if (serviceContext.isAddGroupPermissions() ||
133                            serviceContext.isAddGuestPermissions()) {
134    
135                            addCategoryResources(
136                                    category, serviceContext.isAddGroupPermissions(),
137                                    serviceContext.isAddGuestPermissions());
138                    }
139                    else {
140                            addCategoryResources(
141                                    category, serviceContext.getGroupPermissions(),
142                                    serviceContext.getGuestPermissions());
143                    }
144    
145                    // Properties
146    
147                    for (int i = 0; i < categoryProperties.length; i++) {
148                            String[] categoryProperty = StringUtil.split(
149                                    categoryProperties[i],
150                                    AssetCategoryConstants.PROPERTY_KEY_VALUE_SEPARATOR);
151    
152                            if (categoryProperty.length <= 1) {
153                                    categoryProperty = StringUtil.split(
154                                            categoryProperties[i], CharPool.COLON);
155                            }
156    
157                            String key = StringPool.BLANK;
158                            String value = StringPool.BLANK;
159    
160                            if (categoryProperty.length > 1) {
161                                    key = GetterUtil.getString(categoryProperty[0]);
162                                    value = GetterUtil.getString(categoryProperty[1]);
163                            }
164    
165                            if (Validator.isNotNull(key)) {
166                                    assetCategoryPropertyLocalService.addCategoryProperty(
167                                            userId, categoryId, key, value);
168                            }
169                    }
170    
171                    return category;
172            }
173    
174            @Override
175            public AssetCategory addCategory(
176                            long userId, String title, long vocabularyId,
177                            ServiceContext serviceContext)
178                    throws PortalException {
179    
180                    Map<Locale, String> titleMap = new HashMap<Locale, String>();
181    
182                    Locale locale = LocaleUtil.getSiteDefault();
183    
184                    titleMap.put(locale, title);
185    
186                    Map<Locale, String> descriptionMap = new HashMap<Locale, String>();
187    
188                    descriptionMap.put(locale, StringPool.BLANK);
189    
190                    return assetCategoryLocalService.addCategory(
191                            userId, AssetCategoryConstants.DEFAULT_PARENT_CATEGORY_ID, titleMap,
192                            descriptionMap, vocabularyId, null, serviceContext);
193            }
194    
195            @Override
196            public void addCategoryResources(
197                            AssetCategory category, boolean addGroupPermissions,
198                            boolean addGuestPermissions)
199                    throws PortalException {
200    
201                    resourceLocalService.addResources(
202                            category.getCompanyId(), category.getGroupId(),
203                            category.getUserId(), AssetCategory.class.getName(),
204                            category.getCategoryId(), false, addGroupPermissions,
205                            addGuestPermissions);
206            }
207    
208            @Override
209            public void addCategoryResources(
210                            AssetCategory category, String[] groupPermissions,
211                            String[] guestPermissions)
212                    throws PortalException {
213    
214                    resourceLocalService.addModelResources(
215                            category.getCompanyId(), category.getGroupId(),
216                            category.getUserId(), AssetCategory.class.getName(),
217                            category.getCategoryId(), groupPermissions, guestPermissions);
218            }
219    
220            @Override
221            @SystemEvent(type = SystemEventConstants.TYPE_DELETE)
222            public AssetCategory deleteCategory(AssetCategory category)
223                    throws PortalException {
224    
225                    return assetCategoryLocalService.deleteCategory(category, false);
226            }
227    
228            @Indexable(type = IndexableType.DELETE)
229            @Override
230            public AssetCategory deleteCategory(
231                            AssetCategory category, boolean childCategory)
232                    throws PortalException {
233    
234                    // Categories
235    
236                    List<AssetCategory> categories =
237                            assetCategoryPersistence.findByParentCategoryId(
238                                    category.getCategoryId());
239    
240                    for (AssetCategory curCategory : categories) {
241                            deleteCategory(curCategory, true);
242                    }
243    
244                    if (!categories.isEmpty() && !childCategory) {
245                            final long groupId = category.getGroupId();
246    
247                            TransactionCommitCallbackRegistryUtil.registerCallback(
248                                    new Callable<Void>() {
249    
250                                            @Override
251                                            public Void call() throws Exception {
252                                                    assetCategoryLocalService.rebuildTree(groupId, true);
253    
254                                                    return null;
255                                            }
256    
257                                    });
258                    }
259    
260                    // Category
261    
262                    assetCategoryPersistence.remove(category);
263    
264                    // Resources
265    
266                    resourceLocalService.deleteResource(
267                            category.getCompanyId(), AssetCategory.class.getName(),
268                            ResourceConstants.SCOPE_INDIVIDUAL, category.getCategoryId());
269    
270                    // Entries
271    
272                    List<AssetEntry> entries = assetCategoryPersistence.getAssetEntries(
273                            category.getCategoryId());
274    
275                    // Properties
276    
277                    assetCategoryPropertyLocalService.deleteCategoryProperties(
278                            category.getCategoryId());
279    
280                    // Indexer
281    
282                    assetEntryLocalService.reindex(entries);
283    
284                    return category;
285            }
286    
287            @Override
288            public AssetCategory deleteCategory(long categoryId)
289                    throws PortalException {
290    
291                    AssetCategory category = assetCategoryPersistence.findByPrimaryKey(
292                            categoryId);
293    
294                    return assetCategoryLocalService.deleteCategory(category);
295            }
296    
297            @Override
298            public void deleteVocabularyCategories(long vocabularyId)
299                    throws PortalException {
300    
301                    List<AssetCategory> categories =
302                            assetCategoryPersistence.findByP_V(
303                                    AssetCategoryConstants.DEFAULT_PARENT_CATEGORY_ID, vocabularyId,
304                                    QueryUtil.ALL_POS, QueryUtil.ALL_POS,
305                                    new AssetCategoryLeftCategoryIdComparator(false));
306    
307                    for (AssetCategory category : categories) {
308                            assetCategoryLocalService.deleteCategory(category);
309                    }
310            }
311    
312            @Override
313            public AssetCategory fetchCategory(long categoryId) {
314                    return assetCategoryPersistence.fetchByPrimaryKey(categoryId);
315            }
316    
317            @Override
318            public List<AssetCategory> getCategories() {
319                    return assetCategoryPersistence.findAll();
320            }
321    
322            @Override
323            @ThreadLocalCachable
324            public List<AssetCategory> getCategories(long classNameId, long classPK) {
325                    AssetEntry entry = assetEntryPersistence.fetchByC_C(
326                            classNameId, classPK);
327    
328                    if (entry == null) {
329                            return Collections.emptyList();
330                    }
331    
332                    return assetEntryPersistence.getAssetCategories(entry.getEntryId());
333            }
334    
335            @Override
336            public List<AssetCategory> getCategories(String className, long classPK) {
337                    long classNameId = classNameLocalService.getClassNameId(className);
338    
339                    return getCategories(classNameId, classPK);
340            }
341    
342            @Override
343            public AssetCategory getCategory(long categoryId) throws PortalException {
344                    return assetCategoryPersistence.findByPrimaryKey(categoryId);
345            }
346    
347            @Override
348            public AssetCategory getCategory(String uuid, long groupId)
349                    throws PortalException {
350    
351                    return assetCategoryPersistence.findByUUID_G(uuid, groupId);
352            }
353    
354            @Override
355            public long[] getCategoryIds(String className, long classPK) {
356                    return getCategoryIds(getCategories(className, classPK));
357            }
358    
359            @Override
360            public String[] getCategoryNames() {
361                    return getCategoryNames(getCategories());
362            }
363    
364            @Override
365            public String[] getCategoryNames(long classNameId, long classPK) {
366                    return getCategoryNames(getCategories(classNameId, classPK));
367            }
368    
369            @Override
370            public String[] getCategoryNames(String className, long classPK) {
371                    return getCategoryNames(getCategories(className, classPK));
372            }
373    
374            @Override
375            public List<AssetCategory> getChildCategories(long parentCategoryId) {
376                    return assetCategoryPersistence.findByParentCategoryId(
377                            parentCategoryId);
378            }
379    
380            @Override
381            public List<AssetCategory> getChildCategories(
382                    long parentCategoryId, int start, int end,
383                    OrderByComparator<AssetCategory> obc) {
384    
385                    return assetCategoryPersistence.findByParentCategoryId(
386                            parentCategoryId, start, end, obc);
387            }
388    
389            @Override
390            public int getChildCategoriesCount(long parentCategoryId) {
391                    return assetCategoryPersistence.countByParentCategoryId(
392                            parentCategoryId);
393            }
394    
395            @Override
396            public List<AssetCategory> getEntryCategories(long entryId) {
397                    return assetEntryPersistence.getAssetCategories(entryId);
398            }
399    
400            @Override
401            public List<Long> getSubcategoryIds(long parentCategoryId) {
402                    AssetCategory parentAssetCategory =
403                            assetCategoryPersistence.fetchByPrimaryKey(parentCategoryId);
404    
405                    if (parentAssetCategory == null) {
406                            return Collections.emptyList();
407                    }
408    
409                    return ListUtil.toList(
410                            assetCategoryPersistence.getDescendants(parentAssetCategory),
411                            AssetCategory.CATEGORY_ID_ACCESSOR);
412            }
413    
414            @Override
415            public List<AssetCategory> getVocabularyCategories(
416                    long vocabularyId, int start, int end,
417                    OrderByComparator<AssetCategory> obc) {
418    
419                    return assetCategoryPersistence.findByVocabularyId(
420                            vocabularyId, start, end, obc);
421            }
422    
423            @Override
424            public List<AssetCategory> getVocabularyCategories(
425                    long parentCategoryId, long vocabularyId, int start, int end,
426                    OrderByComparator<AssetCategory> obc) {
427    
428                    return assetCategoryPersistence.findByP_V(
429                            parentCategoryId, vocabularyId, start, end, obc);
430            }
431    
432            @Override
433            public int getVocabularyCategoriesCount(long vocabularyId) {
434                    return assetCategoryPersistence.countByVocabularyId(vocabularyId);
435            }
436    
437            @Override
438            public List<AssetCategory> getVocabularyRootCategories(
439                    long vocabularyId, int start, int end,
440                    OrderByComparator<AssetCategory> obc) {
441    
442                    return getVocabularyCategories(
443                            AssetCategoryConstants.DEFAULT_PARENT_CATEGORY_ID, vocabularyId,
444                            start, end, obc);
445            }
446    
447            @Override
448            public int getVocabularyRootCategoriesCount(long vocabularyId) {
449                    return assetCategoryPersistence.countByP_V(
450                            AssetCategoryConstants.DEFAULT_PARENT_CATEGORY_ID, vocabularyId);
451            }
452    
453            @Indexable(type = IndexableType.REINDEX)
454            @Override
455            public AssetCategory mergeCategories(long fromCategoryId, long toCategoryId)
456                    throws PortalException {
457    
458                    List<AssetEntry> entries = assetCategoryPersistence.getAssetEntries(
459                            fromCategoryId);
460    
461                    assetCategoryPersistence.addAssetEntries(toCategoryId, entries);
462    
463                    List<AssetCategoryProperty> categoryProperties =
464                            assetCategoryPropertyPersistence.findByCategoryId(fromCategoryId);
465    
466                    for (AssetCategoryProperty fromCategoryProperty : categoryProperties) {
467                            AssetCategoryProperty toCategoryProperty =
468                                    assetCategoryPropertyPersistence.fetchByCA_K(
469                                            toCategoryId, fromCategoryProperty.getKey());
470    
471                            if (toCategoryProperty == null) {
472                                    fromCategoryProperty.setCategoryId(toCategoryId);
473    
474                                    assetCategoryPropertyPersistence.update(fromCategoryProperty);
475                            }
476                    }
477    
478                    assetCategoryLocalService.deleteCategory(fromCategoryId);
479    
480                    return getCategory(toCategoryId);
481            }
482    
483            @Indexable(type = IndexableType.REINDEX)
484            @Override
485            public AssetCategory moveCategory(
486                            long categoryId, long parentCategoryId, long vocabularyId,
487                            ServiceContext serviceContext)
488                    throws PortalException {
489    
490                    AssetCategory category = assetCategoryPersistence.findByPrimaryKey(
491                            categoryId);
492    
493                    validate(
494                            categoryId, parentCategoryId, category.getName(), vocabularyId);
495    
496                    if (parentCategoryId > 0) {
497                            assetCategoryPersistence.findByPrimaryKey(parentCategoryId);
498                    }
499    
500                    if (vocabularyId != category.getVocabularyId()) {
501                            assetVocabularyPersistence.findByPrimaryKey(vocabularyId);
502    
503                            category.setVocabularyId(vocabularyId);
504    
505                            updateChildrenVocabularyId(category, vocabularyId);
506                    }
507    
508                    category.setModifiedDate(new Date());
509                    category.setParentCategoryId(parentCategoryId);
510    
511                    assetCategoryPersistence.update(category);
512    
513                    return category;
514            }
515    
516            @Override
517            public void rebuildTree(long groupId, boolean force) {
518                    assetCategoryPersistence.rebuildTree(groupId, force);
519            }
520    
521            @Override
522            public List<AssetCategory> search(
523                    long groupId, String name, String[] categoryProperties, int start,
524                    int end) {
525    
526                    return assetCategoryFinder.findByG_N_P(
527                            groupId, name, categoryProperties, start, end);
528            }
529    
530            @Override
531            public BaseModelSearchResult<AssetCategory> searchCategories(
532                            long companyId, long groupIds, String title, long vocabularyId,
533                            int start, int end)
534                    throws PortalException {
535    
536                    return searchCategories(
537                            companyId, new long[] {groupIds}, title, new long[] {vocabularyId},
538                            start, end);
539            }
540    
541            @Override
542            public BaseModelSearchResult<AssetCategory> searchCategories(
543                            long companyId, long[] groupIds, String title, long[] vocabularyIds,
544                            int start, int end)
545                    throws PortalException {
546    
547                    SearchContext searchContext = buildSearchContext(
548                            companyId, groupIds, title, new long[0], vocabularyIds, start, end);
549    
550                    return searchCategories(searchContext);
551            }
552    
553            @Override
554            public BaseModelSearchResult<AssetCategory> searchCategories(
555                            long companyId, long[] groupIds, String title,
556                            long[] parentCategoryIds, long[] vocabularyIds, int start, int end)
557                    throws PortalException {
558    
559                    SearchContext searchContext = buildSearchContext(
560                            companyId, groupIds, title, parentCategoryIds, vocabularyIds, start,
561                            end);
562    
563                    return searchCategories(searchContext);
564            }
565    
566            @Indexable(type = IndexableType.REINDEX)
567            @Override
568            public AssetCategory updateCategory(
569                            long userId, long categoryId, long parentCategoryId,
570                            Map<Locale, String> titleMap, Map<Locale, String> descriptionMap,
571                            long vocabularyId, String[] categoryProperties,
572                            ServiceContext serviceContext)
573                    throws PortalException {
574    
575                    // Category
576    
577                    String name = titleMap.get(LocaleUtil.getSiteDefault());
578    
579                    name = ModelHintsUtil.trimString(
580                            AssetCategory.class.getName(), "name", name);
581    
582                    if (categoryProperties == null) {
583                            categoryProperties = new String[0];
584                    }
585    
586                    validate(categoryId, parentCategoryId, name, vocabularyId);
587    
588                    if (parentCategoryId > 0) {
589                            assetCategoryPersistence.findByPrimaryKey(parentCategoryId);
590                    }
591    
592                    AssetCategory category = assetCategoryPersistence.findByPrimaryKey(
593                            categoryId);
594    
595                    String oldName = category.getName();
596    
597                    if (vocabularyId != category.getVocabularyId()) {
598                            assetVocabularyPersistence.findByPrimaryKey(vocabularyId);
599    
600                            parentCategoryId =
601                                    AssetCategoryConstants.DEFAULT_PARENT_CATEGORY_ID;
602    
603                            category.setVocabularyId(vocabularyId);
604    
605                            updateChildrenVocabularyId(category, vocabularyId);
606                    }
607    
608                    category.setModifiedDate(new Date());
609                    category.setParentCategoryId(parentCategoryId);
610                    category.setName(name);
611                    category.setTitleMap(titleMap);
612                    category.setDescriptionMap(descriptionMap);
613    
614                    assetCategoryPersistence.update(category);
615    
616                    // Properties
617    
618                    List<AssetCategoryProperty> oldCategoryProperties =
619                            assetCategoryPropertyPersistence.findByCategoryId(categoryId);
620    
621                    oldCategoryProperties = ListUtil.copy(oldCategoryProperties);
622    
623                    for (int i = 0; i < categoryProperties.length; i++) {
624                            String[] categoryProperty = StringUtil.split(
625                                    categoryProperties[i],
626                                    AssetCategoryConstants.PROPERTY_KEY_VALUE_SEPARATOR);
627    
628                            if (categoryProperty.length <= 1) {
629                                    categoryProperty = StringUtil.split(
630                                            categoryProperties[i], CharPool.COLON);
631                            }
632    
633                            String key = StringPool.BLANK;
634    
635                            if (categoryProperty.length > 0) {
636                                    key = GetterUtil.getString(categoryProperty[0]);
637                            }
638    
639                            String value = StringPool.BLANK;
640    
641                            if (categoryProperty.length > 1) {
642                                    value = GetterUtil.getString(categoryProperty[1]);
643                            }
644    
645                            if (Validator.isNotNull(key)) {
646                                    boolean addCategoryProperty = true;
647    
648                                    AssetCategoryProperty oldCategoryProperty = null;
649    
650                                    Iterator<AssetCategoryProperty> iterator =
651                                            oldCategoryProperties.iterator();
652    
653                                    while (iterator.hasNext()) {
654                                            oldCategoryProperty = iterator.next();
655    
656                                            if ((categoryId == oldCategoryProperty.getCategoryId()) &&
657                                                    key.equals(oldCategoryProperty.getKey())) {
658    
659                                                    addCategoryProperty = false;
660    
661                                                    if (!value.equals(oldCategoryProperty.getValue())) {
662                                                            assetCategoryPropertyLocalService.
663                                                                    updateCategoryProperty(
664                                                                            userId,
665                                                                            oldCategoryProperty.getCategoryPropertyId(),
666                                                                            key, value);
667                                                    }
668    
669                                                    iterator.remove();
670    
671                                                    break;
672                                            }
673                                    }
674    
675                                    if (addCategoryProperty) {
676                                            assetCategoryPropertyLocalService.addCategoryProperty(
677                                                    userId, categoryId, key, value);
678                                    }
679                            }
680                    }
681    
682                    for (AssetCategoryProperty categoryProperty : oldCategoryProperties) {
683                            assetCategoryPropertyLocalService.deleteAssetCategoryProperty(
684                                    categoryProperty);
685                    }
686    
687                    // Indexer
688    
689                    if (!oldName.equals(name)) {
690                            List<AssetEntry> entries = assetCategoryPersistence.getAssetEntries(
691                                    category.getCategoryId());
692    
693                            assetEntryLocalService.reindex(entries);
694                    }
695    
696                    return category;
697            }
698    
699            protected SearchContext buildSearchContext(
700                    long companyId, long[] groupIds, String title, long[] parentCategoryIds,
701                    long[] vocabularyIds, int start, int end) {
702    
703                    SearchContext searchContext = new SearchContext();
704    
705                    Map<String, Serializable> attributes =
706                            new HashMap<String, Serializable>();
707    
708                    attributes.put(Field.ASSET_PARENT_CATEGORY_IDS, parentCategoryIds);
709                    attributes.put(Field.ASSET_VOCABULARY_IDS, vocabularyIds);
710                    attributes.put(Field.TITLE, title);
711    
712                    searchContext.setAttributes(attributes);
713    
714                    searchContext.setCompanyId(companyId);
715                    searchContext.setEnd(end);
716                    searchContext.setGroupIds(groupIds);
717                    searchContext.setKeywords(title);
718                    searchContext.setStart(start);
719    
720                    QueryConfig queryConfig = searchContext.getQueryConfig();
721    
722                    queryConfig.setHighlightEnabled(false);
723                    queryConfig.setScoreEnabled(false);
724    
725                    return searchContext;
726            }
727    
728            protected long[] getCategoryIds(List<AssetCategory> categories) {
729                    return ListUtil.toLongArray(
730                            categories, AssetCategory.CATEGORY_ID_ACCESSOR);
731            }
732    
733            protected String[] getCategoryNames(List<AssetCategory> categories) {
734                    return ListUtil.toArray(categories, AssetCategory.NAME_ACCESSOR);
735            }
736    
737            protected BaseModelSearchResult<AssetCategory> searchCategories(
738                            SearchContext searchContext)
739                    throws PortalException {
740    
741                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
742                            AssetCategory.class);
743    
744                    for (int i = 0; i < 10; i++) {
745                            Hits hits = indexer.search(searchContext);
746    
747                            List<AssetCategory> categories = AssetCategoryUtil.getCategories(
748                                    hits);
749    
750                            if (categories != null) {
751                                    return new BaseModelSearchResult<AssetCategory>(
752                                            categories, hits.getLength());
753                            }
754                    }
755    
756                    throw new SearchException(
757                            "Unable to fix the search index after 10 attempts");
758            }
759    
760            protected void updateChildrenVocabularyId(
761                    AssetCategory category, long vocabularyId) {
762    
763                    List<AssetCategory> childrenCategories =
764                            assetCategoryPersistence.findByParentCategoryId(
765                                    category.getCategoryId());
766    
767                    if (!childrenCategories.isEmpty()) {
768                            for (AssetCategory childCategory : childrenCategories) {
769                                    childCategory.setVocabularyId(vocabularyId);
770                                    childCategory.setModifiedDate(new Date());
771    
772                                    assetCategoryPersistence.update(childCategory);
773    
774                                    updateChildrenVocabularyId (childCategory, vocabularyId);
775                            }
776                    }
777            }
778    
779            protected void validate(
780                            long categoryId, long parentCategoryId, String name,
781                            long vocabularyId)
782                    throws PortalException {
783    
784                    if (Validator.isNull(name)) {
785                            throw new AssetCategoryNameException();
786                    }
787    
788                    AssetCategory category = assetCategoryPersistence.fetchByP_N_V(
789                            parentCategoryId, name, vocabularyId);
790    
791                    if ((category != null) && (category.getCategoryId() != categoryId)) {
792                            StringBundler sb = new StringBundler(4);
793    
794                            sb.append("There is another category named ");
795                            sb.append(name);
796                            sb.append(" as a child of category ");
797                            sb.append(parentCategoryId);
798    
799                            throw new DuplicateCategoryException(sb.toString());
800                    }
801            }
802    
803    }