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.ExplorerNode; 032import org.ametys.plugins.explorer.ObservationConstants; 033import org.ametys.plugins.explorer.resources.ModifiableResourceCollection; 034import org.ametys.plugins.explorer.resources.Resource; 035import org.ametys.plugins.explorer.resources.ResourceCollection; 036import org.ametys.plugins.repository.AmetysObject; 037import org.ametys.plugins.repository.AmetysRepositoryException; 038import org.ametys.plugins.repository.data.holder.ModifiableModelAwareDataHolder; 039import org.ametys.plugins.workspaces.AbstractWorkspaceModule; 040import org.ametys.plugins.workspaces.documents.jcr.FolderFactory; 041import org.ametys.plugins.workspaces.project.objects.Project; 042import org.ametys.plugins.workspaces.util.StatisticColumn; 043import org.ametys.plugins.workspaces.util.StatisticsColumnType; 044import org.ametys.runtime.i18n.I18nizableText; 045import org.ametys.web.repository.page.ModifiablePage; 046import org.ametys.web.repository.page.ModifiableZone; 047import org.ametys.web.repository.page.ModifiableZoneItem; 048import org.ametys.web.repository.page.ZoneItem.ZoneType; 049 050import com.google.common.collect.ImmutableSet; 051 052/** 053 * Helper component for managing documents 054 */ 055public class DocumentWorkspaceModule extends AbstractWorkspaceModule 056{ 057 /** The id of document module */ 058 public static final String DOCUMENT_MODULE_ID = DocumentWorkspaceModule.class.getName(); 059 060 /** Workspaces documents node name */ 061 public static final String WORKSPACES_DOCUMENTS_NODE_NAME = "documents"; 062 063 private static final String __DOCUMENT_NUMBER_HEADER_ID = WORKSPACES_DOCUMENTS_NODE_NAME + "$document_number"; 064 065 @Override 066 public void contextualize(Context context) throws ContextException 067 { 068 _context = context; 069 } 070 071 @Override 072 public String getId() 073 { 074 return DOCUMENT_MODULE_ID; 075 } 076 077 @Override 078 public String getModuleName() 079 { 080 return WORKSPACES_DOCUMENTS_NODE_NAME; 081 } 082 083 public int getOrder() 084 { 085 return ORDER_DOCUMENTS; 086 } 087 088 @Override 089 protected String getModulePageName() 090 { 091 return "documents"; 092 } 093 094 public I18nizableText getModuleTitle() 095 { 096 return new I18nizableText("plugin." + _pluginName, "PLUGINS_WORKSPACES_PROJECT_SERVICE_MODULE_DOCUMENT_LABEL"); 097 } 098 public I18nizableText getModuleDescription() 099 { 100 return new I18nizableText("plugin." + _pluginName, "PLUGINS_WORKSPACES_PROJECT_SERVICE_MODULE_DOCUMENT_DESCRIPTION"); 101 } 102 @Override 103 protected I18nizableText getModulePageTitle() 104 { 105 return new I18nizableText("plugin." + _pluginName, "PLUGINS_WORKSPACES_PROJECT_WORKSPACE_PAGE_DOCUMENTS_TITLE"); 106 } 107 108 @Override 109 protected void initializeModulePage(ModifiablePage documentPage) 110 { 111 ModifiableZone defaultZone = documentPage.createZone("default"); 112 113 String serviceId = "org.ametys.plugins.workspaces.module.Document"; 114 ModifiableZoneItem defaultZoneItem = defaultZone.addZoneItem(); 115 defaultZoneItem.setType(ZoneType.SERVICE); 116 defaultZoneItem.setServiceId(serviceId); 117 118 ModifiableModelAwareDataHolder serviceDataHolder = defaultZoneItem.getServiceParameters(); 119 serviceDataHolder.setValue("xslt", _getDefaultXslt(serviceId)); 120 } 121 122 /** 123 * Get the URI of a folder in project'site 124 * @param project The project 125 * @param collectionId The id of collection 126 * @return The thread uri 127 */ 128 public String getFolderUri(Project project, String collectionId) 129 { 130 String moduleUrl = getModuleUrl(project); 131 if (moduleUrl != null) 132 { 133 StringBuilder sb = new StringBuilder(); 134 sb.append(moduleUrl); 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.canAddTag(project)); 167 rightsData.put("remove-tag", _projectRightHelper.canRemoveTag(project)); 168 169 return rightsData; 170 } 171 172 @Override 173 public Set<String> getAllowedEventTypes() 174 { 175 return ImmutableSet.of(ObservationConstants.EVENT_RESOURCE_CREATED, 176 org.ametys.plugins.workspaces.ObservationConstants.EVENT_RESOURCE_COMMENTED, 177 ObservationConstants.EVENT_RESOURCE_RENAMED, 178 ObservationConstants.EVENT_RESOURCE_UPDATED); 179 } 180 181 @Override 182 public Map<String, Object> _getInternalStatistics(Project project, boolean isActive) 183 { 184 if (isActive) 185 { 186 ModifiableResourceCollection documentRoot = getModuleRoot(project, false); 187 long fileNumber = documentRoot.getChildren() 188 .stream() 189 .mapToLong(child -> _getFileNumber(child)) 190 .sum(); 191 return Map.of(__DOCUMENT_NUMBER_HEADER_ID, fileNumber); 192 } 193 else 194 { 195 return Map.of(__DOCUMENT_NUMBER_HEADER_ID, __SIZE_INACTIVE); 196 } 197 } 198 199 private long _getRessourceSize(AmetysObject document) 200 { 201 if (document instanceof Resource) 202 { 203 Resource file = (Resource) document; 204 return file.getLength(); 205 } 206 else if (document instanceof ResourceCollection) 207 { 208 ResourceCollection folder = (ResourceCollection) document; 209 return folder.getChildren() 210 .stream() 211 .mapToLong(child -> _getRessourceSize(child)) 212 .sum(); 213 } 214 return 0; 215 } 216 217 private long _getFileNumber(AmetysObject document) 218 { 219 if (document instanceof Resource) 220 { 221 return 1; 222 } 223 else if (document instanceof ResourceCollection) 224 { 225 ResourceCollection folder = (ResourceCollection) document; 226 return folder.getChildren() 227 .stream() 228 .mapToLong(child -> _getFileNumber(child)) 229 .sum(); 230 } 231 return 0; 232 } 233 234 @Override 235 public List<StatisticColumn> _getInternalStatisticModel() 236 { 237 238 return List.of(new StatisticColumn(__DOCUMENT_NUMBER_HEADER_ID, new I18nizableText("plugin." + _pluginName, "PLUGINS_WORKSPACES_PROJECT_STATISTICS_TOOL_COLUMN_FILE_NUMBER")) 239 .withRenderer("Ametys.plugins.workspaces.project.tool.ProjectsGridHelper.renderElements") 240 .withType(StatisticsColumnType.LONG) 241 .withGroup(GROUP_HEADER_ELEMENTS_ID)); 242 } 243 244 @Override 245 protected long _getModuleSize(Project project) 246 { 247 return getModuleRoot(project, false).getChildren() 248 .stream() 249 .mapToLong(child -> _getRessourceSize(child)) 250 .sum(); 251 } 252 253 @Override 254 protected boolean _showModuleSize() 255 { 256 return true; 257 } 258 259 @Override 260 public Set<String> getAllEventTypes() 261 { 262 return Set.of(ObservationConstants.EVENT_RESOURCE_CREATED, 263 org.ametys.plugins.workspaces.ObservationConstants.EVENT_RESOURCE_COMMENTED, 264 ObservationConstants.EVENT_RESOURCE_DELETED, 265 ObservationConstants.EVENT_RESOURCE_MOVED, 266 ObservationConstants.EVENT_RESOURCE_RENAMED, 267 ObservationConstants.EVENT_RESOURCE_UPDATED); 268 } 269 270 @Override 271 public ModifiableResourceCollection getModuleRoot(Project project, boolean create) 272 { 273 try 274 { 275 ExplorerNode projectRootNode = project.getExplorerRootNode(); 276 277 if (projectRootNode instanceof ModifiableResourceCollection projectRootNodeRc) 278 { 279 return _getAmetysObject(projectRootNodeRc, getModuleName(), FolderFactory.FOLDER_NODETYPE, create); 280 } 281 else 282 { 283 throw new IllegalArgumentException("Error getting the " + getModuleName() + " root node : it should be a ModifiableResourceCollection and not " + projectRootNode.getClass()); 284 } 285 } 286 catch (AmetysRepositoryException e) 287 { 288 throw new AmetysRepositoryException("Error getting the " + getModuleName() + " root node.", e); 289 } 290 } 291}