001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.asset.service.impl;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.json.JSONArray;
020    import com.liferay.portal.kernel.json.JSONFactoryUtil;
021    import com.liferay.portal.kernel.json.JSONObject;
022    import com.liferay.portal.kernel.search.Document;
023    import com.liferay.portal.kernel.search.Field;
024    import com.liferay.portal.kernel.search.Hits;
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.util.GetterUtil;
031    import com.liferay.portal.kernel.util.ListUtil;
032    import com.liferay.portal.kernel.util.OrderByComparator;
033    import com.liferay.portal.kernel.util.StringBundler;
034    import com.liferay.portal.kernel.util.StringPool;
035    import com.liferay.portal.kernel.util.Validator;
036    import com.liferay.portal.model.User;
037    import com.liferay.portal.security.permission.ActionKeys;
038    import com.liferay.portal.security.permission.PermissionChecker;
039    import com.liferay.portal.service.ServiceContext;
040    import com.liferay.portlet.asset.model.AssetCategory;
041    import com.liferay.portlet.asset.model.AssetCategoryConstants;
042    import com.liferay.portlet.asset.model.AssetCategoryDisplay;
043    import com.liferay.portlet.asset.model.AssetVocabulary;
044    import com.liferay.portlet.asset.service.AssetCategoryLocalServiceUtil;
045    import com.liferay.portlet.asset.service.base.AssetCategoryServiceBaseImpl;
046    import com.liferay.portlet.asset.service.permission.AssetCategoryPermission;
047    import com.liferay.util.Autocomplete;
048    import com.liferay.util.dao.orm.CustomSQLUtil;
049    
050    import java.io.Serializable;
051    
052    import java.util.ArrayList;
053    import java.util.Collections;
054    import java.util.HashMap;
055    import java.util.Iterator;
056    import java.util.List;
057    import java.util.Locale;
058    import java.util.Map;
059    
060    /**
061     * Provides the remote service for accessing, adding, deleting, moving, and
062     * updating asset categories. Its methods include permission checks.
063     *
064     * @author Brian Wing Shun Chan
065     * @author Jorge Ferrer
066     * @author Alvaro del Castillo
067     * @author Eduardo Lundgren
068     * @author Bruno Farache
069     */
070    public class AssetCategoryServiceImpl extends AssetCategoryServiceBaseImpl {
071    
072            @Override
073            public AssetCategory addCategory(
074                            long parentCategoryId, Map<Locale, String> titleMap,
075                            Map<Locale, String> descriptionMap, long vocabularyId,
076                            String[] categoryProperties, ServiceContext serviceContext)
077                    throws PortalException, SystemException {
078    
079                    AssetCategoryPermission.check(
080                            getPermissionChecker(), serviceContext.getScopeGroupId(),
081                            parentCategoryId, ActionKeys.ADD_CATEGORY);
082    
083                    return assetCategoryLocalService.addCategory(
084                            getUserId(), parentCategoryId, titleMap, descriptionMap,
085                            vocabularyId, categoryProperties, serviceContext);
086            }
087    
088            @Override
089            public AssetCategory addCategory(
090                            String title, long vocabularyId, ServiceContext serviceContext)
091                    throws PortalException, SystemException {
092    
093                    AssetCategoryPermission.check(
094                            getPermissionChecker(), serviceContext.getScopeGroupId(),
095                            AssetCategoryConstants.DEFAULT_PARENT_CATEGORY_ID,
096                            ActionKeys.ADD_CATEGORY);
097    
098                    return assetCategoryLocalService.addCategory(
099                            getUserId(), title, vocabularyId, serviceContext);
100            }
101    
102            /**
103             * @deprecated As of 6.2.0, Replaced by {@link #deleteCategories(long[],
104             *             ServiceContext)}
105             */
106            @Override
107            public void deleteCategories(long[] categoryIds)
108                    throws PortalException, SystemException {
109    
110                    deleteCategories(categoryIds, null);
111            }
112    
113            @Override
114            public List<AssetCategory> deleteCategories(
115                            long[] categoryIds, ServiceContext serviceContext)
116                    throws PortalException, SystemException {
117    
118                    List<AssetCategory> failedCategories = new ArrayList<AssetCategory>();
119    
120                    for (long categoryId : categoryIds) {
121                            try {
122                                    AssetCategoryPermission.check(
123                                            getPermissionChecker(), categoryId, ActionKeys.DELETE);
124    
125                                    assetCategoryLocalService.deleteCategory(categoryId);
126                            }
127                            catch (PortalException pe) {
128                                    if (serviceContext == null) {
129                                            return null;
130                                    }
131    
132                                    if (serviceContext.isFailOnPortalException()) {
133                                            throw pe;
134                                    }
135    
136                                    AssetCategory category =
137                                            assetCategoryPersistence.fetchByPrimaryKey(categoryId);
138    
139                                    if (category == null) {
140                                            category = assetCategoryPersistence.create(categoryId);
141                                    }
142    
143                                    failedCategories.add(category);
144                            }
145                    }
146    
147                    return failedCategories;
148            }
149    
150            @Override
151            public void deleteCategory(long categoryId)
152                    throws PortalException, SystemException {
153    
154                    AssetCategoryPermission.check(
155                            getPermissionChecker(), categoryId, ActionKeys.DELETE);
156    
157                    assetCategoryLocalService.deleteCategory(categoryId);
158            }
159    
160            @Override
161            public List<AssetCategory> getCategories(String className, long classPK)
162                    throws PortalException, SystemException {
163    
164                    return filterCategories(
165                            assetCategoryLocalService.getCategories(className, classPK));
166            }
167    
168            @Override
169            public AssetCategory getCategory(long categoryId)
170                    throws PortalException, SystemException {
171    
172                    AssetCategoryPermission.check(
173                            getPermissionChecker(), categoryId, ActionKeys.VIEW);
174    
175                    return assetCategoryLocalService.getCategory(categoryId);
176            }
177    
178            @Override
179            public List<AssetCategory> getChildCategories(long parentCategoryId)
180                    throws PortalException, SystemException {
181    
182                    return filterCategories(
183                            assetCategoryLocalService.getChildCategories(parentCategoryId));
184            }
185    
186            @Override
187            public List<AssetCategory> getChildCategories(
188                            long parentCategoryId, int start, int end, OrderByComparator obc)
189                    throws PortalException, SystemException {
190    
191                    return filterCategories(
192                            assetCategoryLocalService.getChildCategories(
193                                    parentCategoryId, start, end, obc));
194            }
195    
196            /**
197             * @deprecated As of 6.2.0, replaced by {@link #search(long[], String,
198             *             long[], int, int)}
199             */
200            @Override
201            public JSONArray getJSONSearch(
202                            long groupId, String name, long[] vocabularyIds, int start, int end)
203                    throws PortalException, SystemException {
204    
205                    return search(new long[] {groupId}, name, vocabularyIds, start, end);
206            }
207    
208            /**
209             * @deprecated As of 6.2.0, replaced by {@link
210             *             #getVocabularyCategoriesDisplay(long, int, int,
211             *             OrderByComparator)}
212             */
213            @Override
214            public JSONObject getJSONVocabularyCategories(
215                            long vocabularyId, int start, int end, OrderByComparator obc)
216                    throws PortalException, SystemException {
217    
218                    JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
219    
220                    List<AssetCategory> categories = filterCategories(
221                            assetCategoryLocalService.getVocabularyCategories(
222                                    vocabularyId, start, end, obc));
223    
224                    jsonObject.put("categories", toJSONArray(categories));
225                    jsonObject.put("total", categories.size());
226    
227                    return jsonObject;
228            }
229    
230            /**
231             * @deprecated As of 6.2.0, replaced by {@link
232             *             #getVocabularyCategoriesDisplay(long, String, long, int, int,
233             *             OrderByComparator)}
234             */
235            @Override
236            public JSONObject getJSONVocabularyCategories(
237                            long groupId, String title, long vocabularyId, int start, int end,
238                            OrderByComparator obc)
239                    throws PortalException, SystemException {
240    
241                    JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
242    
243                    int page = 0;
244    
245                    if ((end > 0) && (start > 0)) {
246                            page = end / (end - start);
247                    }
248    
249                    jsonObject.put("page", page);
250    
251                    List<AssetCategory> categories;
252                    int total = 0;
253    
254                    if (Validator.isNotNull(title)) {
255                            categories = searchCategories(
256                                    new long[] {groupId}, title, new long[] {vocabularyId}, start,
257                                    end);
258                            total = categories.size();
259                    }
260                    else {
261                            categories = getVocabularyCategories(vocabularyId, start, end, obc);
262                            total = getVocabularyCategoriesCount(groupId, vocabularyId);
263                    }
264    
265                    jsonObject.put("categories", toJSONArray(categories));
266                    jsonObject.put("total", total);
267    
268                    return jsonObject;
269            }
270    
271            @Override
272            public List<AssetCategory> getVocabularyCategories(
273                            long vocabularyId, int start, int end, OrderByComparator obc)
274                    throws PortalException, SystemException {
275    
276                    return filterCategories(
277                            assetCategoryLocalService.getVocabularyCategories(
278                                    vocabularyId, start, end, obc));
279            }
280    
281            @Override
282            public List<AssetCategory> getVocabularyCategories(
283                            long parentCategoryId, long vocabularyId, int start, int end,
284                            OrderByComparator obc)
285                    throws PortalException, SystemException {
286    
287                    return filterCategories(
288                            assetCategoryLocalService.getVocabularyCategories(
289                                    parentCategoryId, vocabularyId, start, end, obc));
290            }
291    
292            @Override
293            public List<AssetCategory> getVocabularyCategories(
294                            long groupId, String name, long vocabularyId, int start, int end,
295                            OrderByComparator obc)
296                    throws SystemException {
297    
298                    if (Validator.isNull(name)) {
299                            return assetCategoryPersistence.filterFindByG_V(
300                                    groupId, vocabularyId, start, end, obc);
301                    }
302                    else {
303                            return assetCategoryPersistence.filterFindByG_LikeN_V(
304                                    groupId, name, vocabularyId, start, end, obc);
305                    }
306            }
307    
308            @Override
309            public int getVocabularyCategoriesCount(long groupId, long vocabularyId)
310                    throws SystemException {
311    
312                    return assetCategoryPersistence.filterCountByG_V(groupId, vocabularyId);
313            }
314    
315            @Override
316            public int getVocabularyCategoriesCount(
317                            long groupId, String name, long vocabularyId)
318                    throws SystemException {
319    
320                    if (Validator.isNull(name)) {
321                            return assetCategoryPersistence.filterCountByG_V(
322                                    groupId, vocabularyId);
323                    }
324                    else {
325                            return assetCategoryPersistence.filterCountByG_LikeN_V(
326                                    groupId, name, vocabularyId);
327                    }
328            }
329    
330            @Override
331            public AssetCategoryDisplay getVocabularyCategoriesDisplay(
332                            long vocabularyId, int start, int end, OrderByComparator obc)
333                    throws PortalException, SystemException {
334    
335                    List<AssetCategory> categories = filterCategories(
336                            assetCategoryLocalService.getVocabularyCategories(
337                                    vocabularyId, start, end, obc));
338    
339                    return new AssetCategoryDisplay(
340                            categories, categories.size(), start, end);
341            }
342    
343            @Override
344            public AssetCategoryDisplay getVocabularyCategoriesDisplay(
345                            long groupId, String name, long vocabularyId, int start, int end,
346                            OrderByComparator obc)
347                    throws PortalException, SystemException {
348    
349                    List<AssetCategory> categories = null;
350                    int total = 0;
351    
352                    if (Validator.isNotNull(name)) {
353                            name = (CustomSQLUtil.keywords(name))[0];
354    
355                            categories = getVocabularyCategories(
356                                    groupId, name, vocabularyId, start, end, obc);
357                            total = getVocabularyCategoriesCount(groupId, name, vocabularyId);
358                    }
359                    else {
360                            categories = getVocabularyCategories(vocabularyId, start, end, obc);
361                            total = getVocabularyCategoriesCount(groupId, vocabularyId);
362                    }
363    
364                    return new AssetCategoryDisplay(categories, total, start, end);
365            }
366    
367            /**
368             * @deprecated As of 6.2.0, replaced by {@link
369             *             #getVocabularyRootCategories(long, long, int, int,
370             *             OrderByComparator)}
371             */
372            @Override
373            public List<AssetCategory> getVocabularyRootCategories(
374                            long vocabularyId, int start, int end, OrderByComparator obc)
375                    throws PortalException, SystemException {
376    
377                    AssetVocabulary vocabulary = assetVocabularyLocalService.getVocabulary(
378                            vocabularyId);
379    
380                    return getVocabularyRootCategories(
381                            vocabulary.getGroupId(), vocabularyId, start, end, obc);
382            }
383    
384            @Override
385            public List<AssetCategory> getVocabularyRootCategories(
386                            long groupId, long vocabularyId, int start, int end,
387                            OrderByComparator obc)
388                    throws SystemException {
389    
390                    return assetCategoryPersistence.filterFindByG_P_V(
391                            groupId, AssetCategoryConstants.DEFAULT_PARENT_CATEGORY_ID,
392                            vocabularyId, start, end, obc);
393            }
394    
395            @Override
396            public int getVocabularyRootCategoriesCount(long groupId, long vocabularyId)
397                    throws SystemException {
398    
399                    return assetCategoryPersistence.filterCountByG_P_V(
400                            groupId, AssetCategoryConstants.DEFAULT_PARENT_CATEGORY_ID,
401                            vocabularyId);
402            }
403    
404            @Override
405            public AssetCategory moveCategory(
406                            long categoryId, long parentCategoryId, long vocabularyId,
407                            ServiceContext serviceContext)
408                    throws PortalException, SystemException {
409    
410                    AssetCategoryPermission.check(
411                            getPermissionChecker(), categoryId, ActionKeys.UPDATE);
412    
413                    return assetCategoryLocalService.moveCategory(
414                            categoryId, parentCategoryId, vocabularyId, serviceContext);
415            }
416    
417            @Override
418            public List<AssetCategory> search(
419                            long groupId, String keywords, long vocabularyId, int start,
420                            int end, OrderByComparator obc)
421                    throws SystemException {
422    
423                    String name = CustomSQLUtil.keywords(keywords)[0];
424    
425                    if (Validator.isNull(name)) {
426                            return assetCategoryPersistence.filterFindByG_V(
427                                    groupId, vocabularyId, start, end, obc);
428                    }
429                    else {
430                            return assetCategoryPersistence.filterFindByG_LikeN_V(
431                                    groupId, name, vocabularyId, start, end, obc);
432                    }
433            }
434    
435            @Override
436            public JSONArray search(
437                            long groupId, String name, String[] categoryProperties, int start,
438                            int end)
439                    throws PortalException, SystemException {
440    
441                    List<AssetCategory> categories = assetCategoryLocalService.search(
442                            groupId, name, categoryProperties, start, end);
443    
444                    categories = filterCategories(categories);
445    
446                    return Autocomplete.listToJson(categories, "name", "name");
447            }
448    
449            @Override
450            public JSONArray search(
451                            long[] groupIds, String title, long[] vocabularyIds, int start,
452                            int end)
453                    throws PortalException, SystemException {
454    
455                    List<AssetCategory> categories = searchCategories(
456                            groupIds, title, vocabularyIds, start, end);
457    
458                    return toJSONArray(categories);
459            }
460    
461            @Override
462            public AssetCategory updateCategory(
463                            long categoryId, long parentCategoryId,
464                            Map<Locale, String> titleMap, Map<Locale, String> descriptionMap,
465                            long vocabularyId, String[] categoryProperties,
466                            ServiceContext serviceContext)
467                    throws PortalException, SystemException {
468    
469                    AssetCategoryPermission.check(
470                            getPermissionChecker(), categoryId, ActionKeys.UPDATE);
471    
472                    return assetCategoryLocalService.updateCategory(
473                            getUserId(), categoryId, parentCategoryId, titleMap, descriptionMap,
474                            vocabularyId, categoryProperties, serviceContext);
475            }
476    
477            protected SearchContext buildSearchContext(
478                    long companyId, long[] groupIds, String title, long[] vocabularyIds,
479                    int start, int end) {
480    
481                    SearchContext searchContext = new SearchContext();
482    
483                    Map<String, Serializable> attributes =
484                            new HashMap<String, Serializable>();
485    
486                    attributes.put(Field.ASSET_VOCABULARY_IDS, vocabularyIds);
487                    attributes.put(Field.TITLE, title);
488    
489                    searchContext.setAttributes(attributes);
490    
491                    searchContext.setCompanyId(companyId);
492                    searchContext.setEnd(end);
493                    searchContext.setGroupIds(groupIds);
494                    searchContext.setKeywords(title);
495    
496                    QueryConfig queryConfig = new QueryConfig();
497    
498                    queryConfig.setHighlightEnabled(false);
499                    queryConfig.setScoreEnabled(false);
500    
501                    searchContext.setQueryConfig(queryConfig);
502    
503                    searchContext.setStart(start);
504    
505                    return searchContext;
506            }
507    
508            protected List<AssetCategory> filterCategories(
509                            List<AssetCategory> categories)
510                    throws PortalException, SystemException {
511    
512                    PermissionChecker permissionChecker = getPermissionChecker();
513    
514                    categories = ListUtil.copy(categories);
515    
516                    Iterator<AssetCategory> itr = categories.iterator();
517    
518                    while (itr.hasNext()) {
519                            AssetCategory category = itr.next();
520    
521                            if (!AssetCategoryPermission.contains(
522                                            permissionChecker, category, ActionKeys.VIEW)) {
523    
524                                    itr.remove();
525                            }
526                    }
527    
528                    return categories;
529            }
530    
531            protected List<AssetCategory> searchCategories(
532                            long[] groupIds, String title, long[] vocabularyIds, int start,
533                            int end)
534                    throws PortalException, SystemException {
535    
536                    User user = getUser();
537    
538                    SearchContext searchContext = buildSearchContext(
539                            user.getCompanyId(), groupIds, title, vocabularyIds, start, end);
540    
541                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
542                            AssetCategory.class);
543    
544                    for (int i = 0; i < 10; i++) {
545                            Hits hits = indexer.search(searchContext);
546    
547                            List<Document> documents = hits.toList();
548    
549                            List<AssetCategory> categories = new ArrayList<AssetCategory>(
550                            documents.size());
551    
552                            for (Document document : documents) {
553                                    long categoryId = GetterUtil.getLong(
554                                            document.get(Field.ASSET_CATEGORY_ID));
555    
556                                    AssetCategory category =
557                                            AssetCategoryLocalServiceUtil.getCategory(categoryId);
558    
559                                    if (category == null) {
560                                            categories = null;
561    
562                                            long companyId = GetterUtil.getLong(
563                                                    document.get(Field.COMPANY_ID));
564    
565                                            indexer.delete(companyId, document.getUID());
566                                    }
567                                    else if (categories != null) {
568                                            categories.add(category);
569                                    }
570                            }
571    
572                            if (categories != null) {
573                                    return categories;
574                            }
575                    }
576    
577                    throw new SearchException(
578                            "Unable to fix the search index after 10 attempts");
579            }
580    
581            protected JSONArray toJSONArray(List<AssetCategory> categories)
582                    throws PortalException, SystemException {
583    
584                    JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
585    
586                    for (AssetCategory category : categories) {
587                            String categoryJSON = JSONFactoryUtil.looseSerialize(category);
588    
589                            JSONObject categoryJSONObject = JSONFactoryUtil.createJSONObject(
590                                    categoryJSON);
591    
592                            List<String> names = new ArrayList<String>();
593    
594                            AssetCategory curCategory = category;
595    
596                            while (curCategory.getParentCategoryId() > 0) {
597                                    AssetCategory parentCategory = getCategory(
598                                            curCategory.getParentCategoryId());
599    
600                                    names.add(parentCategory.getName());
601                                    names.add(
602                                            StringPool.SPACE + StringPool.GREATER_THAN +
603                                                    StringPool.SPACE);
604    
605                                    curCategory = parentCategory;
606                            }
607    
608                            Collections.reverse(names);
609    
610                            AssetVocabulary vocabulary = assetVocabularyService.getVocabulary(
611                                    category.getVocabularyId());
612    
613                            StringBundler sb = new StringBundler(1 + names.size());
614    
615                            sb.append(vocabulary.getTitleCurrentValue());
616                            sb.append(names.toArray(new String[names.size()]));
617    
618                            categoryJSONObject.put("path", sb.toString());
619    
620                            jsonArray.put(categoryJSONObject);
621                    }
622    
623                    return jsonArray;
624            }
625    
626    }