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.plugins.extraction.execution.pipeline;
017
018import java.io.IOException;
019import java.io.OutputStream;
020import java.nio.file.Files;
021import java.nio.file.Path;
022import java.util.Optional;
023import java.util.Properties;
024
025import javax.xml.transform.OutputKeys;
026import javax.xml.transform.TransformerFactory;
027import javax.xml.transform.sax.SAXTransformerFactory;
028import javax.xml.transform.sax.TransformerHandler;
029import javax.xml.transform.stream.StreamResult;
030
031import org.apache.xml.serializer.OutputPropertiesFactory;
032
033import org.ametys.core.util.LambdaUtils;
034
035/**
036 * Convenient method for {@link Pipeline} API implementations
037 */
038public final class Pipelines
039{
040    private static final Properties __OUTPUT_FORMAT_PROPERTIES = new Properties();
041    static
042    {
043        __OUTPUT_FORMAT_PROPERTIES.put(OutputKeys.ENCODING, "UTF-8");
044        __OUTPUT_FORMAT_PROPERTIES.put(OutputKeys.METHOD, "xml");
045        __OUTPUT_FORMAT_PROPERTIES.put(OutputKeys.INDENT, "yes");
046        __OUTPUT_FORMAT_PROPERTIES.put(OutputPropertiesFactory.S_KEY_INDENT_AMOUNT, "4");
047    }
048    
049    private static SAXTransformerFactory __transformerFactory;
050    
051    private Pipelines()
052    {
053        // Nothing
054    }
055    
056    /**
057     * Gets a {@link SAXTransformerFactory}
058     * @return a {@link SAXTransformerFactory}
059     */
060    public static SAXTransformerFactory getSaxTransformerFactory()
061    {
062        if (__transformerFactory == null)
063        {
064            __transformerFactory = (SAXTransformerFactory) TransformerFactory.newInstance();
065        }
066        return __transformerFactory;
067    }
068    
069    /**
070     * Sets standard output properties to the transformer of the given handler, such as encoding and indentation. 
071     * @param transformerHandler The transformer handler
072     */
073    public static void setStandardOutputProperties(TransformerHandler transformerHandler)
074    {
075        transformerHandler.getTransformer().setOutputProperties(__OUTPUT_FORMAT_PROPERTIES);
076    }
077    
078    /**
079     * Gets the output stream of the given file (which will be created if it does not exist).
080     * @param outputFile The output file. Will be created if needed.
081     * @return the output stream
082     * @throws IOException if an I/O error occured
083     */
084    public static OutputStream getOutputStream(Path outputFile) throws IOException
085    {
086        outputFile.getParent().toFile().mkdirs();
087        OutputStream resultOs = Files.newOutputStream(outputFile);
088        return resultOs;
089    }
090    
091    /**
092     * Sets the result of a transformer handler into an output stream.
093     * @param transformerHandler The transformer handler
094     * @param outputStream The output stream
095     * @return the stream result
096     * @throws IOException if an I/O error occured
097     */
098    public static StreamResult setResult(TransformerHandler transformerHandler, OutputStream outputStream) throws IOException
099    {
100        StreamResult streamResult = new StreamResult(outputStream);
101        transformerHandler.setResult(streamResult);
102        return streamResult;
103    }
104    
105    /**
106     * Close the given stream result
107     * @param result the stream result
108     */
109    public static void close(StreamResult result)
110    {
111        Optional.ofNullable(result)
112                .map(StreamResult::getOutputStream)
113                .ifPresent(LambdaUtils.wrapConsumer(OutputStream::close));
114    }
115}