org.nuiton.eugene.writer.DefaultChainedWriterEngine Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eugene Show documentation
Show all versions of eugene Show documentation
Efficient Universal Generator.
/*
* #%L
* EUGene :: EUGene
* %%
* Copyright (C) 2004 - 2010 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
* .
* #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);
}
}