All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.eugene.plugin.writer.XmiChainedFileWriter Maven / Gradle / Ivy

There is a newer version: 3.0-beta-2
Show newest version
/*
 * #%L
 * EUGene :: Maven plugin
 * %%
 * Copyright (C) 2006 - 2017 Code Lutin, Ultreia.io
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

package org.nuiton.eugene.plugin.writer;

import io.ultreia.java4all.lang.ClassLoaders;
import org.nuiton.eugene.GeneratorUtil;
import org.nuiton.eugene.models.object.ObjectModel;
import org.nuiton.eugene.models.state.StateModel;
import org.nuiton.eugene.writer.ChainedFileWriterConfiguration;
import org.nuiton.eugene.writer.WriterReport;
import org.nuiton.plugin.PluginHelper;
import org.nuiton.eugene.FasterCachedResourceResolver;
import org.nuiton.eugene.ResourceResolver;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.util.List;
import java.util.Map;

/**
 * Implentation pour les writer to type xmi (qui transforme du xmi via xsl
 * vers du model).
 *
 * @author tchemit
 * @plexus.component role="org.nuiton.eugene.writer.ChainedFileWriter" role-hint="xmi"
 * @since 2.0.0
 */
public class XmiChainedFileWriter extends BaseChainedFileWriter {

    public static final String PROP_RESOLVER = "resolver";

    public static final String PROP_FULL_PACKAGE_PATH = "fullPackagePath";

    public static final String PROP_EXTRACTED_PACKAGES = "extraPackages";

    public XmiChainedFileWriter() {
        super(PROP_RESOLVER,
              "resolver",
              PROP_FULL_PACKAGE_PATH,
              "fullPackagePath",
              PROP_EXTRACTED_PACKAGES,
              "extraPackages"
        );
    }

    @Override
    public boolean acceptModel(String modelType) {
        // supported by objectModel and stateModel
        return acceptObjectModelOrStateModel(modelType);
    }

    @Override
    public String getInputProtocol() {
        return "xmi";
    }

    @Override
    public String getOutputProtocol(String modelType) {
        // next writer : write from model files
        return "model";
    }

    @Override
    public boolean acceptInclude(String include) {
        return include.startsWith("xmi:") || include.endsWith(".xmi") || include.endsWith(".uml");
    }

    @Override
    public String getDefaultIncludes() {
        return "**/*.xmi";
    }

    @Override
    public String getDefaultInputDirectory() {
        return "src/main/xmi";
    }

    @Override
    public String getDefaultOutputDirectory() {
        return "models";
    }

    @Override
    public String getDefaultTestInputDirectory() {
        return "src/test/xmi";
    }

    @Override
    public String getDefaultTestOutputDirectory() {
        return "test-models";
    }

    protected TransformerFactory transformerFactory;

    protected TransformerFactory getTransformerFactory() {
        if (transformerFactory == null) {
            transformerFactory = TransformerFactory.newInstance();
        }
        return transformerFactory;
    }

    public String getFullPackagePath() {
        return getProperty(PROP_FULL_PACKAGE_PATH, String.class);
    }

    public String getExtractedPackages() {
        return getProperty(PROP_EXTRACTED_PACKAGES, String.class);
    }

    public String getResolver() {
        return getProperty(PROP_RESOLVER, String.class);
    }

    @Override
    public void generate(ChainedFileWriterConfiguration configuration,
                         File outputDirectory,
                         Map> filesByRoot,
                         Map> resourcesByFile) throws IOException {

        if (configuration.isVerbose()) {
            getLog().info(" with fullPackagePath   : " + getFullPackagePath());
            getLog().info(" with resolver          : " + getResolver());
        }

        for (Map.Entry> entry : filesByRoot.entrySet()) {
            File inputDirectory = entry.getKey();
            List files = entry.getValue();

            if (configuration.isVerbose()) {
                getLog().info("Processing XSL tranformation on " +
                              inputDirectory + " for " + files.size() + " file(s).");
            }

            for (File file : files) {

                // lancement des traitements xsl sur les fichiers trouvés dans le repertoire
                actionXsl(configuration,
                          outputDirectory,
                          inputDirectory,
                          file
                );

//                if (!reacted) {
//
//                    // file was not treated, nothing else to do
//                    continue;
//                }

                // copy resources associated with the file
                copyResources(configuration,
                              outputDirectory,
                              inputDirectory,
                              file,
                              resourcesByFile
                );

            }
        }
    }

