001/*
002 *  Copyright 2020 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.plugins.workspaces.categories;
017
018import java.util.ArrayList;
019import java.util.Collection;
020import java.util.Collections;
021import java.util.List;
022import java.util.Map;
023
024import org.apache.avalon.framework.component.Component;
025import org.apache.avalon.framework.service.ServiceException;
026import org.apache.avalon.framework.service.ServiceManager;
027import org.apache.avalon.framework.service.Serviceable;
028import org.apache.commons.lang3.StringUtils;
029
030/**
031 * Helper for project's categories
032 *
033 */
034public class CategoryHelper implements Serviceable, Component
035{
036    /** The avalon role */
037    public static final String ROLE = CategoryHelper.class.getName();
038    
039    private CategoryProviderExtensionPoint _categoryProviderEP;
040
041    private CategoryJCRProvider _jcrCategoryProvider;
042
043    private CategoryColorsComponent _categoryColorsComponent;
044    
045    public void service(ServiceManager smanager) throws ServiceException
046    {
047        _categoryProviderEP = (CategoryProviderExtensionPoint) smanager.lookup(CategoryProviderExtensionPoint.ROLE);
048        _jcrCategoryProvider = (CategoryJCRProvider) _categoryProviderEP.getExtension(CategoryJCRProvider.class.getName());
049        _categoryColorsComponent = (CategoryColorsComponent) smanager.lookup(CategoryColorsComponent.ROLE);
050    }
051    
052    /**
053     * Get the root categories
054     * @return the root categories
055     */
056    public Collection<Category> getRootCategories()
057    {
058        return _jcrCategoryProvider.getTags(Collections.EMPTY_MAP).values();
059    }
060    
061    /**
062     * Get the leaf categories
063     * @return the leaf categories
064     */
065    public Collection<Category> getLeafCategories()
066    {
067        Collection<Category> rootCategories = getRootCategories();
068        
069        List<Category> leafCategories = new ArrayList<>();
070        for (Category category : rootCategories)
071        {
072            leafCategories.addAll(getLeafCategories(category));
073        }
074        
075        return leafCategories;
076    }
077    
078    /**
079     * Get the leaf categories of a given category
080     * @param category the category
081     * @return the leaf categories or the category it self if it has no child
082     */
083    public Collection<Category> getLeafCategories(Category category)
084    {
085        Map<String, Category> childTags = category.getTags();
086        if (childTags.isEmpty())
087        {
088            return Collections.singletonList(category);
089        }
090        else
091        {
092            List<Category> leafCategories = new ArrayList<>();
093            for (Category childCategory : childTags.values())
094            {
095                leafCategories.addAll(getLeafCategories(childCategory));
096            }
097            return leafCategories;
098        }
099    }
100    
101    /**
102     * Get the (flattened) child categories recursively
103     * @param category the category
104     * @return the child categories
105     */
106    public Collection<Category> getChildCategories(Category category)
107    {
108        List<Category> childCategories = new ArrayList<>();
109        
110        for (Category childCategory : category.getTags().values())
111        {
112            childCategories.add(childCategory);
113            childCategories.addAll(getChildCategories(childCategory));
114        }
115        
116        return childCategories;
117    }
118    
119    /**
120     * Get the colors of a category.
121     * @param category the category. Can be null to get default color.
122     * @return the colors associated to this category or the default color if there is no category or if the category has no color
123     */
124    public Map<String, String> getCategoryColor(Category category)
125    {
126        Category categoryForColor = category;
127        while (categoryForColor != null && categoryForColor.getColor(false) == null)
128        {
129            // if category has no color, try to get color from its closest parent category
130            categoryForColor = categoryForColor.getParent();
131        }
132        
133        String colorIndex = StringUtils.defaultIfBlank(categoryForColor != null ? categoryForColor.getColor(false) : "", _categoryColorsComponent.getDefaultKey());
134        Map<String, String> color =  _categoryColorsComponent.getColors().get(colorIndex);
135        if (color == null)
136        {
137            color = _categoryColorsComponent.getColors().get(_categoryColorsComponent.getDefaultKey());
138        }
139        return color;
140    }
141}