/* UtilLib - Copyright (c) 2014 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 net.mapeadores.util.xml.json;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import net.mapeadores.util.exceptions.InternalResourceException;
import net.mapeadores.util.exceptions.NestedTransformerException;
import net.mapeadores.util.io.IOUtils;


/**
 *
 * @author Vincent Calame
 */
public final class XmlToJson {

    public final static String JSONSTRUCTURE_NAME = "jsonstructure";
    public final static String JSONML_NAME = "jsonml";
    private final static Templates jsonstructureTemplates;
    private final static Templates jsonmlTemplates;
    private final static String JSONSTRUCTURE_CONF;
    private final static String JSONML_CONF;
    private final static URIResolver URIRESOLVER;

    static {
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        try {
            InputStream jsonstructureStream = XmlToJson.class.getResourceAsStream("jsonstructure.xsl");
            jsonstructureTemplates = transformerFactory.newTemplates(new StreamSource(jsonstructureStream));
            jsonstructureStream.close();
            InputStream jsonmlStream = XmlToJson.class.getResourceAsStream("jsonml.xsl");
            jsonmlTemplates = transformerFactory.newTemplates(new StreamSource(jsonmlStream));
            jsonmlStream.close();
        } catch (TransformerException te) {
            throw new NestedTransformerException(te);
        } catch (IOException ioe) {
            throw new InternalResourceException(ioe);
        }
        try {
            InputStream jsonstructureConf = XmlToJson.class.getResourceAsStream("conf_jsonstructure.xml");
            JSONSTRUCTURE_CONF = IOUtils.toString(jsonstructureConf, "UTF-8");
            jsonstructureConf.close();
            InputStream jsonmlConf = XmlToJson.class.getResourceAsStream("conf_jsonml.xml");
            JSONML_CONF = IOUtils.toString(jsonmlConf, "UTF-8");
            jsonmlConf.close();
        } catch (IOException ioe) {
            throw new InternalResourceException(ioe);
        }
        URIRESOLVER = new InternalURIResolver();
    }

    private XmlToJson() {
    }

    public static Transformer newTransformer(String name) {
        try {
            Transformer transformer;
            if (name.equals(JSONSTRUCTURE_NAME)) {
                transformer = jsonstructureTemplates.newTransformer();
            } else if (name.equals(JSONML_NAME)) {
                transformer = jsonmlTemplates.newTransformer();
            } else {
                return null;
            }
            transformer.setURIResolver(URIRESOLVER);
            return transformer;
        } catch (TransformerConfigurationException tce) {
            throw new NestedTransformerException(tce);
        }
    }

    public static String transform(String name, String xmlString) throws TransformerException {
        Transformer transformer = newTransformer(name);
        if (transformer == null) {
            throw new IllegalArgumentException("Unknown name: " + name);
        }
        Source source = new StreamSource(new StringReader(xmlString));
        StringWriter writer = new StringWriter();
        transformer.transform(source, new StreamResult(writer));
        return writer.toString();
    }


    private static class InternalURIResolver implements URIResolver {

        private InternalURIResolver() {
        }

        @Override
        public Source resolve(String href, String base) throws TransformerException {
            if (href.equals("conf_jsonstructure.xml")) {
                return new StreamSource(new StringReader(JSONSTRUCTURE_CONF));
            }
            if (href.equals("conf_jsonml.xml")) {
                return new StreamSource(new StringReader(JSONML_CONF));
            }
            return null;
        }

    }

}
