/* BdfServer - Copyright (c) 2013-2022 Vincent Calame - Exemole
 * Logiciel libre donné sous triple licence :
 * 1) selon les termes de la CeCILL V2
 * 2) selon les termes de l’EUPL V.1.1
 * 3) selon les termes de la GNU GPLv3
 * Voir le fichier licences.txt
 */


package fr.exemole.bdfserver.tools.exportation.transformation;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.api.configuration.PathConfiguration;
import fr.exemole.bdfserver.api.exportation.transformation.SimpleTemplateFactory;
import java.io.StringWriter;
import java.util.Map;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.stream.StreamResult;
import net.fichotheque.exportation.transformation.SimpleTemplate;
import net.fichotheque.extraction.def.ExtractionDef;
import net.mapeadores.util.attr.Attributes;
import net.mapeadores.util.exceptions.NestedTransformerException;
import net.mapeadores.util.mimetype.MimeTypeUtils;


/**
 *
 * @author Vincent Calame
 */
public class XsltSimpleTemplateFactory implements SimpleTemplateFactory {

    private final BdfServer bdfServer;
    private final PathConfiguration pathConfiguration;
    private final Attributes attributes;
    private final ExtractionDef customExtractionDef;
    private final Templates templates;

    public XsltSimpleTemplateFactory(BdfServer bdfServer, PathConfiguration pathConfiguration, Attributes attributes, ExtractionDef customExtractionDef, Templates templates) {
        this.bdfServer = bdfServer;
        this.pathConfiguration = pathConfiguration;
        this.attributes = attributes;
        this.customExtractionDef = customExtractionDef;
        this.templates = templates;
    }

    @Override
    public SimpleTemplate newInstance() {
        Transformer transformer = BdfTransformationUtils.newTransformer(bdfServer, pathConfiguration, templates);
        return new XsltSimpleTemplate(attributes, customExtractionDef, transformer);
    }


    private static class XsltSimpleTemplate implements SimpleTemplate {

        private final Attributes attributes;
        private final ExtractionDef customExtractionDef;
        private final Transformer transformer;
        private final String mimeType;

        public XsltSimpleTemplate(Attributes attributes, ExtractionDef customExtractionDef, Transformer transformer) {
            this.attributes = attributes;
            this.customExtractionDef = customExtractionDef;
            this.transformer = transformer;
            String method = transformer.getOutputProperty("method");
            if ((method == null) || (method.equals("xml"))) {
                this.mimeType = MimeTypeUtils.XML;
            } else if (method.equals("html")) {
                this.mimeType = MimeTypeUtils.HTML;
            } else {
                this.mimeType = MimeTypeUtils.PLAIN;
            }
        }

        @Override
        public Attributes getAttributes() {
            return attributes;
        }

        @Override
        public ExtractionDef getCustomExtractionDef() {
            return customExtractionDef;
        }

        @Override
        public String getMimeType() {
            return mimeType;
        }

        @Override
        public String getCharset() {
            String encoding = transformer.getOutputProperty("encoding");
            if (encoding == null) {
                return "UTF-8";
            }
            return encoding;
        }

        @Override
        public String transform(Source extractionSource, Map<String, Object> paramMap) {
            StringWriter stringWriter = new StringWriter();
            if (paramMap != null) {
                for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
                    transformer.setParameter(entry.getKey(), entry.getValue());
                }
            }
            try {
                transformer.transform(extractionSource, new StreamResult(stringWriter));
            } catch (TransformerException te) {
                throw new NestedTransformerException(te);
            }
            return stringWriter.toString();
        }

    }

}
