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

org.nuiton.eugene.writer.DefaultChainedWriterEngine Maven / Gradle / Ivy

/*
 * #%L
 * EUGene :: EUGene Core
 * %%
 * Copyright (C) 2004 - 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.writer;

import com.google.common.base.Preconditions;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Default implementation of the {@link ChainedWriterEngine}.
 *
 * Created: 17 déc. 2009
 *
 * @author Tony Chemit - [email protected]
 * @plexus.component role="org.nuiton.eugene.writer.ChainedWriterEngine" role-hint="default"
 * @since 2.0.0
 */
public class DefaultChainedWriterEngine implements ChainedWriterEngine {

    /** Logger */
    private static final Log log = LogFactory.getLog(DefaultChainedWriterEngine.class);

    /** shared configuration */
    protected ChainedFileWriterConfiguration configuration;

    /** available writers corresponding to the given configuration */
    protected Set availableWriters;

    /** selected writers obtain while the register phase. */
    protected List selectedWriters;

    private FileGrabberFromDirectory fileGrabberFromDirectory;

    private FileGrabberFromClassPath fileGrabberFromClassPath;

    public ChainedFileWriterConfiguration getConfiguration() {
        return configuration;
    }

    @Override
    public List getSelectedWriters() {
        if (selectedWriters == null) {
            checkInit("getSelectedWriters");
            selectedWriters = new ArrayList<>();
        }
        return selectedWriters;
    }

    @Override
    public boolean containsWriter(String inputProtocol) {
        for (ChainedFileWriter w : getSelectedWriters()) {
            if (inputProtocol.equals(w.getInputProtocol())) {
                return true;
            }
        }
        return false;
    }

    @Override
    public Set getAvailableWriters() {
        if (availableWriters == null) {
            checkInit("getAvailableWriters");
            availableWriters = filterWriterForModelType(
                    getConfiguration().getWriters(),
                    getConfiguration().getModelType()
            );
        }
        return availableWriters;
    }

    @Override
    public void registerInclude(String include) {
        checkInit("registerInclude");

        List selectedWriters = getSelectedWriters();

        if (log.isDebugEnabled()) {
            log.debug(">>>>>>>>>>>>>>>>> [" + include + "]");
            log.debug("Will register include " + "[" + include + "]");
            log.debug("actual selected writers : " + selectedWriters);
        }
        ModelFileWriterEntryType selectedType = null;
        Matcher matcher = null;

        // obtain the good type of entry and the corresponding matcher

        for (ModelFileWriterEntryType type :
                ModelFileWriterEntryType.values()) {
            matcher = type.getMatcher(include);
            if (matcher != null) {
                // get a matcher
                selectedType = type;
                break;
            }
        }

        if (selectedType == null) {
            // no writer
            throw new IllegalArgumentException("could not find a writer for include pattern : " + include);
        }

        // obtain the writer
        ChainedFileWriter writer =
                selectedType.getWriter(this, include, matcher);

        // create the new entry

        ChainedFileWriterEntry writerEntry =
                selectedType.newEntry(this, include, matcher, writer);

        // register the new entry

        writer.addEntry(writerEntry);
        if (!selectedWriters.contains(writer)) {
            // register the writer as to be used
            if (log.isDebugEnabled()) {
                log.debug("[" + include + "] Associated with writer " + writer);
            }
            selectedWriters.add(writer);
        }

        ChainedFileWriterConfiguration configuration = getConfiguration();

        String modelType = configuration.getModelType();

        String outpoutProtocol = writer.getOutputProtocol(modelType);

        if (outpoutProtocol == null) {
            // nothing more to do
            if (log.isDebugEnabled()) {
                log.debug("<<<<<<<<<<<<<<<<< [" + include + "]");
            }
            return;
        }

        // the writer need the includes of another writer

        if (log.isDebugEnabled()) {
            log.debug("[" + include + "]" + " writer " +
                      writer.getClass().getSimpleName() +
                      " require a next writer of protocol " + outpoutProtocol);
        }

        ChainedFileWriter nextWriter =
                ((AbstractChainedFileWriter) writer).getNextWriter();
        if (nextWriter == null) {
            // the next writer was not initialize, just have to add new entry

            nextWriter = getWriterForInputProtocol(
                    getAvailableWriters(),
                    outpoutProtocol,
                    modelType
            );

            if (nextWriter == null) {
                throw new IllegalArgumentException(
                        "could not find a writer for protocole " +
                        outpoutProtocol + " on model " + modelType);
            }
            // chain writer
            ((AbstractChainedFileWriter) writer).setNextWriter(nextWriter);
        }

        // build the next include to do

        String basedirpath = configuration.getBasedir().getAbsolutePath();

        String outputpath = writer.getOutputDirectory(
                configuration.getOutputDirectory(),
                configuration.isTestPhase()).getAbsolutePath();

        String path = outputpath.substring(basedirpath.length() + 1);

        String newInclude = outpoutProtocol + ":" + path + ":" +
                            nextWriter.getDefaultIncludes();

        registerInclude(newInclude);

        if (log.isDebugEnabled()) {
            log.debug("<<<<<<<<<<<<<<<<< [" + include + "]");
        }
    }

