001/* 002 * Copyright 2024 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.ArrayList; 019import java.util.HashMap; 020import java.util.List; 021import java.util.Map; 022import java.util.stream.Collectors; 023 024import org.apache.avalon.framework.component.Component; 025import org.apache.avalon.framework.service.ServiceException; 026import org.apache.avalon.framework.service.ServiceManager; 027import org.apache.commons.lang3.StringUtils; 028 029import org.ametys.cms.repository.comment.AbstractComment; 030import org.ametys.cms.tag.Tag; 031import org.ametys.core.user.UserIdentity; 032import org.ametys.core.util.DateUtils; 033import org.ametys.plugins.explorer.ModifiableExplorerNode; 034import org.ametys.plugins.explorer.resources.ModifiableResource; 035import org.ametys.plugins.explorer.resources.Resource; 036import org.ametys.plugins.explorer.resources.ResourceCollection; 037import org.ametys.plugins.repository.AmetysObject; 038import org.ametys.plugins.repository.ModifiableAmetysObject; 039import org.ametys.plugins.repository.tag.TagAwareAmetysObject; 040import org.ametys.plugins.workspaces.WorkspacesHelper; 041import org.ametys.plugins.workspaces.documents.WorkspaceExplorerResourceDAO.ResourceType; 042import org.ametys.plugins.workspaces.project.ProjectManager; 043import org.ametys.plugins.workspaces.project.modules.WorkspaceModuleExtensionPoint; 044import org.ametys.plugins.workspaces.project.objects.Project; 045import org.ametys.plugins.workspaces.util.WorkspaceObjectJSONHelper; 046 047/** 048 * Helper to convert documents to JSON 049 */ 050public class DocumentsJSONHelper extends WorkspaceObjectJSONHelper implements Component 051{ 052 /** The Avalon role */ 053 public static final String ROLE = DocumentsJSONHelper.class.getName(); 054 055 /** The project manager */ 056 protected ProjectManager _projectManager; 057 058 private WorkspaceModuleExtensionPoint _moduleEP; 059 private WorkspacesHelper _workspaceHelper; 060 061 @Override 062 public void service(ServiceManager manager) throws ServiceException 063 { 064 super.service(manager); 065 _moduleEP = (WorkspaceModuleExtensionPoint) manager.lookup(WorkspaceModuleExtensionPoint.ROLE); 066 _workspaceHelper = (WorkspacesHelper) manager.lookup(WorkspacesHelper.ROLE); 067 _projectManager = (ProjectManager) manager.lookup(ProjectManager.ROLE); 068 } 069 070 /** 071 * return a list of comments in JSON format 072 * @param <T> type of the value to retrieve 073 * @param comments the comments to translate as JSON 074 * @param lang the current language 075 * @param siteName The current site name 076 * @return list of comments 077 */ 078 public <T extends AbstractComment> List<Map<String, Object>> commentsToJson(List<T> comments, String lang, String siteName) 079 { 080 List<Map<String, Object>> json = new ArrayList<>(); 081 082 for (T comment : comments) 083 { 084 Map<String, Object> commentAsJSON = _commentToJson(comment, lang, siteName, null, true); 085 // As we do not want file comments to be editable or deletable, remove rights 086 commentAsJSON.put("canHandle", false); 087 json.add(commentAsJSON); 088 } 089 090 return json; 091 } 092 093 /** 094 * Internal method to extract the valuable data of a folder 095 * @param folder The folder 096 * @return the valuable folder data 097 */ 098 public Map<String, Object> extractCommonFolderData(ResourceCollection folder) 099 { 100 Map<String, Object> data = new HashMap<>(); 101 102 data.put("id", folder.getId()); 103 data.put("name", folder.getName()); 104 data.put("type", ResourceType.FOLDER.name().toLowerCase()); 105 data.put("description", StringUtils.defaultString(folder.getDescription())); 106 107 AmetysObject parent = folder.getParent(); 108 if (parent != null && parent instanceof ResourceCollection) 109 { 110 data.put("location", parent.getName()); 111 data.put("parentId", parent.getId()); 112 } 113 114 115 data.put("modifiable", folder instanceof ModifiableAmetysObject); 116 data.put("canCreateChild", folder instanceof ModifiableExplorerNode); 117 DocumentWorkspaceModule module = _moduleEP.getModule(DocumentWorkspaceModule.DOCUMENT_MODULE_ID); 118 data.put("length", String.valueOf(module.getRessourceSize(folder))); 119 120 data.put("notification", false); // TODO unread notification (not yet supported) 121 122 return data; 123 } 124 125 /** 126 * Internal method to extract the valuable data of a file 127 * @param file The file 128 * @return the valuable file data 129 */ 130 public Map<String, Object> extractCommonFileData(Resource file) 131 { 132 Map<String, Object> data = new HashMap<>(); 133 134 data.put("id", file.getId()); 135 data.put("name", file.getName()); 136 137 data.put("type", ResourceType.FILE.name().toLowerCase()); 138 data.put("fileType", _workspaceHelper.getFileType(file).name().toLowerCase()); 139 data.put("fileExtension", StringUtils.substringAfterLast(file.getName(), ".")); 140 141 AmetysObject parent = file.getParent(); 142 if (parent != null && parent instanceof ResourceCollection) 143 { 144 data.put("location", parent.getName()); 145 data.put("parentId", parent.getId()); 146 data.put("parentPath", ((ResourceCollection) parent).getExplorerPath()); 147 } 148 149 data.put("modifiable", file instanceof ModifiableResource); 150 data.put("canCreateChild", file instanceof ModifiableExplorerNode); 151 data.put("tags", tags2json(file)); 152 data.put("mimetype", file.getMimeType()); 153 data.put("length", String.valueOf(file.getLength())); 154 155 boolean image = _workspaceHelper.isImage(file); 156 if (image) 157 { 158 data.put("image", true); 159 } 160 161 UserIdentity creatorIdentity = file.getCreator(); 162 data.put("creator", _userHelper.user2json(creatorIdentity)); 163 data.put("creationDate", DateUtils.dateToString(file.getCreationDate())); 164 165 UserIdentity contribIdentity = file.getLastContributor(); 166 data.put("author", _userHelper.user2json(contribIdentity)); 167 data.put("lastModified", DateUtils.dateToString(file.getLastModified())); 168 169 return data; 170 } 171 172 /** 173 * Extract resource tags as JSON 174 * @param file the file containing the tags 175 * @return list of tags as JSON 176 */ 177 public List<Map<String, Object>> tags2json(Resource file) 178 { 179 Map<String, Object> contextParameters = new HashMap<>(); 180 181 Project project = _projectManager.getParentProject(file); 182 // if we can not get project from file, such as when we handle a trashed file, try to get project from request 183 if (project == null) 184 { 185 project = _workspaceHelper.getProjectFromRequest(); 186 } 187 if (project != null) 188 { 189 contextParameters.put("projectName", project.getName()); 190 } 191 192 193 return ((TagAwareAmetysObject) file).getTags() 194 .stream() 195 .filter(tag -> _tagProviderExtensionPoint.hasTag(tag, contextParameters)) 196 .map(tag -> _tagProviderExtensionPoint.getTag(tag, contextParameters)) 197 .map(this::tag2json) 198 .collect(Collectors.toList()); 199 } 200 201 /** 202 * Extract tag as JSON 203 * @param tag the tag to convert 204 * @return tag as JSON 205 */ 206 public Map<String, Object> tag2json(Tag tag) 207 { 208 Map<String, Object> tagMap = new HashMap<>(); 209 tagMap.put("text", tag.getTitle()); 210 tagMap.put("title", tag.getTitle()); 211 tagMap.put("name", tag.getName()); 212 tagMap.put("color", null); // FIXME tag color is not supported yet 213 214 return tagMap; 215 } 216 217}