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.URLEncoder;
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}", URLEncoder.encodeParameter(subProgramId)));
129            docPropsCustomPart.setProperty("MentionURL", _baseURL.replace("#{CONTENTID}", URLEncoder.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