    @Override
    public void clear() {

        if (selectedWriters != null) {
            selectedWriters.clear();
            selectedWriters = null;
        }
        if (availableWriters != null) {
            for (ChainedFileWriter writer : availableWriters) {
                writer.clear();
            }
            availableWriters.clear();
            availableWriters = null;
        }
        configuration = null;

        fileGrabberFromDirectory = null;
        fileGrabberFromClassPath = null;

    }

    @Override
    public void init(ChainedFileWriterConfiguration configuration) {

        Preconditions.checkNotNull(configuration, "Configuration can not be null");

        this.configuration = configuration;
        fileGrabberFromDirectory = new FileGrabberFromDirectory(configuration);
        fileGrabberFromClassPath = new FileGrabberFromClassPath(configuration);

    }

    @Override
    public Set filterWriterForModelType(
            Map universe, String modelType) {
        Set result = new HashSet<>();
        for (ChainedFileWriter w : universe.values()) {
            if (w.acceptModel(modelType)) {
                if (log.isDebugEnabled()) {
                    log.debug("writer [" + w + "] accept model " + modelType);
                }
                result.add(w);
            }
        }
        return result;
    }

    @Override
    public ChainedFileWriter getWriterForInputProtocol(
            Set universe,
            String inputProtocol,
            String modelType) {
        for (ChainedFileWriter writer : universe) {
            if (inputProtocol.equals(writer.getInputProtocol(modelType))) {
                return writer;
            }
        }
        return null;
    }

    @Override
    public ChainedFileWriter getWriterForInclude(
            Set universe,
            String include,
            String modelType) {
        for (ChainedFileWriter w : universe) {
            if (w.acceptInclude(include)) {
                return w;
            }
        }
        return null;
    }

    @Override
    public ChainedFileWriterData getData(ChainedFileWriter writer) throws IOException {

        checkInit("getData");
        File outputDir = writer.getOutputDirectory(configuration.getOutputDirectory(), configuration.isTestPhase());

        if (!outputDir.exists()) {
            if (log.isDebugEnabled()) {
                log.debug("[" + writer.getInputProtocol() + "] Create output directory " + outputDir);
            }
            boolean b = outputDir.mkdirs();
            if (!b) {
                throw new IOException("Could not create directory " + outputDir);
            }
        }

        // split directory and classpath entries
        Map> directoryEntries = new HashMap<>();
        Map> classpathEntries = new HashMap<>();

        for (ChainedFileWriterEntry e : writer.getEntries()) {

            Map> currentMap;

            if (e.isUseClassPath()) {
                currentMap = classpathEntries;
            } else {
                currentMap = directoryEntries;
            }

            String input = e.getInputPath();
            Set includes = currentMap.get(input);
            if (includes == null) {
                currentMap.put(input, includes = new LinkedHashSet<>());
            }
            includes.add(e.getIncludePattern());

        }

        ChainedFileWriterData result = new ChainedFileWriterData();
        result.setFilesByRoot(new HashMap<>());
        result.setResourcesByFile(new HashMap<>());
        result.setOutputDirectory(outputDir);

        File extractDirectory = writer.getExtractDirectory(configuration.getExtractDirectory(),
                                                           configuration.isTestPhase());

        // search from directory files
        grabFiles(extractDirectory, fileGrabberFromDirectory, directoryEntries, result);

        // search class-path files
        grabFiles(extractDirectory, fileGrabberFromClassPath, classpathEntries, result);

        return result;

    }

    protected void grabFiles(File extractDirectory, FileGrabber grabber,
                             Map> entries,
                             ChainedFileWriterData result) throws IOException {

        for (Map.Entry> entry : entries.entrySet()) {

            String inputDirectory = entry.getKey();
            Set includePatterns = entry.getValue();
            grabber.addFilesToTreate(extractDirectory, inputDirectory, includePatterns, result);

        }

    }

