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