org.etlunit.maven.FeatureCompilerMojo Maven / Gradle / Ivy
package org.etlunit.maven;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.codehaus.jackson.JsonNode;
import org.etlunit.io.FileBuilder;
import org.etlunit.json.validator.*;
import org.etlunit.maven.util.JavaProperty;
import org.etlunit.maven.util.JavaSource;
import org.etlunit.util.IOUtils;
import org.etlunit.util.StringUtils;
import org.etlunit.util.maven.regexp.OperationNameExpression;
import java.io.File;
import java.io.FileFilter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Goal which touches a timestamp file.
*
* @goal generate-gson-proxies
* @phase generate-sources
* @requiresDependencyResolution test
*/
public class FeatureCompilerMojo
extends AbstractMojo
{
/**
* @parameter expression="${project}" default-value="${project}"
*/
protected MavenProject mavenProject;
/**
* Location of the file.
*
* @parameter expression="${basedir}/src/main/resources"
* @required
*/
private File inputDirectory;
private final SchemaResolver resolver = new CachingSchemaResolver();
/**
* Location of the file.
*
* @parameter expression="${outputDirectory}" default-value="${project.build.directory}/generated-sources/etlunit"
* @required
*/
private File outputDirectory;
private final List schemaErrors = new ArrayList();
public void execute()
throws MojoExecutionException
{
File f = outputDirectory;
if (!f.exists())
{
f.mkdirs();
}
// recurse, looking for schema's
scanDir(inputDirectory, null, true);
scanDir(inputDirectory, null, false);
if (schemaErrors.size() != 0)
{
throw new MojoExecutionException("Errors processing schema files: " + schemaErrors);
}
if (mavenProject != null)
{
mavenProject.addCompileSourceRoot(outputDirectory.getAbsolutePath());
}
}
private void scan(File file, String packag, boolean scanOnly)
{
if (file.isDirectory())
{
getLog().info((!scanOnly ? "Processing" : "Prescanning") + " 1-level resource dir: " + file.getAbsolutePath());
scanDir(file, packag == null ? file.getName() : (packag + "." + file.getName()), scanOnly);
}
else if (file.isFile() && file.getName().endsWith(".jsonSchema"))
{
scanFile(file, packag, scanOnly);
}
}
private void scanFile(File file, String packag, boolean scanOnly)
{
getLog().info((!scanOnly ? "Processing" : "Prescanning") + " schema file: " + file.getName());
try
{
JsonNode schemaNode = JsonUtils.loadJson(file);
JsonSchema schema = new JsonSchema(schemaNode);
if (scanOnly)
{
String uri = (packag == null ? "" : (packag.replace('.', '/') + "/")) + file.getName();
getLog().info("Registering schema to uri: " + uri);
resolver.registerSchemaByLocalId(uri, schema);
return;
}
FileBuilder outputBuilder = new FileBuilder(outputDirectory);
if (packag != null)
{
outputBuilder = outputBuilder.subdir(packag.replace('.', '/'));
}
outputBuilder = outputBuilder.mkdirs();
JsonValidator validator = new JsonValidator(schema, resolver);
String featureName = getFeatureName(file.getName());
if (file.getName().endsWith(".configuration.validator.jsonSchema"))
{
// process configuration schema
generateSourceFromSchema(packag, outputBuilder, validator.resolveSchemaReference(schema.getSchemaNode()), StringUtils.makeProperPropertyName(featureName + "Configuration"));
}
else if (file.getName().endsWith(".validator.jsonSchema"))
{
// process operational schema
// each of these extends the configuration schema
generateSourceFromSchema(packag, outputBuilder, validator.resolveSchemaReference(schema.getSchemaNode()), StringUtils.makeProperPropertyName(getOperationName(file.getName()) + "Operation"));
generateInterfaceForOperation(
packag,
StringUtils.makeProperPropertyName(getOperationName(file.getName()) + "Operation"),
StringUtils.makeProperPropertyName(getOperationName(file.getName()))
);
}
}
catch (JsonSchemaValidationException e)
{
getLog().error(e);
schemaErrors.add(e);
throw new IllegalArgumentException(e);
}
catch (Exception e)
{
getLog().error(e);
throw new IllegalArgumentException(e);
}
}
private void generateInterfaceForOperation(String packag, String operationClass, String operationName) throws IOException
{
String name = operationClass + "Processor";
FileBuilder outputBuilder = new FileBuilder(outputDirectory);
if (packag != null)
{
outputBuilder = outputBuilder.subdir(packag.replace('.', '/'));
}
outputBuilder = outputBuilder.mkdirs();
File output = outputBuilder.name(name + ".java").file();
getLog().info("Creating processor interface: " + output);
IOUtils.writeBufferToFile(output, new StringBuffer("package " + packag + ";\n" +
"\n" +
"import org.etlunit.*;\n" +
"import org.etlunit.context.VariableContext;\n" +
"import org.etlunit.parser.ETLTestOperation;\n" +
"import org.etlunit.parser.ETLTestValueObject;\n" +
"\n" +
"public interface " + operationClass + "Processor {\n" +
"\tpublic ClassResponder.action_code process" + operationName + "(" + operationClass + " operation, ETLTestOperation op, ETLTestValueObject obj, VariableContext context, ExecutionContext econtext) throws TestAssertionFailure, TestExecutionError, TestWarning;\n" +
"}"));
}
private String getOperationName(String name)
{
OperationNameExpression one = new OperationNameExpression(name);
if (one.hasNext())
{
return one.getOperationName();
}
throw new IllegalArgumentException("Invalid schema file name: " + name);
}
private void generateSourceFromSchema(String packag, FileBuilder outputBuilder, JsonSchemaObjectNode schema, String className) throws IOException
{
File output = outputBuilder.name(className + ".java").file();
getLog().info("Creating operation request interface: " + output);
Map properties = schema.getPropertySchemas();
JavaSource source = new JavaSource(packag, className);
for (Map.Entry entry : properties.entrySet())
{
String key = entry.getKey();
if (key.startsWith("_"))
{
continue;
}
JsonSchemaObjectNode propertySchema = entry.getValue();
JavaProperty property = new JavaProperty(key, propertySchema.getType().get(0), propertySchema.getEnumValues(), propertySchema.isRequired());
source.addProperty(property);
}
IOUtils.writeBufferToFile(output, new StringBuffer(source.toSource()));
}
private String getFeatureName(String name)
{
int endOfFeatureName = name.indexOf('.');
return name.substring(0, endOfFeatureName);
}
private void scanDir(File file, final String packag, final boolean scanOnly)
{
getLog().info((!scanOnly ? "Processing" : "Prescanning") + " resource dir: " + file.getName());
// skip these common dirs
if (file.getName().equals("META-INF") || file.getName().equals("WEB-INF") || file.getName().startsWith("."))
{
return;
}
file.listFiles(new FileFilter()
{
public boolean accept(File pathname)
{
scan(pathname, packag, scanOnly);
return false;
}
});
}
public void setInputDirectory(File inputDirectory)
{
this.inputDirectory = inputDirectory;
if (!inputDirectory.exists())
{
throw new IllegalArgumentException("Input directory does not exist: " + inputDirectory);
}
}
public void setOutputDirectory(File outputDirectory)
{
this.outputDirectory = outputDirectory;
outputDirectory.mkdirs();
if (!outputDirectory.exists())
{
throw new IllegalArgumentException("Input directory does not exist: " + outputDirectory);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy