001/*
002 *  Copyright 2024 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.cdmfr;
017
018import java.io.IOException;
019import java.io.InputStream;
020import java.util.Set;
021import java.util.stream.Stream;
022
023import org.apache.avalon.framework.activity.Initializable;
024import org.apache.avalon.framework.component.Component;
025import org.apache.avalon.framework.context.Context;
026import org.apache.avalon.framework.context.ContextException;
027import org.apache.avalon.framework.context.Contextualizable;
028import org.apache.avalon.framework.service.ServiceException;
029import org.apache.avalon.framework.service.ServiceManager;
030import org.apache.avalon.framework.service.Serviceable;
031import org.apache.cocoon.components.ContextHelper;
032import org.apache.excalibur.source.Source;
033import org.apache.excalibur.source.SourceResolver;
034
035import org.ametys.odf.ODFHelper;
036import org.ametys.odf.program.Program;
037import org.ametys.runtime.config.Config;
038import org.ametys.runtime.plugin.component.AbstractLogEnabled;
039
040/**
041 * Processor to process CDM-fr files.
042 *  - Filter programs if need
043 *  - Iterate on programs
044 *  - Generate the CDM-fr file
045 *  - Process on the CDM-fr file
046 */
047public abstract class AbstractCDMfrProcessor extends AbstractLogEnabled implements Component, Serviceable, Initializable, Contextualizable
048{
049    /** The source resolver */
050    protected SourceResolver _sourceResolver;
051
052    /** The ODF helper */
053    protected ODFHelper _odfHelper;
054    
055    /** the Avalon context */
056    protected Context _context;
057    
058    private boolean _isActive;
059    
060    public void service(ServiceManager manager) throws ServiceException
061    {
062        _sourceResolver = (SourceResolver) manager.lookup(SourceResolver.ROLE);
063        _odfHelper = (ODFHelper) manager.lookup(ODFHelper.ROLE);
064    }
065    
066    public void initialize() throws Exception
067    {
068        _isActive = Config.getInstance().getValue(getConfigActiveParam());
069    }
070    
071    public void contextualize(Context context) throws ContextException
072    {
073        _context = context;
074    }
075    
076    /**
077     * Get the configuration parameter name to determine if the process is active.
078     * @return The configuration parameter name
079     */
080    protected abstract String getConfigActiveParam();
081    
082    /**
083     * <code>true</code> if the process is active
084     * @return <code>true</code> if the process is active
085     */
086    public boolean isActive()
087    {
088        return _isActive;
089    }
090    
091    /**
092     * Process the CDM-fr of the given programs.
093     * @param programs The programs to process
094     */
095    public void processPrograms(Set<Program> programs)
096    {
097        // Check if the process is active
098        if (isActive())
099        {
100            // Filter programs if needed and iterate on it
101            filterPrograms(programs.stream()).forEach(
102                program ->
103                {
104                    // Get the CDM-fr content and process the program
105                    Source cdmfrSource = null;
106                    try
107                    {
108                        cdmfrSource = _getCDMfrContent(program);
109                        try (InputStream is = cdmfrSource != null ? cdmfrSource.getInputStream() : null)
110                        {
111                            processProgram(program, is);
112                        }
113                    }
114                    catch (IOException e)
115                    {
116                        getLogger().error(getErrorMessage(), e);
117                    }
118                    finally
119                    {
120                        if (cdmfrSource != null)
121                        {
122                            _sourceResolver.release(cdmfrSource);
123                        }
124                    }
125                }
126            );
127        }
128    }
129    
130    /**
131     * Process the program and its CDM-fr input stream.
132     * @param program The program
133     * @param cdmfrContent The CDM-fr content as {@link InputStream}
134     * @throws IOException if an exception occurs
135     */
136    protected abstract void processProgram(Program program, InputStream cdmfrContent) throws IOException;
137    
138    /**
139     * Get the error message if process fails.
140     * @return the error message
141     */
142    protected abstract String getErrorMessage();
143    
144    /**
145     * Filter programs if needed.
146     * @param programs The programs to filter
147     * @return The filtered programs
148     */
149    protected Stream<Program> filterPrograms(Stream<Program> programs)
150    {
151        // Default implementation does not filter anything
152        return programs;
153    }
154    
155    /**
156     * Get the CDM-fr of the current program.
157     * @param program The program to export as CDM-fr
158     * @return The {@link InputStream} with the CDM-fr content
159     * @throws IOException if an exception occurs
160     */
161    protected Source _getCDMfrContent(Program program) throws IOException
162    {
163        ContextHelper.getRequest(_context).setAttribute(ExportToCDMfrGenerator.CHECK_RIGHTS_ATTRIBUTE_NAME, false);
164        
165        // Build the URI to export program as CDM-fr
166        StringBuilder sb = new StringBuilder("cocoon://_plugins/odf/export-cdmfr.xml");
167        sb.append("?id=").append(program.getId());
168        sb.append("&").append(ExportCDMfrHelper.REQUEST_PARAM_VALID_LABEL).append("=true");
169        if (isCDMfrForAmetys())
170        {
171            sb.append("&").append(ExportCDMfrHelper.REQUEST_PARAM_EXPORT_FOR_AMETYS).append("=true");
172        }
173        
174        // Generate CDM-fr file
175        return _sourceResolver.resolveURI(sb.toString());
176    }
177    
178    /**
179     * <code>true</code> to generate CDM-fr for another Ametys, <code>false</code> otherwise.
180     * @return <code>true</code> to generate CDM-fr for another Ametys instance
181     */
182    protected abstract boolean isCDMfrForAmetys();
183}