    protected void checkInit(String method) throws IllegalStateException {
        if (configuration == null) {
            throw new IllegalStateException("Engine was not initialized! Can not access to " + method +
                                            " before the init method was invoked!");
        }
    }

    public enum ModelFileWriterEntryType {

        ONLY_PROTOCOL_PATTERN("^([a-zA-Z]+)$") {
            @Override
            public ChainedFileWriter getWriter(DefaultChainedWriterEngine engine,
                                               String include,
                                               Matcher matcher) {
                ChainedFileWriterConfiguration conf = engine.getConfiguration();
                Set universe = engine.getAvailableWriters();

                String protocol = matcher.group(1).toLowerCase();
                ChainedFileWriter writer = engine.getWriterForInputProtocol(
                        universe,
                        protocol,
                        conf.getModelType()
                );
                if (writer == null) {
                    throw new IllegalArgumentException(
                            "could not find the writer named '" + protocol + "', use one of " + universe);
                }
                if (log.isDebugEnabled()) {
                    log.debug("[" + include + "] " + "writer = (" + writer + ")");
                }
                return writer;
            }

            @Override
            public ChainedFileWriterEntry newEntry(
                    DefaultChainedWriterEngine engine,
                    String include,
                    Matcher matcher,
                    ChainedFileWriter writer) {
                ChainedFileWriterConfiguration conf = engine.getConfiguration();
                if (log.isDebugEnabled()) {
                    log.debug("[" + include + "] " + "detected pattern (" + name() + ")");
                }

                ChainedFileWriterEntry writerEntry = new ChainedFileWriterEntry(
                        new File(conf.getBasedir(),
                                 conf.isTestPhase() ?
                                 writer.getDefaultTestInputDirectory() :
                                 writer.getDefaultInputDirectory()
                        ).getAbsolutePath(),
                        writer.getDefaultIncludes()
                );
                return writerEntry;
            }
        },

        NO_PROTOCOL_PATTERN_WITH_CLASSPATH("^classpath:([^:]+):([^:]+)$") {
            @Override
            public ChainedFileWriter getWriter(DefaultChainedWriterEngine engine,
                                               String include,
                                               Matcher matcher) {
                ChainedFileWriterConfiguration conf = engine.getConfiguration();
                Set universe = engine.getAvailableWriters();

                String modelType = conf.getModelType();
                // with no protocol pattern
                // pattern is discover from the includes

                // discover the writer from the given pattern
                ChainedFileWriter writer = engine.getWriterForInclude(universe, include, modelType);
                if (writer == null) {
                    throw new IllegalArgumentException("could not find a writer for include " + include);
                }
                if (log.isDebugEnabled()) {
                    log.debug("[" + include + "] " + "writer = (" + writer + ")");
                }
                return writer;
            }

            @Override
            public ChainedFileWriterEntry newEntry(DefaultChainedWriterEngine engine,
                                                   String include,
                                                   Matcher matcher,
                                                   ChainedFileWriter writer) {

                // with no protocol pattern
                // pattern is discover from the includes
                if (log.isDebugEnabled()) {
                    log.debug("[" + include + "] " + "detected pattern (" + name() + ")");
                }

                String inputPath = matcher.group(1);
                String includes = matcher.group(2);

                ChainedFileWriterEntry writerEntry = new ChainedFileWriterEntry(inputPath, includes, true);
                return writerEntry;
            }
        },

        NO_PROTOCOL_PATTERN("^([^:]+):([^:]+)$") {
            @Override
            public ChainedFileWriter getWriter(DefaultChainedWriterEngine engine,
                                               String include,
                                               Matcher matcher) {
                ChainedFileWriterConfiguration conf = engine.getConfiguration();
                Set universe = engine.getAvailableWriters();

                String modelType = conf.getModelType();
                // with no protocol pattern
                // pattern is discover from the includes

                // discover the writer from the given pattern
                ChainedFileWriter writer = engine.getWriterForInclude(universe, include, modelType);
                if (writer == null) {
                    throw new IllegalArgumentException("could not find a writer for include " + include);
                }
                if (log.isDebugEnabled()) {
                    log.debug("[" + include + "] " + "writer = (" + writer + ")");
                }
                return writer;
            }

            @Override
            public ChainedFileWriterEntry newEntry(DefaultChainedWriterEngine engine,
                                                   String include,
                                                   Matcher matcher,
                                                   ChainedFileWriter writer) {
                ChainedFileWriterConfiguration conf = engine.getConfiguration();
                // with no protocol pattern
                // pattern is discover from the includes
                if (log.isDebugEnabled()) {
                    log.debug("[" + include + "] " + "detected pattern (" + name() + ")");
                }

                String inputPath = matcher.group(1);
                String includes = matcher.group(2);

                ChainedFileWriterEntry writerEntry = new ChainedFileWriterEntry(
                        new File(conf.getBasedir(), inputPath).getAbsolutePath(),
                        includes
                );
                return writerEntry;
            }
        },

