001/* 002 * Copyright 2020 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.Map; 020import java.util.Set; 021import java.util.regex.Pattern; 022 023import org.apache.avalon.framework.service.ServiceException; 024import org.apache.avalon.framework.service.ServiceManager; 025import org.apache.cocoon.ProcessingException; 026import org.apache.cocoon.environment.ObjectModelHelper; 027import org.apache.cocoon.environment.Request; 028import org.apache.cocoon.generation.ServiceableGenerator; 029import org.apache.cocoon.xml.AttributesImpl; 030import org.apache.cocoon.xml.XMLUtils; 031import org.apache.commons.lang.StringUtils; 032import org.xml.sax.SAXException; 033 034import org.ametys.cms.repository.Content; 035import org.ametys.odf.course.Course; 036import org.ametys.odf.enumeration.OdfReferenceTableEntry; 037import org.ametys.odf.program.AbstractProgram; 038import org.ametys.odf.program.Program; 039import org.ametys.odf.program.SubProgram; 040import org.ametys.odf.skill.ODFSkillsHelper; 041 042/** 043 * SAX the skills hold by child courses of a {@link Program} or a not mutualised {@link SubProgram} 044 */ 045public class ProgramSkillsGenerator extends ServiceableGenerator 046{ 047 // FIXME Accept all view names starting with "main" to be able to make the ODF and ODF orientation skins coexist (whereas they use different main views) 048 private static final Set<Pattern> __ALLOWED_VIEW_NAMES = Set.of(Pattern.compile("main[a-z\\-]*")); 049 050 private ODFSkillsHelper _skillsHelper; 051 052 @Override 053 public void service(ServiceManager smanager) throws ServiceException 054 { 055 super.service(smanager); 056 _skillsHelper = (ODFSkillsHelper) smanager.lookup(ODFSkillsHelper.ROLE); 057 } 058 059 public void generate() throws IOException, SAXException, ProcessingException 060 { 061 Request request = ObjectModelHelper.getRequest(objectModel); 062 Content content = (Content) request.getAttribute(Content.class.getName()); 063 064 String viewName = request.getParameter("viewName"); 065 066 contentHandler.startDocument(); 067 068 if (StringUtils.isEmpty(viewName) || __ALLOWED_VIEW_NAMES.stream().anyMatch(p -> p.matcher(viewName).matches())) 069 { 070 if (content instanceof AbstractProgram abstractProgram) 071 { 072 Map<Content, Map<Content, Set<Content>>> skillsDistribution = _skillsHelper.getSkillsDistribution(abstractProgram, 2); 073 if (skillsDistribution != null) 074 { 075 saxSkillsDistribution(skillsDistribution); 076 } 077 } 078 else 079 { 080 getLogger().warn("Cannot get the skills of a non program '" + content.getId() + "'"); 081 } 082 } 083 084 contentHandler.endDocument(); 085 } 086 087 /** 088 * SAX the skills distribution 089 * @param distribution the skills distribution 090 * @throws IOException if an I/O error occurred 091 * @throws SAXException if an error occurred while saxing 092 */ 093 protected void saxSkillsDistribution(Map<Content, Map<Content, Set<Content>>> distribution) throws IOException, SAXException 094 { 095 XMLUtils.startElement(contentHandler, "skills"); 096 097 // Iterate on macro skills 098 for (Map.Entry<Content, Map<Content, Set<Content>>> macroSkillEntry : distribution.entrySet()) 099 { 100 Content macroSkill = macroSkillEntry.getKey(); 101 102 AttributesImpl attrs = new AttributesImpl(); 103 attrs.addCDATAAttribute("id", macroSkill.getId()); 104 attrs.addCDATAAttribute("title", macroSkill.getTitle()); 105 attrs.addCDATAAttribute("code", macroSkill.getValue(OdfReferenceTableEntry.CODE, false, "")); 106 107 XMLUtils.startElement(contentHandler, "skillSet", attrs); 108 109 // Iterate on micro skills 110 for (Map.Entry<Content, Set<Content>> microSkillEntry : macroSkillEntry.getValue().entrySet()) 111 { 112 Content microSkill = microSkillEntry.getKey(); 113 114 attrs.clear(); 115 attrs.addCDATAAttribute("id", microSkill.getId()); 116 attrs.addCDATAAttribute("title", microSkill.getTitle()); 117 attrs.addCDATAAttribute("code", microSkill.getValue(OdfReferenceTableEntry.CODE, false, StringUtils.EMPTY)); 118 119 XMLUtils.startElement(contentHandler, "skill", attrs); 120 121 // Iterate on courses 122 for (Content course : microSkillEntry.getValue()) 123 { 124 attrs.clear(); 125 attrs.addCDATAAttribute("id", course.getId()); 126 attrs.addCDATAAttribute("title", course.getTitle()); 127 attrs.addCDATAAttribute("code", ((Course) course).getCode()); 128 129 XMLUtils.startElement(contentHandler, "course", attrs); 130 131 XMLUtils.endElement(contentHandler, "course"); 132 } 133 134 XMLUtils.endElement(contentHandler, "skill"); 135 } 136 137 XMLUtils.endElement(contentHandler, "skillSet"); 138 } 139 140 XMLUtils.endElement(contentHandler, "skills"); 141 } 142}