001/*
002 *  Copyright 2016 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.tasks;
017
018import java.util.ArrayList;
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022import java.util.Set;
023
024import org.apache.cocoon.components.ContextHelper;
025import org.apache.cocoon.environment.Request;
026import org.apache.commons.lang.IllegalClassException;
027
028import org.ametys.cms.transformation.xslt.ResolveURIComponent;
029import org.ametys.core.right.RightManager.RightResult;
030import org.ametys.core.ui.Callable;
031import org.ametys.core.user.UserIdentity;
032import org.ametys.plugins.explorer.ExplorerNode;
033import org.ametys.plugins.explorer.resources.ModifiableResourceCollection;
034import org.ametys.plugins.explorer.resources.jcr.JCRResourcesCollectionFactory;
035import org.ametys.plugins.explorer.tasks.jcr.JCRTasksDAO;
036import org.ametys.plugins.explorer.tasks.jcr.JCRTasksListFactory;
037import org.ametys.plugins.repository.AmetysObjectIterable;
038import org.ametys.plugins.repository.AmetysRepositoryException;
039import org.ametys.plugins.repository.data.holder.ModifiableModelAwareDataHolder;
040import org.ametys.plugins.repository.jcr.DefaultTraversableAmetysObject;
041import org.ametys.plugins.workspaces.AbstractWorkspaceModule;
042import org.ametys.plugins.workspaces.project.objects.Project;
043import org.ametys.runtime.i18n.I18nizableText;
044import org.ametys.web.repository.page.ModifiablePage;
045import org.ametys.web.repository.page.ModifiableZone;
046import org.ametys.web.repository.page.ModifiableZoneItem;
047import org.ametys.web.repository.page.Page;
048import org.ametys.web.repository.page.ZoneItem.ZoneType;
049
050import com.google.common.collect.ImmutableSet;
051
052/**
053 * Tasks manager for workspaces
054 */
055public class TasksWorkspaceModule extends AbstractWorkspaceModule
056{
057    /** The id of task module */
058    public static final String TASK_MODULE_ID = TasksWorkspaceModule.class.getName();
059    
060    /** Tag on the main page holding the task module */
061    public static final String TASK_MODULE_TAG = "WORKSPACES_MODULE_TASK";
062    
063    /** Workspaces tasks list node name */
064    private static final String __WORKSPACES_TASKS_NODE_NAME = "tasks";
065    
066    /** Workspaces default tasks list node name */
067    private static final String __WORKSPACES_TASKS_DEFAULT_NODE_NAME = "default";
068
069    /** Module i18n title key */
070    private static final String __MODULE_TITLE_KEY = "PLUGINS_WORKSPACES_PROJECT_SERVICE_MODULE_TASK_LABEL";
071    
072    @Override
073    public String getId()
074    {
075        return TASK_MODULE_ID;
076    }
077    
078    @Override
079    public String getModuleName()
080    {
081        return __WORKSPACES_TASKS_NODE_NAME;
082    }
083    
084    @Override
085    protected String getModulePageName()
086    {
087        return "tasks";
088    }
089    
090    @Override
091    public I18nizableText getModuleTitle()
092    {
093        return new I18nizableText("plugin.workspaces", __MODULE_TITLE_KEY);
094    }
095    
096    @Override
097    protected I18nizableText getModulePageTitle()
098    {
099        return new I18nizableText("plugin." + _pluginName, "PLUGINS_WORKSPACES_PROJECT_WORKSPACE_PAGE_TASKS_TITLE");
100    }
101    
102    @Override
103    protected String getModuleTagName()
104    {
105        return TASK_MODULE_TAG;
106    }
107    @Override
108    protected void initializeModulePage(ModifiablePage taskPage)
109    {
110        ModifiableZone defaultZone = taskPage.createZone("default");
111        
112        String serviceId = "org.ametys.plugins.workspaces.module.Tasks";
113        ModifiableZoneItem defaultZoneItem = defaultZone.addZoneItem();
114        defaultZoneItem.setType(ZoneType.SERVICE);
115        defaultZoneItem.setServiceId(serviceId);
116        
117        ModifiableModelAwareDataHolder serviceDataHolder = defaultZoneItem.getServiceParameters();
118        serviceDataHolder.setValue("xslt", _getDefaultXslt(serviceId));
119    }
120
121    /**
122     * Retrieves the rights for the current user in the project
123     * @return The project
124     */
125    @Callable
126    public Map<String, Object> getTasksModuleRights()
127    {
128        Map<String, Object> rights = new HashMap<>();
129        
130        Request request = ContextHelper.getRequest(_context);
131        String projectName = (String) request.getAttribute("projectName");
132        Project project = _projectManager.getProject(projectName);
133        ModifiableResourceCollection tasksRoot = getModuleRoot(project, false);
134        
135        UserIdentity currentUser = _currentUserProvider.getUser();
136        rights.put("view", tasksRoot != null && _rightManager.hasRight(currentUser, JCRTasksDAO.RIGHTS_VIEW_TASKS, tasksRoot) == RightResult.RIGHT_ALLOW);
137        rights.put("add", tasksRoot != null && _rightManager.hasRight(currentUser, JCRTasksDAO.RIGHTS_ADD_TASK, tasksRoot) == RightResult.RIGHT_ALLOW);
138        
139        return rights;
140    }
141    
142    /**
143     * Retrieves the rights for the current user in the projects list
144     * @param projectNames The name of projects to checks rights from
145     * @return The rights data
146     */
147    @Callable
148    public Map<String, Object> getTasksServiceRights(List<String> projectNames)
149    {
150        Map<String, Object> rights = new HashMap<>();
151        
152        List<String> rightAdd = new ArrayList<>();
153        
154        UserIdentity currentUser = _currentUserProvider.getUser();
155        for (String projectName : projectNames)
156        {
157            Project project = _projectManager.getProject(projectName);
158            ModifiableResourceCollection tasksRoot = getModuleRoot(project, false);
159            
160            if (tasksRoot != null && _rightManager.hasRight(currentUser, JCRTasksDAO.RIGHTS_ADD_TASK, tasksRoot) == RightResult.RIGHT_ALLOW)
161            {
162                rightAdd.add(projectName);
163            }
164        }
165        
166        rights.put("add", rightAdd);
167        
168        return rights;
169    }
170    
171    /**
172     * Get the URI of a task in project'site
173     * @param project The project
174     * @param taskId The id of the task
175     * @param language The sitemap language
176     * @return The thread uri
177     */
178    public String getTaskUri(Project project, String taskId, String language)
179    {
180        AmetysObjectIterable<Page> pages = getModulePages(project, language);
181        
182        if (pages.getSize() > 0)
183        {
184            Page page = pages.iterator().next();
185            
186            StringBuilder sb = new StringBuilder();
187            sb.append(ResolveURIComponent.resolve("page", page.getId()));
188            sb.append("#").append(taskId);
189            
190            return sb.toString();
191        }
192        
193        return null;
194    }
195    
196    @Override
197    public ModifiableResourceCollection getModuleRoot(Project project, boolean create)
198    {
199        try
200        {
201            ExplorerNode projectRootNode = project.getExplorerRootNode();
202            
203            if (projectRootNode instanceof ModifiableResourceCollection)
204            {
205                ModifiableResourceCollection projectRootNodeRc = (ModifiableResourceCollection) projectRootNode;
206                return _getAmetysObject(projectRootNodeRc, __WORKSPACES_TASKS_NODE_NAME, JCRResourcesCollectionFactory.RESOURCESCOLLECTION_NODETYPE, create);
207            }
208            else
209            {
210                throw new IllegalClassException(ModifiableResourceCollection.class, projectRootNode.getClass());
211            }
212        }
213        catch (AmetysRepositoryException e)
214        {
215            throw new AmetysRepositoryException("Error getting the documents root node.", e);
216        }
217    }
218    
219    /**
220     * Get the root for tasks
221     * @param project The project
222     * @param create true to create root if not exists
223     * @return The root for tasks
224     */
225    public DefaultTraversableAmetysObject getTasksRoot(Project project, boolean create)
226    {
227        ModifiableResourceCollection moduleRoot = getModuleRoot(project, create);
228        return _getAmetysObject(moduleRoot, __WORKSPACES_TASKS_DEFAULT_NODE_NAME, JCRTasksListFactory.TASKS_LIST_NODETYPE, create);
229    }
230
231    @Override
232    public Set<String> getAllowedEventTypes()
233    {
234        return ImmutableSet.of("task.created", "task.assigned", "task.status.changed");
235    }
236}