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.odf.clientsideelement; 017 018import java.util.ArrayList; 019import java.util.HashMap; 020import java.util.List; 021import java.util.Map; 022 023import org.ametys.cms.clientsideelement.SmartContentClientSideElement; 024import org.ametys.cms.repository.Content; 025import org.ametys.core.ui.Callable; 026import org.ametys.odf.ProgramItem; 027import org.ametys.odf.course.Course; 028import org.ametys.odf.course.CourseContainer; 029import org.ametys.odf.courselist.CourseList; 030import org.ametys.odf.courselist.CourseListContainer; 031import org.ametys.odf.coursepart.CoursePart; 032import org.ametys.odf.program.ProgramPart; 033import org.ametys.odf.program.TraversableProgramPart; 034import org.ametys.plugins.repository.UnknownAmetysObjectException; 035import org.ametys.runtime.i18n.I18nizableText; 036 037/** 038 * This client side element is enabled if the catalog of a {@link Course} can be edited 039 * 040 */ 041public class EditCatalogClientSideElement extends SmartContentClientSideElement 042{ 043 /** 044 * Get informations on contents' state 045 * @param contentsId the ids of contents 046 * @return informations on contents' state 047 */ 048 @Callable 049 public Map<String, Object> getStatus(List<String> contentsId) 050 { 051 Map<String, Object> results = new HashMap<>(); 052 053 results.put("unmodifiable-contents", new ArrayList<Map<String, Object>>()); 054 results.put("locked-contents", new ArrayList<Map<String, Object>>()); 055 results.put("invalidworkflowaction-contents", new ArrayList<Map<String, Object>>()); 056 results.put("unmodifiablecatalog-contents", new ArrayList<Map<String, Object>>()); 057 results.put("referenced-contents", new ArrayList<Map<String, Object>>()); 058 results.put("allright-contents", new ArrayList<Map<String, Object>>()); 059 060 for (String contentId : contentsId) 061 { 062 Content content = _resolver.resolveById(contentId); 063 064 if (content instanceof ProgramItem) 065 { 066 boolean error = false; 067 068 // Is modifiable 069 String enabledOnModifiableOnly = (String) this._script.getParameters().get("enabled-on-modifiable-only"); 070 if ("true".equals(enabledOnModifiableOnly) && !_isModifiable(content)) 071 { 072 Map<String, Object> contentParams = getContentDefaultParameters (content); 073 contentParams.put("description", _getNoModifiableDescription(content)); 074 075 @SuppressWarnings("unchecked") 076 List<Map<String, Object>> unModifiableContents = (List<Map<String, Object>>) results.get("unmodifiable-contents"); 077 unModifiableContents.add(contentParams); 078 079 error = true; 080 } 081 082 // Is locked 083 String enabledOnUnlockOnly = (String) this._script.getParameters().get("enabled-on-unlock-only"); 084 if ("true".equals(enabledOnUnlockOnly) && _isLocked(content)) 085 { 086 Map<String, Object> contentParams = getContentDefaultParameters (content); 087 contentParams.put("description", _getLockedDescription(content)); 088 089 @SuppressWarnings("unchecked") 090 List<Map<String, Object>> lockedContents = (List<Map<String, Object>>) results.get("locked-contents"); 091 lockedContents.add(contentParams); 092 093 error = true; 094 } 095 096 // Is workflow action correct 097 String enabledOnWorkflowActionOnly = (String) this._script.getParameters().get("enabled-on-workflow-action-only"); 098 if (enabledOnWorkflowActionOnly != null) 099 { 100 int actionId = _workflowAction(content); 101 if (actionId == -1) 102 { 103 Map<String, Object> contentParams = getContentDefaultParameters (content); 104 contentParams.put("description", _getWorkflowActionUnvailableDescription(content)); 105 106 @SuppressWarnings("unchecked") 107 List<Map<String, Object>> invalidActionContents = (List<Map<String, Object>>) results.get("invalidworkflowaction-contents"); 108 invalidActionContents.add(contentParams); 109 110 error = true; 111 } 112 else 113 { 114 results.put("workflowaction-content-actionId", actionId); 115 } 116 } 117 118 // Is catalog can be edited ? 119 if (!_isCatalogModifiable(content)) 120 { 121 Map<String, Object> contentParams = getContentDefaultParameters (content); 122 contentParams.put("description", _getNoModifiableCatalogDescription(content)); 123 124 @SuppressWarnings("unchecked") 125 List<Map<String, Object>> unModifiableCatalogContents = (List<Map<String, Object>>) results.get("unmodifiablecatalog-contents"); 126 unModifiableCatalogContents.add(contentParams); 127 128 error = true; 129 } 130 131 // Is part of ODF contents ? 132 if (_isReferenced(content)) 133 { 134 Map<String, Object> contentParams = getContentDefaultParameters (content); 135 contentParams.put("description", _getReferencedDescription(content)); 136 137 @SuppressWarnings("unchecked") 138 List<Map<String, Object>> referencedContents = (List<Map<String, Object>>) results.get("referenced-contents"); 139 referencedContents.add(contentParams); 140 141 error = true; 142 } 143 144 if (_isAllRight (content, error, results)) 145 { 146 Map<String, Object> contentParams = getContentDefaultParameters (content); 147 contentParams.put("description", _getAllRightDescription(content)); 148 149 @SuppressWarnings("unchecked") 150 List<Map<String, Object>> allrightContents = (List<Map<String, Object>>) results.get("allright-contents"); 151 allrightContents.add(contentParams); 152 } 153 } 154 } 155 156 return results; 157 } 158 159 private I18nizableText _getNoModifiableCatalogDescription (Content content) 160 { 161 List<String> modifiableI18nParameters = new ArrayList<>(); 162 modifiableI18nParameters.add(content.getTitle()); 163 164 I18nizableText ed = (I18nizableText) this._script.getParameters().get("nomodifiablecatalog-content-description"); 165 return new I18nizableText(ed.getCatalogue(), ed.getKey(), modifiableI18nParameters); 166 } 167 168 private I18nizableText _getReferencedDescription (Content content) 169 { 170 List<String> modifiableI18nParameters = new ArrayList<>(); 171 modifiableI18nParameters.add(content.getTitle()); 172 173 I18nizableText ed = (I18nizableText) this._script.getParameters().get("referenced-content-description"); 174 return new I18nizableText(ed.getCatalogue(), ed.getKey(), modifiableI18nParameters); 175 } 176 177 private boolean _isCatalogModifiable (Content content) 178 { 179 // Browse the ODF content children to detect if a child content is shared with other 180 return !_hasSharedContent(content); 181 } 182 183 private boolean _isReferenced (Content content) 184 { 185 if (content instanceof ProgramPart) 186 { 187 return content.getMetadataHolder().getStringArray(ProgramPart.METADATA_PARENT_PROGRAM_PARTS, new String[0]).length > 0; 188 } 189 else if (content instanceof Course) 190 { 191 return content.getMetadataHolder().getStringArray(Course.METADATA_PARENT_COURSE_LISTS, new String[0]).length > 0; 192 } 193 else if (content instanceof CourseList) 194 { 195 return content.getMetadataHolder().getStringArray(CourseList.METADATA_PARENT_COURSES, new String[0]).length > 0; 196 } 197 return true; 198 } 199 200 private boolean _hasSharedContent (Content content) 201 { 202 if (content instanceof TraversableProgramPart) 203 { 204 String[] children = content.getMetadataHolder().getStringArray(TraversableProgramPart.METADATA_CHILD_PROGRAM_PARTS, new String[0]); 205 for (String id : children) 206 { 207 try 208 { 209 Content child = _resolver.resolveById(id); 210 _isShared(child, ProgramPart.METADATA_PARENT_PROGRAM_PARTS); 211 } 212 catch (UnknownAmetysObjectException e) 213 { 214 // Nothing 215 } 216 } 217 } 218 219 if (content instanceof CourseContainer) 220 { 221 for (Course course : ((CourseContainer) content).getCourses()) 222 { 223 _isShared(course, Course.METADATA_PARENT_COURSE_LISTS); 224 } 225 } 226 227 if (content instanceof CourseListContainer) 228 { 229 for (CourseList cl : ((CourseListContainer) content).getCourseLists()) 230 { 231 try 232 { 233 if (_hasSharedContent(cl)) 234 { 235 return true; 236 } 237 } 238 catch (UnknownAmetysObjectException e) 239 { 240 // Nothing 241 } 242 } 243 } 244 245 if (content instanceof Course) 246 { 247 for (CoursePart coursePart : ((Course) content).getCourseParts()) 248 { 249 _isShared(coursePart, CoursePart.METADATA_PARENT_COURSES); 250 } 251 } 252 253 return false; 254 } 255 256 private boolean _isShared(Content content, String metadataName) 257 { 258 try 259 { 260 String[] parentIds = content.getMetadataHolder().getStringArray(metadataName, new String[0]); 261 if (parentIds.length > 1 || _hasSharedContent(content)) 262 { 263 return true; 264 } 265 } 266 catch (UnknownAmetysObjectException e) 267 { 268 // Nothing 269 } 270 271 return false; 272 } 273}