001/* 002 * Copyright 2018 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.rncp; 017 018import java.io.IOException; 019import java.io.InputStream; 020import java.io.OutputStream; 021import java.net.MalformedURLException; 022import java.util.ArrayList; 023import java.util.Collection; 024import java.util.List; 025import java.util.Map; 026 027import org.apache.avalon.framework.activity.Initializable; 028import org.apache.avalon.framework.component.Component; 029import org.apache.avalon.framework.configuration.ConfigurationException; 030import org.apache.avalon.framework.service.ServiceException; 031import org.apache.avalon.framework.service.ServiceManager; 032import org.apache.avalon.framework.service.Serviceable; 033import org.apache.excalibur.source.Source; 034import org.apache.excalibur.source.SourceResolver; 035import org.apache.excalibur.source.TraversableSource; 036import org.docx4j.openpackaging.exceptions.Docx4JException; 037import org.docx4j.openpackaging.packages.WordprocessingMLPackage; 038import org.docx4j.openpackaging.parts.DocPropsCustomPart; 039import org.xml.sax.SAXException; 040 041import org.ametys.core.util.URIUtils; 042import org.ametys.runtime.config.Config; 043import org.ametys.runtime.plugin.component.AbstractLogEnabled; 044 045import com.google.common.collect.ImmutableMap; 046 047/** 048 * Helper for RNCP models. 049 */ 050public class RNCPModelHelper extends AbstractLogEnabled implements Component, Serviceable, Initializable 051{ 052 /** The component role */ 053 public static final String ROLE = RNCPModelHelper.class.getName(); 054 055 private static final String RNCP_DIR = "context://WEB-INF/param/rncp"; 056 057 /** The source resolver */ 058 protected SourceResolver _srcResolver; 059 060 /** URL to update DOCX properties */ 061 private String _baseURL; 062 063 @Override 064 public void initialize() throws Exception 065 { 066 _baseURL = Config.getInstance().getValue("cms.url") + "/_odf/request/get-metadata-value.xml?contentId=#{CONTENTID}&metadata="; 067 } 068 069 @Override 070 public void service(ServiceManager smanager) throws ServiceException 071 { 072 _srcResolver = (SourceResolver) smanager.lookup(SourceResolver.ROLE); 073 } 074 075 /** 076 * Get the list of RNCP models. 077 * @return A JSON list with id and label of each available RNCP model 078 * @throws ConfigurationException if an error occurs 079 * @throws SAXException if an error occurs 080 * @throws IOException if an error occurs 081 */ 082 public List<Map<String, Object>> getModels() throws ConfigurationException, SAXException, IOException 083 { 084 List<Map<String, Object>> models = new ArrayList<>(); 085 086 TraversableSource rncpDir = (TraversableSource) _srcResolver.resolveURI(RNCP_DIR); 087 if (rncpDir.exists() && rncpDir.isCollection()) 088 { 089 for (TraversableSource file : (Collection<TraversableSource>) rncpDir.getChildren()) 090 { 091 String fileName = file.getName(); 092 if (!file.isCollection() && fileName.endsWith(".docx")) 093 { 094 models.add(ImmutableMap.of("id", fileName, "label", fileName)); 095 } 096 } 097 } 098 else 099 { 100 getLogger().warn("There is no directory '{}'.", RNCP_DIR); 101 } 102 103 return models; 104 } 105 106 /** 107 * Update the RNCP model with the good properties. 108 * @param modelId The model ID, shouldn't be null 109 * @param programId The mention ID 110 * @param subProgramId The subprogram ID 111 * @param out The {@link OutputStream} 112 * @throws MalformedURLException if an error occurs 113 * @throws IOException if an error occurs 114 */ 115 public void updateAbstractProgramRNCPSheet(String modelId, String programId, String subProgramId, OutputStream out) throws MalformedURLException, IOException 116 { 117 TraversableSource rncpDir = (TraversableSource) _srcResolver.resolveURI(RNCP_DIR); 118 Source childSrc = rncpDir.getChild(modelId); 119 if (!childSrc.exists()) 120 { 121 throw new IllegalArgumentException("The model ID is not valid."); 122 } 123 try (InputStream is = childSrc.getInputStream()) 124 { 125 WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(is); 126 127 DocPropsCustomPart docPropsCustomPart = wordMLPackage.getDocPropsCustomPart(); 128 docPropsCustomPart.setProperty("ParcoursURL", _baseURL.replace("#{CONTENTID}", URIUtils.encodeParameter(subProgramId))); 129 docPropsCustomPart.setProperty("MentionURL", _baseURL.replace("#{CONTENTID}", URIUtils.encodeParameter(programId))); 130 131 wordMLPackage.save(out); 132 } 133 catch (Docx4JException e) 134 { 135 throw new IOException("Error while modifying the document '" + modelId + "'.", e); 136 } 137 } 138} 139 140