    protected boolean actionXsl(ChainedFileWriterConfiguration configuration,
                                File outputDirectory,
                                File inputDirectory,
                                File file) throws IOException {

        try {
            getLog().debug("treat file : " + file);
            // Prepare resolver, stylesheet
            URIResolver fileResolver = getUriResolver(configuration, file);
            String styleSheet = getStyleSheet(configuration.getModelType(), file);
            URL xsl = ClassLoaders.getURL(styleSheet);

            String newExtension = configuration.getModelType();

            // get the mirror file in the ouput root directory
            File mirrorFile = GeneratorUtil.getRelativeFile(inputDirectory, outputDirectory, file);

            // change the extension name to the modeltype
            File result = GeneratorUtil.changeExtension(mirrorFile, newExtension);

            if (!configuration.isOverwrite() &&
                file.lastModified() < result.lastModified()) {

                if (configuration.isVerbose()) {
                    getLog().info(String.format("Will not generate %s (up-to-date).", result));
                }
                return false;
            }

            PluginHelper.createDirectoryIfNecessary(result.getParentFile());
            WriterReport writerReport = getWriterReport();
            if (writerReport != null) {
                writerReport.addFile(getClass().getName(), result, false);
            }

            // Create the xsl transformer and set parameters
            Transformer transformer = getTransformerFactory().
                    newTransformer(new StreamSource(xsl.openStream()));

            transformer.setParameter(PROP_FULL_PACKAGE_PATH, getFullPackagePath());
            transformer.setParameter(PROP_EXTRACTED_PACKAGES, getExtractedPackages());

            transformer.setURIResolver(fileResolver);
            try (FileOutputStream output = new FileOutputStream(result)) {
                transformer.transform(new StreamSource(file), new StreamResult(output));
            }
            return true;
        } catch (IOException e) {
            throw e;
        } catch (Exception e) {
            throw new IOException(e.getMessage(), e);
        }
    }

    protected URIResolver getUriResolver(ChainedFileWriterConfiguration configuration, File model) {
        URIResolver result = null;

        try {
            ClassLoader loader = configuration.getClassLoader();
            Class clazz = Class.forName(getResolver(), true, loader);

            // Try to set the base using the constructor
            try {
                // Look for a constructor with a String parameter (base)
                Constructor withBaseConstructor = clazz.getConstructor(String.class);
                // Set the xmi folder as the base
                String base = model.getParentFile().getAbsolutePath();
                // Instantiate
                result = (URIResolver) withBaseConstructor.newInstance(base);
            } catch (Exception eee) {
                getLog().warn("Unable to instantiate resolver with String parameter", eee);
            }

            // If resolver is still not created, create it using the default
            // constructor
            if (result == null) {
                result = (URIResolver) clazz.newInstance();
            }

            if (result instanceof ResourceResolver) {
                ((ResourceResolver) result).setVerbose(
                        configuration.isVerbose());
                ((ResourceResolver) result).setCl(loader);
                if (result instanceof FasterCachedResourceResolver) {
                    boolean offline = configuration.isOffline();
                    getLog().debug("using offline mode  ? : " + offline);
                    ((FasterCachedResourceResolver) result).setOffline(offline);
                }
            }

        } catch (Exception eee) {
            getLog().warn("Unable to instantiate resolver using the default constructor", eee);
        }

        return result;
    }

    protected String getStyleSheet(String modelType, File model) {
        if (ObjectModel.NAME.equals(modelType)) {
            String version = getXmiVersion(model);
            String styleSheet = null;
            if (version.startsWith("1.")) {
                styleSheet = "xmi1.2ToObjectModel.xsl";
            } else if (version.startsWith("2.")) {
                styleSheet = "xmi2.1ToObjectModel.xsl";
            } else {
                getLog().error("Unsupported xmi version [" + version + "]");
            }
            return styleSheet;
        }
        if (StateModel.NAME.equals(modelType)) {
            //TODO when StateModel will be supported in 2.1, compute the version to resolve the correct stylesheet
            return "xmi1.2ToStateModel.xsl";
        }

        throw new IllegalStateException("unsupported modelType [" + modelType + "]");
    }

    /**
     * Try to find xmi version on a file.
     *
     * @param xmiFile file to inspect
     * @return version or null if version can't have been found
     */
    protected String getXmiVersion(File xmiFile) {
        String version = null;

        SAXParserFactory factory = SAXParserFactory.newInstance();

        try {
            SAXParser parser = factory.newSAXParser();

            XmiVersionHandler handler = new XmiVersionHandler();
            parser.parse(xmiFile, handler);

            version = handler.getVersion();
        } catch (ParserConfigurationException e) {
            getLog().debug("Can't parse file as xmi", e);
        } catch (SAXException e) {
            getLog().debug("Can't parse file as xmi", e);
        } catch (IOException e) {
            getLog().debug("Can't parse file as xmi", e);
        }

        return version;
    }

    /** Sax handler to find xmi version into xmi document. */
    protected class XmiVersionHandler extends DefaultHandler {

        protected String version;

        public XmiVersionHandler() {
        }

        public String getVersion() {
            return version;
        }

        @Override
        public void startElement(String uri,
                                 String localName,
                                 String qName,
                                 Attributes attributes) throws SAXException {

            if (qName.equals("XMI")) {
                version = attributes.getValue("xmi.version");
                if (getLog().isDebugEnabled()) {
                    getLog().debug("XMI version found : " + version);
                }
            }

            if (version == null) {
                version = attributes.getValue("xmi:version");
                if (getLog().isDebugEnabled()) {
                    getLog().debug("XMI version found : " + version);
                }
            }

        }
    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy