package org.insightech.er.editor.model.dbexport.java;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.insightech.er.ResourceString;
import org.insightech.er.db.sqltype.SqlType;
import org.insightech.er.editor.model.ERDiagram;
import org.insightech.er.editor.model.diagram_contents.element.node.NodeElement;
import org.insightech.er.editor.model.diagram_contents.element.node.table.ERTable;
import org.insightech.er.editor.model.diagram_contents.element.node.table.TableView;
import org.insightech.er.editor.model.diagram_contents.element.node.table.column.NormalColumn;
import org.insightech.er.editor.model.settings.export.ExportJavaSetting;
import org.insightech.er.util.Check;
import org.insightech.er.util.Format;
import org.insightech.er.util.io.FileUtils;
import org.insightech.er.util.io.IOUtils;
public class ExportToJavaManager {
private static final String TEMPLATE_DIR = "java" + File.separator;
private static final String[] KEYWORDS = { "java.template.constructor",
"java.template.getter.description",
"java.template.set.adder.description",
"java.template.set.getter.description",
"java.template.set.property.description",
"java.template.set.setter.description",
"java.template.setter.description", };
private static final String TEMPLATE;
private static final String IMPLEMENTS;
private static final String PROPERTIES;
private static final String SET_PROPERTIES;
private static final String SETTER_GETTER;
private static final String SETTER_GETTER_ADDER;
private static final String HASHCODE_EQUALS;
private static final String HASHCODE_LOGIC;
private static final String EQUALS_LOGIC;
private static final String EXTENDS;
private static final String HIBERNATE_TEMPLATE;
private static final String HIBERNATE_PROPERTY;
private static final String HIBERNATE_ID;
private static final String HIBERNATE_COMPOSITE_ID;
private static final String HIBERNATE_COMPOSITE_ID_KEY;
static {
try {
TEMPLATE = loadResource("template");
IMPLEMENTS = loadResource("@implements");
PROPERTIES = loadResource("@properties");
SET_PROPERTIES = loadResource("@set_properties");
SETTER_GETTER = loadResource("@setter_getter");
SETTER_GETTER_ADDER = loadResource("@setter_getter_adder");
HASHCODE_EQUALS = loadResource("@hashCode_equals");
HASHCODE_LOGIC = loadResource("@hashCode logic");
EQUALS_LOGIC = loadResource("@equals logic");
EXTENDS = loadResource("@extends");
HIBERNATE_TEMPLATE = loadResource("hibernate" + File.separator
+ "hbm");
HIBERNATE_PROPERTY = loadResource("hibernate" + File.separator
+ "@property");
HIBERNATE_ID = loadResource("hibernate" + File.separator + "@id");
HIBERNATE_COMPOSITE_ID = loadResource("hibernate" + File.separator
+ "@composite_id");
HIBERNATE_COMPOSITE_ID_KEY = loadResource("hibernate"
+ File.separator + "@composite_id_key");
} catch (IOException e) {
e.printStackTrace();
throw new ExceptionInInitializerError(e);
}
}
private ExportJavaSetting exportJavaSetting;
protected ERDiagram diagram;
private String packageDir;
private Set<String> importClasseNames;
private Set<String> sets;
public ExportToJavaManager(ExportJavaSetting exportJavaSetting,
ERDiagram diagram) {
this.packageDir = exportJavaSetting.getPackageName().replaceAll("\\.",
"\\/");
this.exportJavaSetting = exportJavaSetting;
this.diagram = diagram;
this.importClasseNames = new TreeSet<String>();
this.sets = new TreeSet<String>();
}
protected void doPreTask(ERTable table) {
}
protected void doPostTask() throws InterruptedException {
}
public void doProcess() throws IOException, InterruptedException {
for (ERTable table : diagram.getDiagramContents().getContents()
.getTableSet().getList()) {
this.doPreTask(table);
String className = this.getClassName(table);
String compositeIdClassName = null;
if (this.exportJavaSetting.isWithHibernate()) {
if (table.getPrimaryKeySize() > 1) {
compositeIdClassName = this.getCamelCaseName(table) + "Id";
String compositeIdContent = this
.generateCompositeIdContent(diagram, table,
compositeIdClassName);
this.writeOut(File.separator + this.packageDir
+ File.separator + compositeIdClassName + ".java",
compositeIdContent);
}
String hbmContent = this.generateHbmContent(diagram, table,
compositeIdClassName);
this.writeOut(File.separator + this.packageDir + File.separator
+ className + ".hbm.xml", hbmContent);
}
String content = this.generateContent(diagram, table,
compositeIdClassName);
this.writeOut(File.separator + this.packageDir + File.separator
+ className + ".java", content);
}
}
protected String getClassName(ERTable table) {
return this.getCamelCaseName(table)
+ this.getCamelCaseName(this.exportJavaSetting
.getClassNameSuffix(), true);
}
protected String getCamelCaseName(ERTable table) {
return this.getCamelCaseName(table.getPhysicalName(), true);
}
protected String getCamelCaseName(String name, boolean capital) {
String className = name.toLowerCase();
if (capital && className.length() > 0) {
String first = className.substring(0, 1);
String other = className.substring(1);
className = first.toUpperCase() + other;
}
while (className.indexOf("_") == 0) {
className = className.substring(1);
}
int index = className.indexOf("_");
while (index != -1) {
String before = className.substring(0, index);
if (className.length() == index + 1) {
className = before;
break;
}
String target = className.substring(index + 1, index + 2);
String after = null;
if (className.length() == index + 1) {
after = "";
} else {
after = className.substring(index + 2);
}
className = before + target.toUpperCase() + after;
index = className.indexOf("_");
}
return className;
}
private static String loadResource(String templateName) throws IOException {
String resourceName = TEMPLATE_DIR + templateName + ".txt";
InputStream in = ExportToJavaManager.class.getClassLoader()
.getResourceAsStream(resourceName);
if (in == null) {
throw new FileNotFoundException(resourceName);
}
try {
String content = IOUtils.toString(in);
for (String keyword : KEYWORDS) {
content = content.replaceAll(keyword, ResourceString
.getResourceString(keyword));
}
return content;
} finally {
in.close();
}
}
private String generateContent(ERDiagram diagram, ERTable table,
String compositeIdClassName) throws IOException {
this.importClasseNames.clear();
this.importClasseNames.add("java.io.Serializable");
this.sets.clear();
String content = TEMPLATE;
content = content.replace("@implements", IMPLEMENTS);
content = this.replacePropertiesInfo(content, table,
compositeIdClassName);
content = this.replaceHashCodeEqualsInfo(content, table,
compositeIdClassName);
String classDescription = ResourceString.getResourceString(
"java.template.class.description").replaceAll(
"@LogicalTableName", table.getLogicalName());
content = this.replaceClassInfo(content, classDescription, this
.getCamelCaseName(table), this.exportJavaSetting
.getClassNameSuffix());
content = this.replaceExtendInfo(content);
content = this.replaceImportInfo(content);
content = this.replaceConstructorInfo(content);
return content;
}
private String generateCompositeIdContent(ERDiagram diagram, ERTable table,
String compositeIdClassName) throws IOException {
this.importClasseNames.clear();
this.importClasseNames.add("java.io.Serializable");
this.sets.clear();
String content = TEMPLATE;
content = content.replace("@implements", IMPLEMENTS);
content = this.replacePropertiesInfo(content, null, table
.getPrimaryKeys(), null, null);
content = this.replaceHashCodeEqualsInfo(content, table, null);
String classDescription = ResourceString.getResourceString(
"java.template.composite.id.class.description").replaceAll(
"@LogicalTableName", table.getLogicalName());
content = this.replaceClassInfo(content, classDescription,
compositeIdClassName, "");
content = this.replaceExtendInfo(content);
content = this.replaceImportInfo(content);
content = this.replaceConstructorInfo(content);
return content;
}
private String replacePropertiesInfo(String content, ERTable table,
String compositeIdClassName) throws IOException {
return replacePropertiesInfo(content, table,
table.getExpandedColumns(), table.getReferringElementList(),
compositeIdClassName);
}
private String replacePropertiesInfo(String content, ERTable table,
List<NormalColumn> columns, List<NodeElement> referringElementList,
String compositeIdClassName) throws IOException {
StringBuilder properties = new StringBuilder();
StringBuilder setterGetters = new StringBuilder();
if (compositeIdClassName != null) {
this.addCompositeIdContent(properties, PROPERTIES,
compositeIdClassName, table);
this.addCompositeIdContent(setterGetters, SETTER_GETTER,
compositeIdClassName, table);
}
for (NormalColumn normalColumn : columns) {
if (compositeIdClassName == null || !normalColumn.isPrimaryKey()
|| normalColumn.isForeignKey()) {
this.addContent(properties, PROPERTIES, normalColumn);
this.addContent(setterGetters, SETTER_GETTER, normalColumn);
}
}
if (referringElementList != null) {
for (NodeElement referringElement : referringElementList) {
if (referringElement instanceof TableView) {
TableView tableView = (TableView) referringElement;
this.addContent(properties, SET_PROPERTIES, tableView);
this.addContent(setterGetters, SETTER_GETTER_ADDER,
tableView);
this.sets.add(tableView.getPhysicalName());
}
}
}
content = content.replaceAll("@properties\r\n", properties.toString());
content = content.replaceAll("@setter_getter\r\n", setterGetters
.toString());
return content;
}
private String replaceHashCodeEqualsInfo(String content, ERTable table,
String compositeIdClassName) throws IOException {
if (compositeIdClassName != null) {
StringBuilder hashCodes = new StringBuilder();
StringBuilder equals = new StringBuilder();
this.addCompositeIdContent(hashCodes, HASHCODE_LOGIC,
compositeIdClassName, table);
this.addCompositeIdContent(equals, EQUALS_LOGIC,
compositeIdClassName, table);
String hashCodeEquals = HASHCODE_EQUALS;
hashCodeEquals = hashCodeEquals.replaceAll("@hashCode logic\r\n",
hashCodes.toString());
hashCodeEquals = hashCodeEquals.replaceAll("@equals logic\r\n",
equals.toString());
content = content.replaceAll("@hashCode_equals\r\n", hashCodeEquals
.toString());
} else if (table.getPrimaryKeySize() > 0) {
StringBuilder hashCodes = new StringBuilder();
StringBuilder equals = new StringBuilder();
for (NormalColumn primaryKey : table.getPrimaryKeys()) {
this.addContent(hashCodes, HASHCODE_LOGIC, primaryKey);
this.addContent(equals, EQUALS_LOGIC, primaryKey);
}
String hashCodeEquals = HASHCODE_EQUALS;
hashCodeEquals = hashCodeEquals.replaceAll("@hashCode logic\r\n",
hashCodes.toString());
hashCodeEquals = hashCodeEquals.replaceAll("@equals logic\r\n",
equals.toString());
content = content.replaceAll("@hashCode_equals\r\n", hashCodeEquals
.toString());
} else {
content = content.replaceAll("@hashCode_equals\r\n", "");
}
return content;
}
private String replaceClassInfo(String content, String classDescription,
String className, String classNameSufix) {
if (Check.isEmptyTrim(this.exportJavaSetting.getPackageName())) {
content = content.replaceAll("package @package;\r\n\r\n", "");
} else {
content = content.replaceAll("@package", this.exportJavaSetting
.getPackageName());
}
content = content.replaceAll("@classDescription", classDescription);
content = content.replaceAll("@PhysicalTableName", className);
content = content.replaceAll("@suffix", this.getCamelCaseName(
classNameSufix, true));
content = content.replaceAll("@version", "@version \\$Id\\$");
return content;
}
private String replaceExtendInfo(String content) throws IOException {
if (Check.isEmpty(this.exportJavaSetting.getExtendsClass())) {
content = content.replaceAll("@import extends\r\n", "");
content = content.replaceAll("@extends ", "");
} else {
this.importClasseNames
.add(this.exportJavaSetting.getExtendsClass());
content = content.replaceAll("@extends", EXTENDS);
int index = this.exportJavaSetting.getExtendsClass().lastIndexOf(
".");
String extendsClassWithoutPackage = null;
if (index == -1) {
extendsClassWithoutPackage = this.exportJavaSetting
.getExtendsClass();
} else {
extendsClassWithoutPackage = this.exportJavaSetting
.getExtendsClass().substring(index + 1);
}
content = content.replaceAll("@extendsClassWithoutPackage",
extendsClassWithoutPackage);
content = content.replaceAll("@extendsClass",
this.exportJavaSetting.getExtendsClass());
}
return content;
}
private String replaceImportInfo(String content) {
StringBuilder imports = new StringBuilder();
for (String importClasseName : this.importClasseNames) {
imports.append("import ");
imports.append(importClasseName);
imports.append(";\r\n");
}
content = content.replaceAll("@import\r\n", imports.toString());
return content;
}
private String replaceConstructorInfo(String content) {
StringBuilder constructor = new StringBuilder();
for (String tableName : this.sets) {
constructor.append("\t\tthis.");
constructor.append(this.getCamelCaseName(tableName, false));
constructor.append("Set = new HashSet<");
constructor.append(this.getCamelCaseName(tableName, true)
+ this.getCamelCaseName(this.exportJavaSetting
.getClassNameSuffix(), true));
constructor.append(">();\r\n");
}
content = content
.replaceAll("@constructor\r\n", constructor.toString());
return content;
}
private void addContent(StringBuilder contents, String template,
NormalColumn normalColumn) {
String value = null;
if (normalColumn.isForeignKey()) {
NormalColumn referencedColumn = normalColumn
.getRootReferencedColumn();
ERTable referencedTable = (ERTable) referencedColumn
.getColumnHolder();
String className = this.getClassName(referencedTable);
value = template.replaceAll("@type", className);
value = value.replaceAll("@logicalColumnName", referencedTable
.getName());
String physicalName = normalColumn.getPhysicalName().toLowerCase();
physicalName = physicalName.replaceAll(referencedColumn
.getPhysicalName().toLowerCase(), "");
if (physicalName.indexOf(referencedTable.getPhysicalName()
.toLowerCase()) == -1) {
physicalName = physicalName + referencedTable.getPhysicalName();
}
value = value.replaceAll("@physicalColumnName", this
.getCamelCaseName(physicalName, false));
value = value.replaceAll("@PhysicalColumnName", this
.getCamelCaseName(physicalName, true));
} else {
value = template.replaceAll("@type", this.getClassName(normalColumn
.getType()));
value = value.replaceAll("@logicalColumnName", normalColumn
.getLogicalName());
value = value.replaceAll("@physicalColumnName", this
.getCamelCaseName(normalColumn.getPhysicalName(), false));
value = value.replaceAll("@PhysicalColumnName", this
.getCamelCaseName(normalColumn.getPhysicalName(), true));
}
contents.append(value);
contents.append("\r\n");
}
private void addContent(StringBuilder contents, String template,
TableView tableView) {
String value = template;
this.importClasseNames.add("java.util.Set");
this.importClasseNames.add("java.util.HashSet");
value = value.replaceAll("@setType", "Set<"
+ this.getCamelCaseName(tableView.getPhysicalName(), true)
+ this.getCamelCaseName(this.exportJavaSetting
.getClassNameSuffix(), true) + ">");
value = value.replaceAll("@type", this.getCamelCaseName(tableView
.getPhysicalName(), true)
+ this.getCamelCaseName(this.exportJavaSetting
.getClassNameSuffix(), true));
value = value.replaceAll("@logicalColumnName", tableView.getName());
value = value.replaceAll("@physicalColumnName", this.getCamelCaseName(
tableView.getPhysicalName(), false));
value = value.replaceAll("@PhysicalColumnName", this.getCamelCaseName(
tableView.getPhysicalName(), true));
contents.append(value);
contents.append("\r\n");
}
private void addCompositeIdContent(StringBuilder contents, String template,
String compositeIdClassName, ERTable table) {
String compositeIdPropertyName = compositeIdClassName.substring(0, 1)
.toLowerCase()
+ compositeIdClassName.substring(1);
String propertyDescription = ResourceString.getResourceString(
"java.template.composite.id.property.description").replaceAll(
"@LogicalTableName", table.getLogicalName());
String value = template;
value = value.replaceAll("@type", compositeIdClassName);
value = value.replaceAll("@logicalColumnName", propertyDescription);
value = value
.replaceAll("@physicalColumnName", compositeIdPropertyName);
value = value.replaceAll("@PhysicalColumnName", compositeIdClassName);
contents.append(value);
contents.append("\r\n");
}
private String getClassName(SqlType type) {
if (type == null) {
return "";
}
Class clazz = type.getJavaClass();
String name = clazz.getCanonicalName();
if (!name.startsWith("java.lang")) {
this.importClasseNames.add(name);
}
return clazz.getSimpleName();
}
private String getFullClassName(SqlType type) {
if (type == null) {
return "";
}
Class clazz = type.getJavaClass();
String name = clazz.getCanonicalName();
return name;
}
private void writeOut(String dstPath, String content) throws IOException {
dstPath = this.exportJavaSetting.getJavaOutput() + File.separator
+ "src" + dstPath;
File file = new File(dstPath);
file.getParentFile().mkdirs();
FileUtils.writeStringToFile(file, content, this.exportJavaSetting
.getSrcFileEncoding());
}
private String generateHbmContent(ERDiagram diagram, ERTable table,
String compositeIdClassName) throws IOException {
String content = HIBERNATE_TEMPLATE;
content = content.replaceAll("@package", this.exportJavaSetting
.getPackageName());
content = content.replaceAll("@PhysicalTableName", this
.getCamelCaseName(table));
content = content.replaceAll("@suffix", Format
.null2blank(this.exportJavaSetting.getClassNameSuffix()));
content = content.replaceAll("@realTableName", table.getPhysicalName());
StringBuilder properties = new StringBuilder();
if (table.getPrimaryKeySize() == 1) {
for (NormalColumn column : table.getPrimaryKeys()) {
String property = HIBERNATE_ID;
property = property.replaceAll("@physicalColumnName", this
.getCamelCaseName(column.getPhysicalName(), false));
property = property.replaceAll("@realColumnName", column
.getPhysicalName());
property = property.replaceAll("@type", this
.getFullClassName(column.getType()));
property = property.replaceAll("@generator", "assigned");
properties.append(property);
}
} else if (table.getPrimaryKeySize() > 1) {
String property = HIBERNATE_COMPOSITE_ID;
StringBuilder keys = new StringBuilder();
for (NormalColumn column : table.getPrimaryKeys()) {
String key = HIBERNATE_COMPOSITE_ID_KEY;
key = key.replaceAll("@physicalColumnName", this
.getCamelCaseName(column.getPhysicalName(), false));
key = key.replaceAll("@realColumnName", column
.getPhysicalName());
key = key.replaceAll("@type", this.getFullClassName(column
.getType()));
keys.append(key);
}
String compositeIdPropertyName = compositeIdClassName.substring(0,
1).toLowerCase()
+ compositeIdClassName.substring(1);
property = property.replaceAll("@compositeIdPropertyName",
compositeIdPropertyName);
property = property.replaceAll("@compositeIdClassName",
compositeIdClassName);
property = property.replaceAll("@key_properties", keys.toString());
properties.append(property);
}
for (NormalColumn column : table.getExpandedColumns()) {
if (!column.isPrimaryKey()) {
String property = HIBERNATE_PROPERTY;
property = property.replaceAll("@physicalColumnName", this
.getCamelCaseName(column.getPhysicalName(), false));
property = property.replaceAll("@realColumnName", column
.getPhysicalName());
property = property.replaceAll("@type", this
.getFullClassName(column.getType()));
property = property.replaceAll("@not-null", String
.valueOf(column.isNotNull()));
properties.append(property);
}
}
content = content.replaceAll("@properties\r\n", properties.toString());
return content;
}
}