001/* 002 * Copyright 2019 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.content; 017 018import java.io.IOException; 019import java.util.List; 020import java.util.Locale; 021 022import org.apache.avalon.framework.service.ServiceException; 023import org.apache.avalon.framework.service.ServiceManager; 024import org.apache.cocoon.ProcessingException; 025import org.apache.cocoon.environment.ObjectModelHelper; 026import org.apache.cocoon.environment.Request; 027import org.apache.cocoon.generation.ServiceableGenerator; 028import org.apache.cocoon.xml.AttributesImpl; 029import org.apache.cocoon.xml.XMLUtils; 030import org.apache.commons.lang.StringUtils; 031import org.xml.sax.SAXException; 032 033import org.ametys.cms.contenttype.ContentTypesHelper; 034import org.ametys.cms.repository.Content; 035import org.ametys.odf.ODFHelper; 036import org.ametys.odf.ProgramItem; 037import org.ametys.odf.course.Course; 038import org.ametys.odf.courselist.CourseList; 039import org.ametys.odf.coursepart.CoursePart; 040import org.ametys.odf.enumeration.OdfReferenceTableEntry; 041import org.ametys.odf.enumeration.OdfReferenceTableHelper; 042import org.ametys.odf.program.AbstractProgram; 043import org.ametys.odf.program.Container; 044import org.ametys.odf.program.Program; 045import org.ametys.odf.program.SubProgram; 046import org.ametys.plugins.repository.AmetysRepositoryException; 047import org.ametys.runtime.model.View; 048import org.ametys.runtime.model.exception.BadItemTypeException; 049 050/** 051 * SAX the structure (ie. the child program items) of a {@link ProgramItem} 052 * 053 */ 054public class ProgramItemStructureGenerator extends ServiceableGenerator 055{ 056 /** The ODF helper */ 057 protected ODFHelper _odfHelper; 058 /** Helper for ODF reference table */ 059 protected OdfReferenceTableHelper _odfReferenceTableHelper; 060 /** The content types helper */ 061 protected ContentTypesHelper _cTypesHelper; 062 063 @Override 064 public void service(ServiceManager smanager) throws ServiceException 065 { 066 _odfHelper = (ODFHelper) smanager.lookup(ODFHelper.ROLE); 067 _odfReferenceTableHelper = (OdfReferenceTableHelper) smanager.lookup(OdfReferenceTableHelper.ROLE); 068 _cTypesHelper = (ContentTypesHelper) smanager.lookup(ContentTypesHelper.ROLE); 069 } 070 071 public void generate() throws IOException, SAXException, ProcessingException 072 { 073 Request request = ObjectModelHelper.getRequest(objectModel); 074 Content content = (Content) request.getAttribute(Content.class.getName()); 075 076 String metadataSetName = request.getParameter("metadataSetName"); 077 078 contentHandler.startDocument(); 079 080 if ("main".equals(metadataSetName) || StringUtils.isEmpty(metadataSetName)) 081 { 082 if (content instanceof ProgramItem) 083 { 084 XMLUtils.startElement(contentHandler, "structure"); 085 saxProgramItem((ProgramItem) content); 086 XMLUtils.endElement(contentHandler, "structure"); 087 } 088 else 089 { 090 getLogger().warn("Cannot get the structure of a non program item '" + content.getId() + "'"); 091 } 092 } 093 094 contentHandler.endDocument(); 095 } 096 097 /** 098 * SAX a program item with its child program items 099 * @param programItem the program item 100 * @throws SAXException if an error occurs while saxing 101 */ 102 protected void saxProgramItem(ProgramItem programItem) throws SAXException 103 { 104 if (programItem instanceof Program) 105 { 106 saxProgram((Program) programItem); 107 } 108 else if (programItem instanceof SubProgram) 109 { 110 saxSubProgram((SubProgram) programItem); 111 } 112 else if (programItem instanceof Container) 113 { 114 saxContainer((Container) programItem); 115 } 116 else if (programItem instanceof CourseList) 117 { 118 saxCourseList((CourseList) programItem); 119 } 120 else if (programItem instanceof Course) 121 { 122 saxCourse((Course) programItem); 123 } 124 } 125 126 /** 127 * SAX the child program items 128 * @param programItem the program item 129 * @throws SAXException if an error occurs while saxing 130 */ 131 protected void saxChildProgramItems(ProgramItem programItem) throws SAXException 132 { 133 List<ProgramItem> childProgramItems = _odfHelper.getChildProgramItems(programItem); 134 for (ProgramItem childProgramItem : childProgramItems) 135 { 136 saxProgramItem(childProgramItem); 137 } 138 } 139 140 /** 141 * SAX a program 142 * @param program the subprogram to SAX 143 * @throws SAXException if an error occurs 144 */ 145 protected void saxProgram(Program program) throws SAXException 146 { 147 AttributesImpl attrs = new AttributesImpl(); 148 _saxCommonAttributes(program, attrs); 149 150 XMLUtils.startElement(contentHandler, "program", attrs); 151 152 XMLUtils.startElement(contentHandler, "attributes"); 153 _saxStructureViewIfExists(program); 154 XMLUtils.endElement(contentHandler, "attributes"); 155 156 saxChildProgramItems(program); 157 XMLUtils.endElement(contentHandler, "program"); 158 } 159 160 /** 161 * SAX a subprogram 162 * @param subProgram the subprogram to SAX 163 * @throws SAXException if an error occurs 164 */ 165 protected void saxSubProgram(SubProgram subProgram) throws SAXException 166 { 167 AttributesImpl attrs = new AttributesImpl(); 168 _saxCommonAttributes(subProgram, attrs); 169 170 XMLUtils.startElement(contentHandler, "subprogram", attrs); 171 172 XMLUtils.startElement(contentHandler, "attributes"); 173 _saxReferenceTableItem(subProgram.getEcts(), AbstractProgram.ECTS, subProgram.getLanguage()); 174 _saxStructureViewIfExists(subProgram); 175 XMLUtils.endElement(contentHandler, "attributes"); 176 177 saxChildProgramItems(subProgram); 178 179 XMLUtils.endElement(contentHandler, "subprogram"); 180 } 181 182 /** 183 * SAX a container 184 * @param container the container to SAX 185 * @throws SAXException if an error occurs while saxing 186 */ 187 protected void saxContainer(Container container) throws SAXException 188 { 189 AttributesImpl attrs = new AttributesImpl(); 190 _saxCommonAttributes(container, attrs); 191 192 XMLUtils.startElement(contentHandler, "container", attrs); 193 194 XMLUtils.startElement(contentHandler, "attributes"); 195 _saxReferenceTableItem(container.getNature(), Container.NATURE, container.getLanguage()); 196 _saxReferenceTableItem(container.getPeriod(), Container.PERIOD, container.getLanguage()); 197 198 _saxStructureViewIfExists(container); 199 200 XMLUtils.endElement(contentHandler, "attributes"); 201 202 saxChildProgramItems(container); 203 204 XMLUtils.endElement(contentHandler, "container"); 205 } 206 207 /** 208 * SAX a course list 209 * @param cl the course list to SAX 210 * @throws SAXException if an error occurs while saxing 211 */ 212 protected void saxCourseList(CourseList cl) throws SAXException 213 { 214 AttributesImpl attrs = new AttributesImpl(); 215 _saxCommonAttributes(cl, attrs); 216 217 XMLUtils.startElement(contentHandler, "courselist", attrs); 218 219 XMLUtils.startElement(contentHandler, "attributes"); 220 _saxStructureViewIfExists(cl); 221 XMLUtils.endElement(contentHandler, "attributes"); 222 223 saxChildProgramItems(cl); 224 225 XMLUtils.endElement(contentHandler, "courselist"); 226 } 227 228 /** 229 * SAX a course 230 * @param course the container to SAX 231 * @throws SAXException if an error occurs while saxing 232 */ 233 protected void saxCourse(Course course) throws SAXException 234 { 235 AttributesImpl attrs = new AttributesImpl(); 236 _saxCommonAttributes(course, attrs); 237 238 XMLUtils.startElement(contentHandler, "course", attrs); 239 240 XMLUtils.startElement(contentHandler, "attributes"); 241 _saxReferenceTableItem(course.getCourseType(), Course.COURSE_TYPE, course.getLanguage()); 242 _saxStructureViewIfExists(course); 243 XMLUtils.endElement(contentHandler, "attributes"); 244 245 saxChildProgramItems(course); 246 247 saxCourseParts(course); 248 249 XMLUtils.endElement(contentHandler, "course"); 250 } 251 252 /** 253 * SAX a course part 254 * @param course The course 255 * @throws SAXException if an error occurs 256 */ 257 protected void saxCourseParts(Course course) throws SAXException 258 { 259 List<CoursePart> courseParts = course.getCourseParts(); 260 261 double totalHours = 0; 262 for (CoursePart coursePart : course.getCourseParts()) 263 { 264 totalHours += coursePart.getNumberOfHours(); 265 } 266 267 AttributesImpl attrs = new AttributesImpl(); 268 attrs.addCDATAAttribute("totalHours", String.valueOf(totalHours)); 269 XMLUtils.startElement(contentHandler, "courseparts", attrs); 270 271 for (CoursePart coursePart : courseParts) 272 { 273 saxCoursePart(coursePart); 274 } 275 276 XMLUtils.endElement(contentHandler, "courseparts"); 277 } 278 279 /** 280 * SAX a course part 281 * @param coursePart The course part to SAX 282 * @throws SAXException if an error occurs 283 */ 284 protected void saxCoursePart(CoursePart coursePart) throws SAXException 285 { 286 AttributesImpl attrs = new AttributesImpl(); 287 attrs.addCDATAAttribute("id", coursePart.getId()); 288 attrs.addCDATAAttribute("title", coursePart.getTitle()); 289 _addAttrIfNotEmpty(attrs, "code", coursePart.getCode()); 290 291 XMLUtils.startElement(contentHandler, "coursepart", attrs); 292 293 XMLUtils.startElement(contentHandler, "attributes"); 294 _saxReferenceTableItem(coursePart.getNature(), CoursePart.NATURE, coursePart.getLanguage()); 295 296 _saxStructureViewIfExists(coursePart); 297 298 XMLUtils.endElement(contentHandler, "attributes"); 299 300 XMLUtils.endElement(contentHandler, "coursepart"); 301 } 302 303 /** 304 * SAX the 'structure' view if exists 305 * @param content the content 306 * @throws SAXException if an error occurs 307 */ 308 protected void _saxStructureViewIfExists(Content content) throws SAXException 309 { 310 View view = _cTypesHelper.getView("structure", content.getTypes(), content.getMixinTypes()); 311 if (view != null) 312 { 313 try 314 { 315 content.dataToSAX(contentHandler, view, new Locale(content.getLanguage())); 316 } 317 catch (BadItemTypeException | AmetysRepositoryException | IOException e) 318 { 319 throw new SAXException("Fail to sax the 'structure' view for content " + content.getId(), e); 320 } 321 } 322 } 323 324 /** 325 * SAX the common attributes for program item 326 * @param programItem the program item 327 * @param attrs the attributes 328 */ 329 protected void _saxCommonAttributes(ProgramItem programItem, AttributesImpl attrs) 330 { 331 attrs.addCDATAAttribute("title", ((Content) programItem).getTitle()); 332 attrs.addCDATAAttribute("id", programItem.getId()); 333 attrs.addCDATAAttribute("code", programItem.getCode()); 334 attrs.addCDATAAttribute("name", programItem.getName()); 335 } 336 337 /** 338 * SAX the item of a reference table 339 * @param itemId the item id 340 * @param tagName the tag name 341 * @param lang the language to use 342 * @throws SAXException if an error occurs while saxing 343 */ 344 protected void _saxReferenceTableItem(String itemId, String tagName, String lang) throws SAXException 345 { 346 if (StringUtils.isNotEmpty(itemId)) 347 { 348 OdfReferenceTableEntry item = _odfReferenceTableHelper.getItem(itemId); 349 350 AttributesImpl attrs = new AttributesImpl(); 351 attrs.addCDATAAttribute("id", item.getId()); 352 _addAttrIfNotEmpty(attrs, "code", item.getCode()); 353 354 XMLUtils.createElement(contentHandler, tagName, attrs, item.getLabel(lang)); 355 356 } 357 } 358 359 /** 360 * Add an attribute if its not null or empty. 361 * @param attrs The attributes 362 * @param attrName The attribute name 363 * @param attrValue The attribute value 364 */ 365 protected void _addAttrIfNotEmpty(AttributesImpl attrs, String attrName, String attrValue) 366 { 367 if (StringUtils.isNotEmpty(attrValue)) 368 { 369 attrs.addCDATAAttribute(attrName, attrValue); 370 } 371 } 372 373}