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.documents;
017
018import java.util.HashMap;
019import java.util.Map;
020import java.util.Set;
021
022import org.apache.avalon.framework.context.Context;
023import org.apache.avalon.framework.context.ContextException;
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.repository.AmetysObject;
036import org.ametys.plugins.repository.AmetysObjectIterable;
037import org.ametys.plugins.repository.AmetysRepositoryException;
038import org.ametys.plugins.repository.ModifiableTraversableAmetysObject;
039import org.ametys.plugins.repository.metadata.ModifiableCompositeMetadata;
040import org.ametys.plugins.workspaces.AbstractWorkspaceModule;
041import org.ametys.plugins.workspaces.project.objects.Project;
042import org.ametys.runtime.i18n.I18nizableText;
043import org.ametys.web.repository.page.ModifiablePage;
044import org.ametys.web.repository.page.ModifiableZone;
045import org.ametys.web.repository.page.ModifiableZoneItem;
046import org.ametys.web.repository.page.Page;
047import org.ametys.web.repository.page.ZoneItem.ZoneType;
048
049import com.google.common.collect.ImmutableSet;
050
051/**
052 * Helper component for managing documents
053 */
054public class DocumentWorkspaceModule extends AbstractWorkspaceModule
055{
056    /** The id of document module */
057    public static final String DODUMENT_MODULE_ID = DocumentWorkspaceModule.class.getName();
058    
059    /** Workspaces documents node name */
060    public static final String WORKSPACES_DOCUMENTS_NODE_NAME = "documents";
061    
062    /** Tag on the main page holding the document module */
063    private static final String __DOCUMENT_MODULE_TAG = "WORKSPACES_MODULE_DOCUMENT";
064    
065    /** Module i18n title key */
066    private static final String __MODULE_TITLE_KEY = "PLUGINS_WORKSPACES_PROJECT_SERVICE_MODULE_DOCUMENT_LABEL";
067    
068    @Override
069    public void contextualize(Context context) throws ContextException
070    {
071        _context = context;
072    }
073    
074    @Override
075    public String getId()
076    {
077        return DODUMENT_MODULE_ID;
078    }
079    
080    @Override
081    public I18nizableText getModuleTitle()
082    {
083        return new I18nizableText("plugin." + _pluginName, __MODULE_TITLE_KEY);
084    }
085    
086    @Override
087    protected String getModulePageName()
088    {
089        return "documents";
090    }
091    
092    @Override
093    protected I18nizableText getModulePageTitle()
094    {
095        return new I18nizableText("plugin." + _pluginName, "PLUGINS_WORKSPACES_PROJECT_WORKSPACE_PAGE_DOCUMENTS_TITLE");
096    }
097    
098    @Override
099    protected String getModuleTagName()
100    {
101        return __DOCUMENT_MODULE_TAG;
102    }
103    
104    @Override
105    protected void initializeModulePage(ModifiablePage documentPage)
106    {
107        ModifiableZone defaultZone = documentPage.createZone("default");
108        
109        String serviceId = "org.ametys.plugins.workspaces.module.Document";
110        ModifiableZoneItem defaultZoneItem = defaultZone.addZoneItem();
111        defaultZoneItem.setType(ZoneType.SERVICE);
112        defaultZoneItem.setServiceId(serviceId);
113        
114        ModifiableCompositeMetadata serviceMetadata = defaultZoneItem.getServiceParameters();
115        serviceMetadata.setMetadata("xslt", _getDefaultXslt(serviceId));
116    }
117
118    /**
119     * Get the URI of a folder in project'site
120     * @param project The project
121     * @param collectionId The id of collection
122     * @param language The sitemap language
123     * @return The thread uri
124     */
125    public String getFolderUri(Project project, String collectionId, String language)
126    {
127        AmetysObjectIterable<Page> pages = getModulePages(project, language);
128        
129        if (pages.getSize() > 0)
130        {
131            Page page = pages.iterator().next();
132            
133            StringBuilder sb = new StringBuilder();
134            sb.append(ResolveURIComponent.resolve("page", page.getId()));
135            sb.append("#").append(collectionId);
136            
137            return sb.toString();
138        }
139        
140        return null;
141    }
142    
143    /**
144     * Retrieves the set of general rights used in the document module for the current user
145     * @return The map of right data. Keys are the rights id, and values indicates whether the current user has the right or not.
146     */
147    @Callable
148    public Map<String, Object> getModuleBaseRights()
149    {
150        Request request = ContextHelper.getRequest(_context);
151        
152        String projectName = (String) request.getAttribute("projectName");
153        Project project = _projectManager.getProject(projectName);
154        
155        ModifiableResourceCollection documentRoot = getModuleRoot(project, false);
156        
157        Map<String, Object> rightsData = new HashMap<>();
158        UserIdentity user = _currentUserProvider.getUser();
159        
160        // Add file / folder
161        rightsData.put("add-file", _rightManager.hasRight(user, "Plugin_Explorer_File_Add", documentRoot) == RightResult.RIGHT_ALLOW);
162        rightsData.put("add-folder", _rightManager.hasRight(user, "Plugin_Explorer_Folder_Add", documentRoot) == RightResult.RIGHT_ALLOW);
163        rightsData.put("add-cmis-folder", _rightManager.hasRight(user, "Plugin_Explorer_CMIS_Add", documentRoot) == RightResult.RIGHT_ALLOW);
164        
165        // Tags
166        rightsData.put("add-tag", _projectRightHelper.hasRight("Plugins_Workspaces_Rights_Project_Add_Tag", project));
167        rightsData.put("remove-tag", _projectRightHelper.hasRight("Plugins_Workspaces_Rights_Project_Delete_Tag", project));
168        
169        return rightsData;
170    }
171    
172    @Override
173    public ModifiableResourceCollection getModuleRoot(Project project, boolean create)
174    {
175        try
176        {
177            ExplorerNode projectRootNode = project.getExplorerRootNode();
178            
179            if (projectRootNode instanceof ModifiableResourceCollection)
180            {
181                ModifiableResourceCollection projectRootNodeRc = (ModifiableResourceCollection) projectRootNode;
182                return _getAmetysObject(projectRootNodeRc, WORKSPACES_DOCUMENTS_NODE_NAME, JCRResourcesCollectionFactory.RESOURCESCOLLECTION_NODETYPE, create);
183            }
184            else
185            {
186                throw new IllegalClassException(ModifiableResourceCollection.class, projectRootNode.getClass());
187            }
188        }
189        catch (AmetysRepositoryException e)
190        {
191            throw new AmetysRepositoryException("Error getting the documents root node.", e);
192        }
193    }
194
195    
196    /**
197     * Utility method to get or create an ametys object
198     * @param <A> A sub class of AmetysObject
199     * @param parent The parent object
200     * @param name The ametys object name
201     * @param type The ametys object type
202     * @param create True to create the object if it does not exist
203     * @return ametys object
204     * @throws AmetysRepositoryException if an repository error occurs
205     */
206    protected <A extends AmetysObject> A _getAmetysObject(ModifiableTraversableAmetysObject parent, String name, String type, boolean create) throws AmetysRepositoryException
207    {
208        A object = null;
209        
210        if (parent.hasChild(name))
211        {
212            object = parent.getChild(name);
213        }
214        else if (create)
215        {
216            object = parent.createChild(name, type);
217            parent.saveChanges();
218        }
219        
220        return object;
221    }
222
223    @Override
224    public Set<String> getAllowedEventTypes()
225    {
226        return ImmutableSet.of("resource.created", "resource.updated", "resource.renamed");
227    }
228}