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.plugins.odfpilotage.report.impl; 017 018import java.io.File; 019import java.io.FileOutputStream; 020import java.util.List; 021import java.util.Map; 022import java.util.stream.Collectors; 023 024import javax.xml.transform.Result; 025import javax.xml.transform.TransformerFactory; 026import javax.xml.transform.sax.SAXTransformerFactory; 027import javax.xml.transform.sax.TransformerHandler; 028import javax.xml.transform.stream.StreamResult; 029 030import org.apache.avalon.framework.service.ServiceException; 031import org.apache.avalon.framework.service.ServiceManager; 032import org.apache.cocoon.xml.AttributesImpl; 033import org.apache.cocoon.xml.XMLUtils; 034import org.apache.commons.io.FileUtils; 035import org.apache.commons.lang3.StringUtils; 036import org.xml.sax.SAXException; 037 038import org.ametys.cms.FilterNameHelper; 039import org.ametys.odf.program.Program; 040import org.ametys.plugins.odfpilotage.report.consistency.AnalysisExtensionPoint; 041import org.ametys.plugins.odfpilotage.report.consistency.ConsistencyAnalysis; 042import org.ametys.plugins.odfpilotage.report.consistency.ConsistencyAnalysisResult; 043import org.ametys.plugins.odfpilotage.schedulable.AbstractReportSchedulable; 044import org.ametys.plugins.odfpilotage.schedulable.OrgUnitConsistencyExtractSchedulable; 045import org.ametys.plugins.odfpilotage.schedulable.ProgramConsistencyExtractSchedulable; 046import org.ametys.runtime.i18n.I18nizableText; 047 048import com.google.common.collect.ImmutableList; 049 050/** 051 * Class to generate consistency extract as DOC. 052 */ 053public class ConsistencyExtract extends AbstractExtract 054{ 055 /** The key for the analysis */ 056 public static final String PARAMETER_ANALYSIS = "analysis"; 057 058 /** The analysis extension point. */ 059 protected AnalysisExtensionPoint _analysisEP; 060 061 /** The analyses to apply. */ 062 protected List<ConsistencyAnalysis> _analyses; 063 064 @Override 065 public void service(ServiceManager manager) throws ServiceException 066 { 067 _analysisEP = (AnalysisExtensionPoint) manager.lookup(AnalysisExtensionPoint.ROLE); 068 super.service(manager); 069 } 070 071 @Override 072 protected String getType() 073 { 074 return "consistency"; 075 } 076 077 @Override 078 public boolean isGeneric() 079 { 080 return false; 081 } 082 083 @Override 084 protected boolean isCompatibleSchedulable(AbstractReportSchedulable schedulable) 085 { 086 return schedulable instanceof OrgUnitConsistencyExtractSchedulable || schedulable instanceof ProgramConsistencyExtractSchedulable; 087 } 088 089 @Override 090 protected String launchByOrgUnit(Map<String, String> reportParameters) throws Exception 091 { 092 _setAdditionalParameters(reportParameters); 093 return super.launchByOrgUnit(reportParameters); 094 } 095 096 @Override 097 protected String launchByProgram(Map<String, String> reportParameters) throws Exception 098 { 099 _setAdditionalParameters(reportParameters); 100 return super.launchByProgram(reportParameters); 101 } 102 103 /** 104 * Sax the additional parameters. 105 * @param reportParameters The report parameters 106 */ 107 protected void _setAdditionalParameters(Map<String, String> reportParameters) 108 { 109 String analysisId = reportParameters.get(PARAMETER_ANALYSIS); 110 if (StringUtils.isNotEmpty(analysisId)) 111 { 112 _analyses = ImmutableList.of(_analysisEP.getExtension(analysisId)); 113 } 114 else 115 { 116 // All analyses 117 _analyses = _analysisEP.getExtensionsIds() 118 .stream() 119 .map(_analysisEP::getExtension) 120 .collect(Collectors.toList()); 121 } 122 } 123 124 @Override 125 protected String _buildZipName(String contextName) 126 { 127 return FilterNameHelper.filterName(getType() + "-" + (_analyses.size() == 1 ? _analyses.get(0).getShortId() : "all") + "-" + getOutputFormat() + "-" + contextName + "-" + _currentFormattedDate) + ".zip"; 128 } 129 130 @Override 131 protected void _saxProgram(Program program) 132 { 133 SAXTransformerFactory factory = (SAXTransformerFactory) TransformerFactory.newInstance(); 134 135 String fileName = _getReportFileName(program); 136 137 File xmlFile = new File(_tmpFolder, fileName + ".xml"); 138 FileUtils.deleteQuietly(xmlFile); 139 140 try (FileOutputStream fos = new FileOutputStream(xmlFile)) 141 { 142 TransformerHandler handler = factory.newTransformerHandler(); 143 Result result = new StreamResult(fos); 144 handler.setResult(result); 145 146 handler.startDocument(); 147 148 AttributesImpl attrs = new AttributesImpl(); 149 attrs.addCDATAAttribute("xmlns:i18n", "http://apache.org/cocoon/i18n/2.1"); 150 attrs.addCDATAAttribute("type", getType()); 151 if (_analyses.size() == 1) 152 { 153 attrs.addCDATAAttribute("analysis", _analyses.get(0).getShortId()); 154 } 155 attrs.addCDATAAttribute("date", _reportHelper.getReadableCurrentDate()); 156 157 XMLUtils.startElement(handler, "report", attrs); 158 _saxReport(handler, program); 159 XMLUtils.endElement(handler, "report"); 160 161 handler.endDocument(); 162 163 // Convert the report to configured output format 164 convertReport(_tmpFolder, fileName, xmlFile); 165 } 166 catch (Exception e) 167 { 168 getLogger().error("An error occured while generating 'Cohérence' report for program '{}' ({})", program.getTitle(), program.getCode(), e); 169 } 170 finally 171 { 172 FileUtils.deleteQuietly(xmlFile); 173 } 174 } 175 176 /** 177 * Get the report filename for a given program 178 * @param program The program 179 * @return the file name 180 */ 181 private String _getReportFileName(Program program) 182 { 183 StringBuilder sb = new StringBuilder(); 184 185 sb.append("consistency-"); 186 187 // Catalog 188 sb.append(program.getCatalog()); 189 sb.append("-"); 190 191 // Lang 192 sb.append(program.getLanguage()); 193 sb.append("-"); 194 195 // Mention or title 196 String mentionId = program.getMention(); 197 if (StringUtils.isBlank(mentionId)) 198 { 199 sb.append(program.getTitle()); 200 } 201 else 202 { 203 sb.append(_refTableHelper.getItemLabel(mentionId, program.getLanguage())); 204 } 205 206 // Code Ametys 207 String code = program.getCode(); 208 if (StringUtils.isNotBlank(code)) 209 { 210 sb.append("-"); 211 sb.append(code); 212 } 213 214 // Date 215 sb.append("-"); 216 sb.append(_currentFormattedDate); 217 218 return FilterNameHelper.filterName(sb.toString()); 219 } 220 221 private void _saxReport(TransformerHandler handler, Program program) throws SAXException 222 { 223 AttributesImpl attr = new AttributesImpl(); 224 attr.addCDATAAttribute("title", program.getTitle()); 225 XMLUtils.startElement(handler, "program", attr); 226 227 for (ConsistencyAnalysis analysis : _analyses) 228 { 229 XMLUtils.startElement(handler, "analysis"); 230 231 // Title 232 analysis.getLabel().toSAX(handler, "title"); 233 234 // Result 235 ConsistencyAnalysisResult result = analysis.analyze(program); 236 237 // Status 238 AttributesImpl attrs = new AttributesImpl(); 239 attrs.addCDATAAttribute("bgColor", result.getStatus().getBgColor()); 240 attrs.addCDATAAttribute("fontColor", result.getStatus().getFontColor()); 241 XMLUtils.startElement(handler, "status", attrs); 242 result.getStatusText().toSAX(handler); 243 XMLUtils.endElement(handler, "status"); 244 245 // Introduction 246 result.getIntroText().toSAX(handler, "intro"); 247 248 // Columns 249 XMLUtils.startElement(handler, "columns"); 250 Map<String, I18nizableText> columns = result.getColumns(); 251 List<String> indentableColumns = result.getIndentableColumns(); 252 for (String key : columns.keySet()) 253 { 254 AttributesImpl columnAttrs = new AttributesImpl(); 255 columnAttrs.addCDATAAttribute("name", key); 256 columnAttrs.addCDATAAttribute("indentable", String.valueOf(indentableColumns.contains(key))); 257 258 XMLUtils.startElement(handler, "column", columnAttrs); 259 columns.get(key).toSAX(handler); 260 XMLUtils.endElement(handler, "column"); 261 } 262 XMLUtils.endElement(handler, "columns"); 263 264 // Lines list 265 XMLUtils.startElement(handler, "lines"); 266 for (Map<String, Object> line : result.getLines()) 267 { 268 XMLUtils.startElement(handler, "line"); 269 for (Map.Entry<String, Object> entry : line.entrySet()) 270 { 271 if (entry.getValue() instanceof I18nizableText) 272 { 273 ((I18nizableText) entry.getValue()).toSAX(handler, entry.getKey()); 274 } 275 else 276 { 277 XMLUtils.createElement(handler, entry.getKey(), entry.getValue().toString()); 278 } 279 } 280 XMLUtils.endElement(handler, "line"); 281 } 282 283 284 285 XMLUtils.endElement(handler, "lines"); 286 287 XMLUtils.endElement(handler, "analysis"); 288 } 289 290 XMLUtils.endElement(handler, "program"); 291 } 292}