001/* 002 * Copyright 2010 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.odf.clientsideelement; 017 018import java.util.ArrayList; 019import java.util.HashMap; 020import java.util.HashSet; 021import java.util.List; 022import java.util.Map; 023import java.util.Set; 024import java.util.stream.Collectors; 025 026import org.apache.avalon.framework.service.ServiceException; 027import org.apache.avalon.framework.service.ServiceManager; 028import org.apache.commons.lang3.tuple.Pair; 029 030import org.ametys.cms.repository.Content; 031import org.ametys.core.ui.Callable; 032import org.ametys.odf.ODFHelper; 033import org.ametys.odf.ProgramItem; 034import org.ametys.odf.course.Course; 035import org.ametys.odf.helper.DeleteODFContentHelper; 036import org.ametys.odf.orgunit.OrgUnit; 037import org.ametys.odf.orgunit.RootOrgUnitProvider; 038 039/** 040 * This element creates an action button to delete a ODF content 041 */ 042public class DeleteContentClientSideElement extends org.ametys.cms.clientsideelement.DeleteContentClientSideElement 043{ 044 /** The root orgunit provider */ 045 protected RootOrgUnitProvider _rootOrgUnitProvider; 046 047 /** The delete ODF content helper */ 048 protected DeleteODFContentHelper _deleteODFContentHelper; 049 050 /** The ODF helper */ 051 protected ODFHelper _odfHelper; 052 053 @Override 054 public void service(ServiceManager manager) throws ServiceException 055 { 056 super.service(manager); 057 _rootOrgUnitProvider = (RootOrgUnitProvider) manager.lookup(RootOrgUnitProvider.ROLE); 058 _deleteODFContentHelper = (DeleteODFContentHelper) manager.lookup(DeleteODFContentHelper.ROLE); 059 _odfHelper = (ODFHelper) manager.lookup(ODFHelper.ROLE); 060 } 061 062 @Override 063 protected boolean _hasRight(Content content) 064 { 065 return _deleteODFContentHelper.hasRight(content); 066 } 067 068 @Override 069 protected boolean _isModifiable(Content content) 070 { 071 if (content instanceof OrgUnit && _rootOrgUnitProvider.isRoot(content.getId())) 072 { 073 // The root orgunit can not be deleted 074 return false; 075 } 076 077 return super._isModifiable(content); 078 } 079 080 @Override 081 protected boolean _isContentReferenced(Content content) 082 { 083 return _deleteODFContentHelper.isContentReferenced(content); 084 } 085 086 /** 087 * Get information of the ODF content structure (type, if program has children) 088 * @param odfContentIds the list of ODF content id 089 * @return a map of information 090 */ 091 @Callable 092 public Map<String, Object> getStructureInfo(List<String> odfContentIds) 093 { 094 Map<String, Object> results = new HashMap<>(); 095 results.putAll(_odfHelper.getStructureInfo(odfContentIds)); 096 097 List<ProgramItem> programItems = odfContentIds.stream() 098 .map(id -> _resolver.resolveById(id)) 099 .filter(ProgramItem.class::isInstance) 100 .map(ProgramItem.class::cast) 101 .toList(); 102 if (!programItems.isEmpty()) 103 { 104 // For the program item deletion, we need to have the number of content to delete 105 // Loop for each content to not count shareable content twice 106 // We need to split the course count with the other content because of the deletion mode 107 Set<String> onlyStructureContentsIds = new HashSet<>(); 108 Set<String> courseIds = new HashSet<>(); 109 for (ProgramItem programItem : programItems) 110 { 111 Pair<Set<String>, Set<String>> childContents = _getChildContents(programItem); 112 onlyStructureContentsIds.addAll(childContents.getLeft()); 113 courseIds.addAll(childContents.getRight()); 114 } 115 116 results.put("nbOnlyStructureContents", onlyStructureContentsIds.size()); 117 results.put("nbCourses", courseIds.size()); 118 } 119 120 return results; 121 } 122 123 private Pair<Set<String>, Set<String>> _getChildContents(ProgramItem programItem) 124 { 125 Set<String> onlyStructureContentsIds = new HashSet<>(); 126 Set<String> courseIds = new HashSet<>(); 127 128 for (ProgramItem item : _odfHelper.getChildProgramItems(programItem)) 129 { 130 if (item instanceof Course) 131 { 132 courseIds.add(item.getId()); 133 } 134 else 135 { 136 onlyStructureContentsIds.add(item.getId()); 137 } 138 Pair<Set<String>, Set<String>> childContents = _getChildContents(item); 139 onlyStructureContentsIds.addAll(childContents.getLeft()); 140 courseIds.addAll(childContents.getRight()); 141 } 142 143 return Pair.of(onlyStructureContentsIds, courseIds); 144 } 145 146 /** 147 * Delete ODF contents 148 * @param contentsId The ids of contents to delete 149 * @param parameters the additional parameters 150 * @return the deleted and undeleted contents 151 */ 152 @SuppressWarnings("unchecked") 153 @Callable 154 public Map<String, Object> deleteContents(List<String> contentsId, Map<String, Object> parameters) 155 { 156 Map<String, Map<String, Object>> initialContentParameters = new HashMap<>(); 157 for (String contentId : contentsId) 158 { 159 initialContentParameters.put(contentId, getContentDefaultParameters(_resolver.resolveById(contentId))); 160 } 161 162 Map<String, Object> deleteResults = _deleteODFContentHelper.deleteContents(contentsId, (String) parameters.get("mode")); 163 164 Map<String, Object> updatedResults = new HashMap<>(); 165 Set<Content> allReferencedContents = new HashSet<>(); 166 Set<Content> allLockedContents = new HashSet<>(); 167 Set<Content> allUnauthorizedContents = new HashSet<>(); 168 Set<Content> allUnDeletedContents = new HashSet<>(); 169 for (String deletedContentId : deleteResults.keySet()) 170 { 171 Map<String, Object> deleteResult = (Map<String, Object>) deleteResults.get(deletedContentId); 172 Map<String, Object> updatedContentResults = new HashMap<>(); 173 174 if (deleteResult.containsKey("check-before-deletion-failed")) 175 { 176 updatedContentResults.put("check-before-deletion-failed", deleteResult.get("check-before-deletion-failed")); 177 } 178 179 String initialContentId = (String) deleteResult.get("initial-content"); 180 updatedContentResults.put("initial-content", initialContentParameters.get(initialContentId)); 181 182 List<Map<String, Object>> deletedContents = new ArrayList<>(); 183 for (String deleteContentId : (Set<String>) deleteResult.get("deleted-contents")) 184 { 185 Map<String, Object> deleteParameters = new HashMap<>(); 186 deleteParameters.put("id", deleteContentId); 187 deletedContents.add(deleteParameters); 188 } 189 updatedContentResults.put("deleted-contents", deletedContents); 190 191 List<Map<String, Object>> undeletedContents = new ArrayList<>(); 192 for (Content content : (Set<Content>) deleteResult.get("undeleted-contents")) 193 { 194 allUnDeletedContents.add(content); 195 undeletedContents.add(getContentDefaultParameters(content)); 196 } 197 updatedContentResults.put("undeleted-contents", undeletedContents); 198 199 List<Map<String, Object>> referencedContents = new ArrayList<>(); 200 for (Content content : (Set<Content>) deleteResult.get("referenced-contents")) 201 { 202 allReferencedContents.add(content); 203 referencedContents.add(getContentDefaultParameters(content)); 204 } 205 updatedContentResults.put("referenced-contents", referencedContents); 206 207 // Update the description for locked contents 208 List<Map<String, Object>> updatedLockedContents = new ArrayList<>(); 209 for (Content content : (Set<Content>) deleteResult.get("locked-contents")) 210 { 211 allLockedContents.add(content); 212 Map<String, Object> contentParameters = getContentDefaultParameters(content); 213 contentParameters.put("description", _getLockedDescription(content)); 214 updatedLockedContents.add(contentParameters); 215 } 216 updatedContentResults.put("locked-contents", updatedLockedContents); 217 218 // Update the description for unauthorized contents 219 List<Map<String, Object>> updatedUnauthorizedContents = new ArrayList<>(); 220 for (Content content : (Set<Content>) deleteResult.get("unauthorized-contents")) 221 { 222 allUnauthorizedContents.add(content); 223 Map<String, Object> contentParameters = getContentDefaultParameters(content); 224 contentParameters.put("description", _getNoRightDescription(content)); 225 updatedUnauthorizedContents.add(contentParameters); 226 } 227 updatedContentResults.put("unauthorized-contents", updatedUnauthorizedContents); 228 229 updatedResults.put(deletedContentId, updatedContentResults); 230 } 231 232 // Add the list of all referenced contents (removing duplicate contents) 233 List<Map<String, Object>> allReferencedContentsMap = allReferencedContents.stream() 234 .map(c -> getContentDefaultParameters(c)) 235 .collect(Collectors.toList()); 236 237 updatedResults.put("all-referenced-contents", allReferencedContentsMap); 238 239 // Add the list of all locked contents (removing duplicate contents) 240 List<Map<String, Object>> allLockedContentsMap = allLockedContents.stream() 241 .map(c -> getContentDefaultParameters(c)) 242 .collect(Collectors.toList()); 243 244 updatedResults.put("all-locked-contents", allLockedContentsMap); 245 246 // Add the list of all unauthorized contents (removing duplicate contents) 247 List<Map<String, Object>> allUnauthorizedContentsMap = allUnauthorizedContents.stream() 248 .map(c -> getContentDefaultParameters(c)) 249 .collect(Collectors.toList()); 250 251 updatedResults.put("all-unauthorized-contents", allUnauthorizedContentsMap); 252 253 // Add the list of all undeleted contents (removing duplicate contents) 254 List<Map<String, Object>> allUnDeletedContentsMap = allUnDeletedContents.stream() 255 .map(c -> getContentDefaultParameters(c)) 256 .collect(Collectors.toList()); 257 258 updatedResults.put("all-undeleted-contents", allUnDeletedContentsMap); 259 260 return updatedResults; 261 } 262 263 @Override 264 protected Map<String, Object> getContentDefaultParameters(Content content) 265 { 266 Map<String, Object> contentDefaultParameters = super.getContentDefaultParameters(content); 267 268 if (content instanceof ProgramItem && content.hasValue(ProgramItem.CODE) && contentDefaultParameters.containsKey("title")) 269 { 270 String title = (String) contentDefaultParameters.get("title"); 271 contentDefaultParameters.put("title", title + " (" + content.getValue(ProgramItem.CODE) + ")"); 272 } 273 274 return contentDefaultParameters; 275 } 276}