        FULL_PATTERN_WITH_CLASSPATH("^classpath:(\\w+):([^:]+):([^:]+)$") {
            @Override
            public ChainedFileWriter getWriter(DefaultChainedWriterEngine engine,
                                               String include,
                                               Matcher matcher) {
                // with full pattern to search in class path (protocol + directory + includes)
                // pattern is discover from the includes
                ChainedFileWriterConfiguration conf = engine.getConfiguration();
                Set universe = engine.getAvailableWriters();

                String protocol = matcher.group(1).toLowerCase();
                ChainedFileWriter writer = engine.getWriterForInputProtocol(universe, protocol, conf.getModelType());

                if (writer == null) {
                    throw new IllegalArgumentException(
                            "could not find the writer named '" + protocol + "', use one of " + universe);
                }
                if (log.isDebugEnabled()) {
                    log.debug("[" + include + "] " + "writer = (" + writer + ")");
                }
                return writer;
            }

            @Override
            public ChainedFileWriterEntry newEntry(DefaultChainedWriterEngine engine,
                                                   String include,
                                                   Matcher matcher,
                                                   ChainedFileWriter writer) {
                // with full pattern (protocol + directory + includes)
                // pattern is discover from the includes
                if (log.isDebugEnabled()) {
                    log.debug("[" + include + "] " + "detected pattern (" + name() + ")");
                }

                String inputPath = matcher.group(2);
                String includes = matcher.group(3);

                //TODO tchemit 2010-09-22 Should be able to do a pattern research
                ChainedFileWriterEntry writerEntry = new ChainedFileWriterEntry(
                        inputPath,
                        includes,
                        true
                );
                return writerEntry;
            }
        },
        FULL_PATTERN("^(\\w+):([^:]+):([^:]+)$") {
            @Override
            public ChainedFileWriter getWriter(DefaultChainedWriterEngine engine,
                                               String include,
                                               Matcher matcher) {
                // with full pattern (protocol + directory + includes)
                // pattern is discover from the includes
                ChainedFileWriterConfiguration conf = engine.getConfiguration();
                Set universe = engine.getAvailableWriters();

                String protocol = matcher.group(1).toLowerCase();
                ChainedFileWriter writer = engine.getWriterForInputProtocol(universe, protocol, conf.getModelType());

                if (writer == null) {
                    throw new IllegalArgumentException(
                            "could not find the writer named '" + protocol + "', use one of " + universe);
                }
                if (log.isDebugEnabled()) {
                    log.debug("[" + include + "] " + "writer = (" + writer + ")");
                }
                return writer;
            }

            @Override
            public ChainedFileWriterEntry newEntry(DefaultChainedWriterEngine engine,
                                                   String include,
                                                   Matcher matcher,
                                                   ChainedFileWriter writer) {
                ChainedFileWriterConfiguration conf = engine.getConfiguration();
                // with full pattern (protocol + directory + includes)
                // pattern is discover from the includes
                if (log.isDebugEnabled()) {
                    log.debug("[" + include + "] " + "detected pattern (" + name() + ")");
                }

                String inputPath = matcher.group(2);
                String includes = matcher.group(3);
                ChainedFileWriterEntry writerEntry = new ChainedFileWriterEntry(
                        new File(conf.getBasedir(), inputPath).getAbsolutePath(),
                        includes
                );
                return writerEntry;
            }
        };

        private final Pattern pattern;

        ModelFileWriterEntryType(String pattern) {
            this.pattern = Pattern.compile(pattern);
        }

        public Pattern getPattern() {
            return pattern;
        }

        public Matcher getMatcher(String include) {
            Matcher matcher = getPattern().matcher(include);
            return matcher.matches() ? matcher : null;
        }

        public abstract ChainedFileWriterEntry newEntry(
                DefaultChainedWriterEngine engine,
                String include,
                Matcher matcher, ChainedFileWriter writer);

        public abstract ChainedFileWriter getWriter(
                DefaultChainedWriterEngine engine,
                String include,
                Matcher matcher);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy