/* * Copyright 2013 Simon Thiel * * This file is part of SitJar. * * SitJar 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. * * SitJar 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with SitJar. If not, see <http://www.gnu.org/licenses/lgpl.txt>. */ package sit.db.generator; import sit.db.Connection; import sit.db.exception.DBException; import sit.db.ConnectionManager; import java.io.IOException; import java.sql.DatabaseMetaData; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; import sit.db.datastructure.DataStructure; import sit.db.table.SQLTypeHelper; import sit.db.table.TABLE_ENTRY_TYPE; import sit.db.table.TableEntry; import sit.io.FileHelper; /** * * @author simon * @param <T> */ public class TableGenerator<T extends DataStructure<T>> { private final String rootDirForGenerateFiles; private final String rootPackage; private final String tableString = "table"; private final String controllerString = "controller"; private final String tableSubPath = "/" + tableString; private final String controllerSubPath = "/" + controllerString; private final String tablePackage; private final String controllerPackage; private final FileHelper fh = new FileHelper(); private final String rootPath; private DatabaseMetaData databaseMetaData = null; public TableGenerator(String rootDirForGenerateFiles, String rootPackage, String rootPath) { this.rootDirForGenerateFiles = rootDirForGenerateFiles; this.rootPackage = rootPackage; this.rootPath = rootPath; this.tablePackage = rootPackage + "." + tableString; this.controllerPackage = rootPackage + "." + controllerString; } public void generateTable(final TableMapEntry tableEntry, ConnectionManager db) throws DBException, SQLException { System.out.println("generate for table: " + tableEntry.tableName); Connection connection = db.getConnection(); try { PreparedStatement stmt = connection.createPrepStmt("Select * from " + tableEntry.tableName); if (!stmt.execute()) { throw new DBException(tableEntry.tableName, "error when accessing", -1); } databaseMetaData = connection.getMetaData(); createFiles(stmt.getMetaData(), tableEntry); } finally { db.returnConnection(connection); } } private void validateDirStructure() { fh.createDirectoriesIfNotExist(rootPath + tableSubPath); fh.createDirectoriesIfNotExist(rootPath + controllerSubPath); } private void createFiles(final TableMapEntry tableEntry, final ArrayList<DBTableEntry> tableStruct) { validateDirStructure(); createEnumFile(tableEntry.tableName, tableStruct); createTableFile(tableEntry, tableStruct); } private void createFiles(ResultSetMetaData metaData, final TableMapEntry tableEntry) throws SQLException { ArrayList<DBTableEntry> tableStruct = new ArrayList<DBTableEntry>(); for (int i = 1; i <= metaData.getColumnCount(); i++) { String columnName = metaData.getColumnName(i); try { TABLE_ENTRY_TYPE dbType = SQLTypeHelper.mapSQLType(metaData.getColumnType(i)); DBTableEntry.DBFlag dbFlag = getDBFlag(tableEntry.tableName, metaData, i); tableStruct.add(new DBTableEntry(columnName, dbType, dbFlag)); } catch (RuntimeException ex) { Logger.getLogger(TableGenerator.class.getName()).log(Level.SEVERE, ex.getMessage() + "for column: " + columnName, ex); System.exit(-1); } } createFiles(tableEntry, tableStruct); } private void createEnumFile(String tableName, ArrayList<DBTableEntry> tableStruct) { StringBuilder content = new StringBuilder(); String className = getFieldClassName(tableName); content.append(TableStrings.header) .append(getPackageContent(tablePackage)) .append("\n\npublic enum ") .append(className) .append("{\n\n") .append(INDENTATION); boolean firstEntry = true; for (DBTableEntry dBTableEntry : tableStruct) { if (firstEntry) { firstEntry = false; } else { content.append(", "); } content.append(dBTableEntry.dbTypeName); } content.append("\n}\n"); try { fh.writeToFile(rootPath + tableSubPath + "/" + className + ".java", content.toString()); } catch (IOException ex) { Logger.getLogger(TableGenerator.class.getName()).log(Level.SEVERE, null, ex); } } private String getFieldClassName(String tableName) { String className = getBasicClassName(tableName) + "Fields"; return className; } public static final String INDENTATION = " "; private String getPackageContent(String TABLE_PACKAGE) { return "\n\n\npackage " + TABLE_PACKAGE + ";\n\n"; } private String getBasicClassName(String tableName) { return tableName.toUpperCase(); } private void createTableFile(TableMapEntry tableEntry, ArrayList<DBTableEntry> tableStruct) { StringBuilder content = new StringBuilder(); String className = getBasicClassName(tableEntry.tableName) + "Table"; String fieldClassName = getFieldClassName(tableEntry.tableName); content.append(TableStrings.header) .append(getPackageContent(tablePackage)) .append(getTableImports(tableEntry)); content.append("\n\npublic class ") .append(className) .append(" extends Table<") .append(tableEntry.dataStructureName) .append(", ") .append(fieldClassName) .append("> {\n\n") .append(INDENTATION) .append("public ") .append(className) .append("() {\n") .append(INDENTATION).append(INDENTATION) .append("super(new StrictSITEnumMap(") .append(fieldClassName) .append(".class,\n").append(INDENTATION).append(INDENTATION).append(INDENTATION) .append("new TableEntry[]{\n\n"); boolean firstEntry = true; for (DBTableEntry dBTableEntry : tableStruct) { if (firstEntry) { firstEntry = false; } else { content.append(", \n\n"); } content.append(createTableTableEntry(fieldClassName, tableEntry, tableStruct, dBTableEntry)); } content .append(" }));\n }\n\n @Override\n public String getTableName() {\n return \"") .append(tableEntry.tableName) .append("\";\n }\n\n @Override\n protected ") .append(tableEntry.dataStructureName) .append(" createNewInstance() {\n return new ") .append(tableEntry.dataStructureName) .append("();\n }") .append("\n}\n"); try { fh.writeToFile(rootPath + tableSubPath + "/" + className + ".java", content.toString()); } catch (IOException ex) { Logger.getLogger(TableGenerator.class.getName()).log(Level.SEVERE, null, ex); } } private String getTableImports(TableMapEntry tableEntry) { return TableStrings.imports + "import " + tableEntry.dataStructurePackage + "." + tableEntry.dataStructureName + ";\n\n"; } private String createTableTableEntry(String fieldClassName, TableMapEntry tableEntry, ArrayList<DBTableEntry> tableStruct, DBTableEntry dBTableEntry) { StringBuilder result = new StringBuilder(); result.append(INDENTATION + INDENTATION + "new TableEntry(") .append(fieldClassName) .append(".") .append(dBTableEntry.dbTypeName) .append(", \"") .append(dBTableEntry.name) .append("\", TABLE_ENTRY_TYPE.") .append(dBTableEntry.dbType.toString()) .append(", new Mapper<") .append(tableEntry.dataStructureName) .append(">() {\n\n") .append(createGetter(fieldClassName, tableEntry, tableStruct, dBTableEntry)) .append("\n\n") .append(createSetter(fieldClassName, tableEntry, tableStruct, dBTableEntry)) .append("\n\n }") .append(getPrimKeyParam(dBTableEntry)) .append(")"); return result.toString(); } private String createGetter(String fieldClassName, TableMapEntry tableEntry, ArrayList<DBTableEntry> tableStruct, DBTableEntry dBTableEntry) { StringBuilder result = new StringBuilder(); result.append(INDENTATION + INDENTATION + INDENTATION + "@Override\n") .append(INDENTATION + INDENTATION + INDENTATION + "public ") .append(dBTableEntry.javaTypeName) .append(" get").append(dBTableEntry.javaGetSetStub) .append("(").append(tableEntry.dataStructureName) .append(" dataStructureEntry) {\n return dataStructureEntry.") .append(tableEntry.guessGetterForDBEntry(dBTableEntry.name)) .append("();\n }\n"); return result.toString(); } private String createSetter(String fieldClassName, TableMapEntry tableEntry, ArrayList<DBTableEntry> tableStruct, DBTableEntry dBTableEntry) { StringBuilder result = new StringBuilder(); result.append(INDENTATION + INDENTATION + INDENTATION + "@Override\n") .append(INDENTATION + INDENTATION + INDENTATION + "public void ") .append("set").append(dBTableEntry.javaGetSetStub) .append("(").append(tableEntry.dataStructureName) .append(" dataStructureEntry, ") .append(dBTableEntry.javaTypeName) .append(" value) {\n dataStructureEntry.") .append(tableEntry.guessSetterForDBEntry(dBTableEntry.name)) .append("(value);\n }\n"); return result.toString(); } private Object getPrimKeyParam(DBTableEntry dBTableEntry) { if (dBTableEntry.flag.flagValue != 0) { return ", " + dBTableEntry.flag.flagString; } return ""; } private DBTableEntry.DBFlag getDBFlag(String tableName, ResultSetMetaData metaData, int i) throws SQLException { boolean primKey = isPrimKey(tableName, metaData.getColumnName(i)); if (primKey) { if (metaData.isAutoIncrement(i)) { return new DBTableEntry.DBFlag("TableEntry.PRIMKEY_AUTOGEN", TableEntry.PRIMKEY_AUTOGEN); } else { return new DBTableEntry.DBFlag("TableEntry.PRIMKEY", TableEntry.PRIMKEY); } } return new DBTableEntry.DBFlag(null, 0); } private boolean isPrimKey(String tableName, String columnName) throws SQLException { ResultSet rs = databaseMetaData.getPrimaryKeys(null, null, tableName); try { while (rs.next()) { if (rs.getString("COLUMN_NAME").equals(columnName)) { return true; } } } finally { rs.close(); } return false; } }