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: 2.4.2
Show newest version
/*
 * *##% 
 * EUGene :: Maven plugin
 * Copyright (C) 2006 - 2009 CodeLutin
 *
 * 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
 * .
 * ##%*
 */
package org.nuiton.eugene.plugin.writer;

import org.nuiton.eugene.models.Model;
import org.nuiton.eugene.models.object.ObjectModel;
import org.nuiton.eugene.models.state.StateModel;
import org.nuiton.eugene.writer.ChainedFileWriterConfiguration;
import org.nuiton.plugin.PluginHelper;
import org.nuiton.plugin.PluginIOContext;
import org.nuiton.util.FasterCachedResourceResolver;
import org.nuiton.util.FileUtil;
import org.nuiton.util.Resource;
import org.nuiton.util.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;

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

    public static final String PROP_RESOLVER = "resolver";
    //    public static final String PROP_EXTRACTED_PACKAGES = "extractedPackages";
    public static final String PROP_FULL_PACKAGE_PATH = "fullPackagePath";

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

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

//    /**
//     * Get style sheet.
//     *
//     * @param modelType model type used
//     * @param model the model file used to determine the stylesheet to use
//     * @return the stylesheet name
//     */
//    protected abstract String getStyleSheet(String modelType, File model);

//    /**
//     * Get extension.
//     *
//     * @return the extension
//     */
//    protected abstract String getExtension();

    @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 outputDir, File inputDirectory, String includePattern) throws IOException {
        long t0 = System.nanoTime();

        boolean overwrite = configuration.isOverwrite();
        try {
            getLog().info("Processing XSL tranformation on " + inputDirectory + " for " + includePattern);

            getLog().info(" with fullPackagePath   : " + getFullPackagePath());
//            getLog().info(" with extractedPackages : " + getExtractedPackages());
//            getLog().info(" with acceptedXmiTypes  : " + getFullPackagePath());
            getLog().info(" with resolver          : " + getResolver());

            // recuperation des fichiers a traiter
            List files = PluginHelper.getIncludedFiles(inputDirectory, new String[]{includePattern}, null);

            // lancement des traitements xsl sur les fichiers trouvés
            // dans le repertoire
            actionXsl(configuration, outputDir, inputDirectory, files, overwrite);
        } finally {
            getLog().info("xsl done in " + PluginHelper.convertTime(System.nanoTime() - t0));
        }

        getLog().info("Copy resources files");

        PluginIOContext ioContext = new PluginIOContext();
        ioContext.setInput(inputDirectory);
        ioContext.setOutput(outputDir);
//            String[] excludes = getSuffixPattern("**/*");
        PluginHelper.copyFiles(ioContext, null, new String[]{includePattern}, overwrite);
    }

    protected void actionXsl(ChainedFileWriterConfiguration configuration, File outputDir, File dir, List files, boolean overwrite) throws IOException {

        for (File file : files) {
            try {
                if (getLog().isDebugEnabled()) {
                    getLog().debug("treate file : " + file);
                }
                // Prepare resolver, stylesheet
                URIResolver fileResolver = getUriResolver(configuration, file);
                String styleSheet = getStyleSheet(configuration.getModelType(), file);
                URL xsl = Resource.getURL(styleSheet);

                //TC-20090820 : using recursive for xmi
//                File result = new File(destDirModel, FileUtil.basename(file,
//                        acceptedSuffixes).concat(".").concat(getExtension()));

                String extension = "." + FileUtil.extension(file);
                String filename = FileUtil.basename(file, extension).concat(".").concat(configuration.getModelType());
//                String filename = FileUtil.basename(file, extension).concat(".").concat(getExtension());
                String relatifPath = file.getParentFile().getAbsolutePath().substring(dir.getAbsolutePath().length());
                File dstDir = outputDir;
                if (!relatifPath.isEmpty()) {
                    dstDir = new File(dstDir, relatifPath);
                    if (!dstDir.exists()) {
                        boolean b = dstDir.mkdirs();
                        if (!b) {
                            throw new IOException("could not create directory " + dstDir);
                        }
                    }
                }
                File result = new File(dstDir, filename);
                if (!overwrite && file.lastModified() < result.lastModified()) {
                    getLog().info("file up-to-date : " + result);
                    continue;
                }
                if (getLog().isDebugEnabled()) {
                    getLog().debug("generate " + result);
                }

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

                transformer.setParameter(PROP_FULL_PACKAGE_PATH, getFullPackagePath());
                //transformer.setParameter("extraPackages", getExtractedPackages());

                transformer.setURIResolver(fileResolver);
                transformer.transform(new StreamSource(file), new StreamResult(
                        new FileOutputStream(result)));

            } 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 = null;

        public XmiVersionHandler() {
            super();
        }

        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");
                getLog().debug("XMI version found : " + version);
            }

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

        }
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy