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