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.report;
017
018import java.util.Collection;
019import java.util.Comparator;
020import java.util.List;
021import java.util.Objects;
022import java.util.Set;
023import java.util.function.Function;
024import java.util.stream.Collectors;
025
026import org.apache.avalon.framework.component.Component;
027import org.apache.avalon.framework.service.ServiceException;
028import org.apache.avalon.framework.service.ServiceManager;
029import org.apache.avalon.framework.service.Serviceable;
030import org.apache.commons.lang.ArrayUtils;
031import org.apache.commons.lang3.StringUtils;
032
033import org.ametys.core.right.RightManager;
034import org.ametys.core.right.RightManager.RightResult;
035import org.ametys.core.user.CurrentUserProvider;
036import org.ametys.core.user.UserIdentity;
037import org.ametys.plugins.workspaces.categories.Category;
038import org.ametys.plugins.workspaces.categories.CategoryProviderExtensionPoint;
039import org.ametys.plugins.workspaces.project.ProjectManager;
040import org.ametys.plugins.workspaces.project.objects.Project;
041
042/**
043 * Component for reporting projects
044 */
045public class ReportHelper implements Serviceable, Component
046{
047    /** Avalon Role */
048    public static final String ROLE = ReportHelper.class.getName();
049    
050    /** The right id to report all project */
051    public static final String REPORT_ALL_RIGHT_ID = "Workspaces_Reports_Right_Report_All";
052    
053    /** The id of reports service */
054    public static final String REPORT_SERVICE_ID = "org.ametys.plugins.workspacesReports.service.Report";
055    
056    /** The current user provider */
057    protected CurrentUserProvider _currentUserProvider;
058    
059    /** The project manager */
060    protected ProjectManager _projectManager;
061    
062    /** The right manager */
063    protected RightManager _rightManager;
064
065    /** The catgeory provider */
066    protected CategoryProviderExtensionPoint _categoryProviderEP;
067    
068    public void service(ServiceManager manager) throws ServiceException
069    {
070        _currentUserProvider = (CurrentUserProvider) manager.lookup(CurrentUserProvider.ROLE);
071        _projectManager = (ProjectManager) manager.lookup(ProjectManager.ROLE);
072        _rightManager = (RightManager) manager.lookup(RightManager.ROLE);
073        _categoryProviderEP = (CategoryProviderExtensionPoint) manager.lookup(CategoryProviderExtensionPoint.ROLE);
074    }
075    
076    /**
077     * Get the available projects (the manager's project)
078     * @return the available projects for reports
079     */
080    public List<Project> getAvailableProjects()
081    {
082        UserIdentity user = _currentUserProvider.getUser();
083        boolean hasSuperRight = hasSuperRight();
084
085        Function<Project, String> getProjectTitle = Project::getTitle;
086        Comparator<Project> projectTitleComparator = Comparator.comparing(getProjectTitle.andThen(StringUtils::stripAccents), String.CASE_INSENSITIVE_ORDER);
087        
088        return _projectManager.getProjects()
089            .stream()
090            .filter(p -> hasSuperRight || ArrayUtils.contains(p.getManagers(), user))
091            .sorted(projectTitleComparator)
092            .collect(Collectors.toList());
093    }
094    
095    /**
096     * Determines if the current user has right to access to all project's reports
097     * @return if the current user has right to access to all project's reports
098     */
099    public boolean hasSuperRight()
100    {
101        return _rightManager.hasRight(_currentUserProvider.getUser(), REPORT_ALL_RIGHT_ID, "/cms") == RightResult.RIGHT_ALLOW;
102    }
103    
104    /**
105     * Get the available projects (the manager's project)
106     * @param filteredProjects the filtered projects
107     * @param filteredCategories the filtered categories
108     * @return the available projects for reports
109     */
110    public List<Project> getAvailableProjects(List<String> filteredProjects, List<String> filteredCategories)
111    {
112        return getAvailableProjects()
113            .stream()
114            .filter(p -> filteredProjects == null || filteredProjects.isEmpty() || filteredProjects.contains(p.getId()))
115            .filter(p -> _matchCategories(p, filteredCategories))
116            .collect(Collectors.toList());
117    }
118    
119    private boolean _matchCategories(Project project, List<String> filteredCategories)
120    {
121        if (filteredCategories == null || filteredCategories.isEmpty())
122        {
123            return true;
124        }
125        
126        for (String projectCategory : project.getCategories())
127        {
128            Category category = _categoryProviderEP.getTag(projectCategory, null);
129            if (category != null)
130            {
131                Category rootCategory = _getRootCategory(category);
132                if (filteredCategories.contains(rootCategory.getName()))
133                {
134                    return true;
135                }
136            }
137        }
138        
139        return false;
140    }
141    
142    /**
143     * Get the available root categories
144     * @param projects the projects
145     * @return the available categories from the given projects
146     */
147    public Set<Category> getAvailableCategories(List<Project> projects)
148    {
149        return projects.stream()
150            .map(Project::getCategories)
151            .flatMap(Collection::stream)
152            .map(id -> _categoryProviderEP.getTag(id, null))
153            .filter(Objects::nonNull)
154            .map(c -> _getRootCategory(c))
155            .collect(Collectors.toSet());
156    }
157    
158    private Category _getRootCategory(Category category)
159    {
160        Category parent = category;
161        while (parent.getParent() != null)
162        {
163            parent = parent.getParent();
164        }
165        return parent;
166    }
167}