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.List;
020import java.util.Map;
021import java.util.Set;
022
023import org.apache.avalon.framework.context.Context;
024import org.apache.avalon.framework.context.ContextException;
025import org.apache.cocoon.components.ContextHelper;
026import org.apache.cocoon.environment.Request;
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.ObservationConstants;
032import org.ametys.plugins.explorer.resources.ModifiableResourceCollection;
033import org.ametys.plugins.explorer.resources.Resource;
034import org.ametys.plugins.explorer.resources.ResourceCollection;
035import org.ametys.plugins.repository.AmetysObject;
036import org.ametys.plugins.repository.data.holder.ModifiableModelAwareDataHolder;
037import org.ametys.plugins.workspaces.AbstractWorkspaceModule;
038import org.ametys.plugins.workspaces.project.objects.Project;
039import org.ametys.plugins.workspaces.util.StatisticColumn;
040import org.ametys.plugins.workspaces.util.StatisticsColumnType;
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 * Helper component for managing documents
051 */
052public class DocumentWorkspaceModule extends AbstractWorkspaceModule
053{
054    /** The id of document module */
055    public static final String DOCUMENT_MODULE_ID = DocumentWorkspaceModule.class.getName();
056    
057    /** Workspaces documents node name */
058    public static final String WORKSPACES_DOCUMENTS_NODE_NAME = "documents";
059
060    private static final String __DOCUMENT_NUMBER_HEADER_ID = WORKSPACES_DOCUMENTS_NODE_NAME + "$document_number";
061    
062    @Override
063    public void contextualize(Context context) throws ContextException
064    {
065        _context = context;
066    }
067    
068    @Override
069    public String getId()
070    {
071        return DOCUMENT_MODULE_ID;
072    }
073    
074    @Override
075    public String getModuleName()
076    {
077        return WORKSPACES_DOCUMENTS_NODE_NAME;
078    }
079    
080    public int getOrder()
081    {
082        return ORDER_DOCUMENTS;
083    }
084    
085    @Override
086    protected String getModulePageName()
087    {
088        return "documents";
089    }
090    
091    public I18nizableText getModuleTitle()
092    {
093        return new I18nizableText("plugin." + _pluginName, "PLUGINS_WORKSPACES_PROJECT_SERVICE_MODULE_DOCUMENT_LABEL");
094    }
095    public I18nizableText getModuleDescription()
096    {
097        return new I18nizableText("plugin." + _pluginName, "PLUGINS_WORKSPACES_PROJECT_SERVICE_MODULE_DOCUMENT_DESCRIPTION");
098    }
099    @Override
100    protected I18nizableText getModulePageTitle()
101    {
102        return new I18nizableText("plugin." + _pluginName, "PLUGINS_WORKSPACES_PROJECT_WORKSPACE_PAGE_DOCUMENTS_TITLE");
103    }
104    
105    @Override
106    protected void initializeModulePage(ModifiablePage documentPage)
107    {
108        ModifiableZone defaultZone = documentPage.createZone("default");
109        
110        String serviceId = "org.ametys.plugins.workspaces.module.Document";
111        ModifiableZoneItem defaultZoneItem = defaultZone.addZoneItem();
112        defaultZoneItem.setType(ZoneType.SERVICE);
113        defaultZoneItem.setServiceId(serviceId);
114        
115        ModifiableModelAwareDataHolder serviceDataHolder = defaultZoneItem.getServiceParameters();
116        serviceDataHolder.setValue("xslt", _getDefaultXslt(serviceId));
117    }
118
119    /**
120     * Get the URI of a folder in project'site
121     * @param project The project
122     * @param collectionId The id of collection
123     * @return The thread uri
124     */
125    public String getFolderUri(Project project, String collectionId)
126    {
127        String moduleUrl = getModuleUrl(project);
128        if (moduleUrl != null)
129        {
130            StringBuilder sb = new StringBuilder();
131            sb.append(moduleUrl);
132            sb.append("#").append(collectionId);
133            
134            return sb.toString();
135        }
136        
137        return null;
138    }
139    
140    /**
141     * Retrieves the set of general rights used in the document module for the current user
142     * @return The map of right data. Keys are the rights id, and values indicates whether the current user has the right or not.
143     */
144    @Callable
145    public Map<String, Object> getModuleBaseRights()
146    {
147        Request request = ContextHelper.getRequest(_context);
148        
149        String projectName = (String) request.getAttribute("projectName");
150        Project project = _projectManager.getProject(projectName);
151        
152        ModifiableResourceCollection documentRoot = getModuleRoot(project, false);
153        
154        Map<String, Object> rightsData = new HashMap<>();
155        UserIdentity user = _currentUserProvider.getUser();
156        
157        // Add file / folder
158        rightsData.put("add-file", _rightManager.hasRight(user, "Plugin_Explorer_File_Add", documentRoot) == RightResult.RIGHT_ALLOW);
159        rightsData.put("add-folder", _rightManager.hasRight(user, "Plugin_Explorer_Folder_Add", documentRoot) == RightResult.RIGHT_ALLOW);
160        rightsData.put("add-cmis-folder", _rightManager.hasRight(user, "Plugin_Explorer_CMIS_Add", documentRoot) == RightResult.RIGHT_ALLOW);
161        
162        // Tags
163        rightsData.put("add-tag", _projectRightHelper.canAddTag(project));
164        rightsData.put("remove-tag", _projectRightHelper.canRemoveTag(project));
165        
166        return rightsData;
167    }
168
169    @Override
170    public Set<String> getAllowedEventTypes()
171    {
172        return ImmutableSet.of(ObservationConstants.EVENT_RESOURCE_CREATED,
173                ObservationConstants.EVENT_RESOURCE_COMMENTED,
174                ObservationConstants.EVENT_RESOURCE_RENAMED,
175                ObservationConstants.EVENT_RESOURCE_UPDATED);
176    }
177
178    @Override
179    public Map<String, Object> _getInternalStatistics(Project project, boolean isActive)
180    { 
181        if (isActive)
182        {
183            ModifiableResourceCollection documentRoot = getModuleRoot(project, false);
184            long fileNumber = documentRoot.getChildren()
185                    .stream()
186                    .mapToLong(child -> _getFileNumber(child))
187                    .sum();
188            return Map.of(__DOCUMENT_NUMBER_HEADER_ID, fileNumber);
189        }
190        else
191        {
192            return Map.of(__DOCUMENT_NUMBER_HEADER_ID, __SIZE_INACTIVE);
193        }
194    }
195    
196    private long _getRessourceSize(AmetysObject document)
197    {
198        if (document instanceof Resource)
199        {
200            Resource file = (Resource) document;
201            return file.getLength();
202        }
203        else if (document instanceof ResourceCollection)
204        {
205            ResourceCollection folder = (ResourceCollection) document;
206            return folder.getChildren()
207                .stream()
208                .mapToLong(child -> _getRessourceSize(child))
209                .sum();
210        }
211        return 0;
212    }
213    
214    private long _getFileNumber(AmetysObject document)
215    {
216        if (document instanceof Resource)
217        {
218            return 1;
219        }
220        else if (document instanceof ResourceCollection)
221        {
222            ResourceCollection folder = (ResourceCollection) document;
223            return folder.getChildren()
224                .stream()
225                .mapToLong(child -> _getFileNumber(child))
226                .sum();
227        }
228        return 0;
229    }
230
231    @Override
232    public List<StatisticColumn> _getInternalStatisticModel()
233    {
234
235        return List.of(new StatisticColumn(__DOCUMENT_NUMBER_HEADER_ID, new I18nizableText("plugin." + _pluginName, "PLUGINS_WORKSPACES_PROJECT_STATISTICS_TOOL_COLUMN_FILE_NUMBER"))
236                .withRenderer("Ametys.plugins.workspaces.project.tool.ProjectsGridHelper.renderElements")
237                .withType(StatisticsColumnType.LONG)
238                .withGroup(GROUP_HEADER_ELEMENTS_ID));
239    }
240    
241    @Override
242    protected long _getModuleSize(Project project)
243    {
244        return getModuleRoot(project, false).getChildren()
245            .stream()
246            .mapToLong(child -> _getRessourceSize(child))
247            .sum();
248    }
249
250    @Override
251    protected boolean _showModuleSize()
252    {
253        return true;
254    }
255
256    @Override
257    public Set<String> getAllEventTypes()
258    {
259        return Set.of(ObservationConstants.EVENT_RESOURCE_CREATED,
260                      ObservationConstants.EVENT_RESOURCE_COMMENTED,
261                      ObservationConstants.EVENT_RESOURCE_DELETED,
262                      ObservationConstants.EVENT_RESOURCE_MOVED,
263                      ObservationConstants.EVENT_RESOURCE_RENAMED,
264                      ObservationConstants.EVENT_RESOURCE_UPDATED);
265    }
266}