/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.transformation.reverseeng;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.eclipse.core.runtime.IStatus;
import org.teiid.designer.core.container.Container.OPTIONS;
import org.teiid.designer.metamodels.transformation.TransformationPlugin;
import org.teiid.designer.runtime.spi.TeiidExecutionException;
import org.teiid.designer.transformation.reverseeng.api.AnnotationType;
import org.teiid.designer.transformation.reverseeng.api.Column;
import org.teiid.designer.transformation.reverseeng.api.MetadataProcessor;
import org.teiid.designer.transformation.reverseeng.api.Options;
import org.teiid.designer.transformation.reverseeng.api.Table;
import org.teiid.designer.transformation.reverseeng.api.Options.Parms;
import org.teiid.designer.transformation.reverseeng.util.Util;
/**
* @author van halbert
*
*/
public class PojoProcessing {
private static final String LICENSE_TEMPLATE = "org/teiid/reverseeng/license_template.txt";
private Options options;
private String path;
private String packageName;
private String pojoJarName;
private String suffixClassName;
private String moduleZipFileName;
private AnnotationType annotationType;
private ModulePackaging module = null;
private Collection<Exception> errors = new ArrayList<Exception>();
public PojoProcessing() {
}
public PojoProcessing(Options options) {
this.options = options;
this.path = options.getProperty(Options.Parms.BUILD_LOCATION);
annotationType = options.getAnnotationTypeInstance();
packageName = options.getProperty(Options.Parms.POJO_PACKAGE_NAME);
pojoJarName = options.getProperty(Options.Parms.POJO_JAR_FILE);
this.suffixClassName = options.getProperty(Options.Parms.CLASS_NAME_SUFFIX);
moduleZipFileName = options.getProperty(Options.Parms.MODULE_ZIP_FILE);
String doGenerateModule = options.getProperty(Options.Parms.GENERATE_MODULE);
if (doGenerateModule != null && moduleZipFileName != null) {
module = new ModulePackaging();
}
}
public Collection<Exception> getExceptions() {
return errors;
}
/**
* Called to perform the project processing of the metadata. Will return <code>true</code> if it
* was successful, with no exceptions. If it returns <code>false</code>, then should call
* {@link #getExceptions()} to obtain the errors that occurred.
* @param metadata
* @return boolean true if successful
*/
public boolean processTables(MetadataProcessor metadata, Options options) {
// ReverseEngineerPlugin.LOGGER.info("[ReverseEngineering] Start reverse engineering process");
try {
performProcess(metadata, options);
} catch (Exception e) {
errors.add(e);
}
// ReverseEngineerPlugin.LOGGER.info("[ReverseEngineering] Finished reverse engineering process");
if (errors.isEmpty()) return true;
return false;
}
private void performProcess(MetadataProcessor metadata, Options options) throws Exception {
// remove if already exist
File buildLocation = new File(path);
if (buildLocation.exists()) {
buildLocation.delete();
}
buildLocation.mkdir();
// Location for the .java and .class files
File classDirLocaton = new File(buildLocation, "class");
classDirLocaton.mkdir();
// location for created kits, example: .jar or .zip
File kitLocation = new File(buildLocation, "kit");
kitLocation.mkdir();
// parse the package name to use to create the folder structure
List<String> nodes = Util.getTokens(packageName, ".");
StringBuffer jarPackageFilePath = new StringBuffer();
for (String n : nodes) {
jarPackageFilePath.append(n).append(File.separator);
}
// TODO: future option to have user define the name of the "main" source folder
nodes.add("main");
// create a file path structure of only the package name, used for creating path structure for artifacts
StringBuffer modulePackagePath = new StringBuffer();
for (String n : nodes) {
modulePackagePath.append(n).append(File.separator);
}
File javaFileLoc = new File(classDirLocaton.getAbsolutePath() + File.separator + jarPackageFilePath.toString());
javaFileLoc.mkdirs();
File pojoJarFile = null;
if (pojoJarName != null && pojoJarName.trim().length() > 0) {
pojoJarFile = new File(kitLocation, pojoJarName);
} else {
pojoJarFile = new File(kitLocation, Options.Parms_Defaults.DEFAULT_POJO_JAR_FILE);
}
File parentPojoJar = pojoJarFile.getParentFile();
if (!parentPojoJar.exists()) {
parentPojoJar.mkdirs();
}
List<Table> tables = metadata.getTableMetadata();
Table theTable = tables.get(0);
if (!theTable.hasRequiredColumn()) {
String msg = "*** Table {" + theTable.getName() + "} doesn't have a required key column (i.e., no primary or unique key defined on the source table). Will not be processed";
TransformationPlugin.Util.log(IStatus.WARNING, msg);
this.errors.add( new TeiidExecutionException(IStatus.ERROR, msg));
}
String className = theTable.getClassName();
String userDefinedClassName = options.getProperty(Parms.POJO_CLASS_NAME);
if( userDefinedClassName != null ) {
className = userDefinedClassName;
}
className = className + (this.suffixClassName != null ? this.suffixClassName : "");
String javaFileName = className + ".java";
File outputFile = new File(javaFileLoc.getAbsolutePath(), javaFileName);
FileOutputStream fileOutput = new FileOutputStream(outputFile);
PrintWriter outputStream = new PrintWriter(fileOutput);
printPackage(outputStream, packageName);
printHeader(outputStream, theTable);
printImports(outputStream, theTable);
printClass(outputStream, theTable, className);
printAttributes(outputStream, theTable);
printGetterSetters(outputStream, theTable);
printToString(outputStream, theTable);
printFooter(outputStream, theTable);
fileOutput.close();
TransformationPlugin.Util.log(IStatus.INFO, "[ReverseEngineering] Created java file: " + outputFile.getAbsolutePath());
PojoCompilation.compile(javaFileLoc, classDirLocaton, jarPackageFilePath.toString(), pojoJarFile);
if (module != null) {
try {
module.performPackaging(options, packageName, pojoJarFile, moduleZipFileName, buildLocation, modulePackagePath.toString(), kitLocation);
// ReverseEngineerPlugin.LOGGER.info("[ReverseEngineering] Created module zip: " + pojoJarName);
} catch(Exception e) {
errors.add(e);
}
}
}
protected void printPackage(PrintWriter outputStream, String packageName) throws IOException {
InputStream is = getClass().getClassLoader().getResourceAsStream(LICENSE_TEMPLATE);
if (is != null) {
for( int c = is.read(); c != -1; c = is.read() ) {
outputStream.print((char) c);
}
}
outputStream.println("package " + packageName + ";");
}
/**
* prints standard source file header to outputStream
*
* @param outputStream
* where to print the header
* @param t
* the Table representing the class
*/
protected void printHeader(PrintWriter outputStream, Table t) {
outputStream.println("/**");
outputStream.println("* Maps a relational database table "
+ t.getName() + " to a java object, " + t.getClassName());
outputStream.println("*");
outputStream.println("* " + (t.getRemarks() != null ? t.getRemarks() : ""));
outputStream.println("*");
outputStream.println("* @author ReverseEngineer");
outputStream.println("*/");
} // printHeader()
/**
* prints imports to outputStream
*
* @param outputStream
* where to print the header
* @param t
* the Table representing the class
*/
protected void printImports(PrintWriter outputStream, Table t) {
outputStream.println("import java.io.Serializable;");
outputStream.println("import java.sql.*;");
outputStream.println("import java.util.*;");
if (annotationType != null) {
List<String> imports = annotationType.getImports();
for(String i : imports) {
outputStream.println(i);
}
}
} // printImports()
protected void printClass(PrintWriter outputStream, Table t, String className) {
outputStream.println("\r");
if (annotationType != null) {
String a = annotationType.getClassAnnotation(t);
if (a != null) {
outputStream.println(a);
}
}
outputStream.println("public class " + className
+ " implements Serializable {");
} // printClass
protected void printAttributes(PrintWriter outputStream, Table t) {
List<Column> columns = t.getColumns();
for (Column c : columns) {
if (annotationType != null) {
outputStream.println("\r");
String a = annotationType.getAttributeAnnotation(c);
if (a != null) {
outputStream.println("\t" + a);
}
}
outputStream.println(buildAttributeStatement(c));
}
}
protected void printGetterSetters(PrintWriter outputStream, Table t) {
outputStream.println("\r");
List<Column> columns = t.getColumns();
for (Column c : columns) {
if (annotationType != null) {
outputStream.println("\r");
String a = annotationType.getGetterMethodAnnotation(c);
if (a != null) {
outputStream.println(a); //"\t" + a);
}
}
outputStream.println(buildGetStatement(c));
outputStream.println("\r");
outputStream.println(buildSetStatement(c));
}
}
protected void printToString(PrintWriter outputStream, Table t) {
outputStream.println(buildToString(t));
}
protected void printFooter(PrintWriter outputStream, Table t) {
outputStream.println("} // class " + t.getClassName());
outputStream.close();
}
/**
* Called to build the Attribute statement based on the Column
*
* @param column
* @return Attribute statement
*/
public String buildAttributeStatement(Column column) {
StringBuffer result = new StringBuffer();
result.append("\tpublic ");
result.append(column.getJavaType());
result.append(" m_");
result.append(column.getMemberName());
result.append(";");
return result.toString();
}
/**
* builds a GET statement based on the Column
*
* @param column
* @return the get statement string
*/
public String buildGetStatement(Column column) {
StringBuffer result = new StringBuffer();
result.append("\tpublic ");
result.append(column.getJavaType());
result.append(" get");
result.append(column.getMemberName());
result.append("( ) { \r");
result.append("\t\treturn this.m_");
result.append(column.getMemberName());
result.append(";");
result.append("\r\t}");
return result.toString();
}
/**
* Called to build a SET based on the Column
*
* @param column
* @return the set statement string
*/
public String buildSetStatement(Column column) {
StringBuffer result = new StringBuffer();
result.append("\tpublic void set");
result.append(column.getMemberName());
result.append("( ");
result.append(column.getJavaType());
result.append(" ");
result.append(column.getName());
result.append(") { \r\t\t this.m_");
result.append(column.getMemberName());
result.append(" = ");
result.append(column.getName());
result.append("; \r\t}");
return result.toString();
}
/**
* Called to build the toString based on the Table
*
* @param table
* @return the set statement string
*/
public String buildToString(Table table) {
StringBuffer result = new StringBuffer();
result.append("\tpublic String toString() {\n\t\tStringBuffer output = new StringBuffer();\n");
List<Column> columns = table.getColumns();
for (Column c : columns) {
result.append("\t\toutput.append(\"" + c.getName() + ":\");\n");
result.append("\t\toutput.append(get" + c.getMemberName() + "());\n");
result.append("\t\toutput.append(\"\\n\");\n");
}
result.append("\n\t\treturn output.toString();\n\t}\n");
return result.toString();
}
}