提交 dd69b685 authored 作者: Thomas Mueller's avatar Thomas Mueller

Cleanup:

- Only one space after a period (using two spaces is last century).
- Rename dateClass to dateTimeClass
- Rename *Clazz to *Class
- Use more appropriate method names ("find" for me implies the method might return null)
- Add missing Javadoc comments
- Java field names can end with *Value, but *_value isn't Java style
- Use appropriate variable names ("cn" isn't, "lower" is)
- Use more appropriate method names (getClassForSqlType versus getClassType, createClassName versus convertTableToClassName, createFieldName versus convertColumnToFieldName) 
上级 0f65e0a5
......@@ -19,35 +19,33 @@ import org.h2.jaqu.util.Utils;
/**
* Class to inspect a model and a database for the purposes of model validation
* and automatic model generation. This class finds the available schemas and
* and automatic model generation. This class finds the available schemas and
* tables and serves as the entry point for model generation and validation.
*/
public class DbInspector {
private Db db;
private DatabaseMetaData metaData;
private Class<? extends java.util.Date> dateClass = java.util.Date.class;
private int todoReviewWholeClass;
private Class<? extends java.util.Date> dateTimeClass = java.util.Date.class;
public DbInspector(Db db) {
this.db = db;
}
/**
* Set the preferred Date class. Possible values are: java.util.Date
* (default), java.sql.Date, java.sql.Timestamp.
* Set the preferred class to store date and time. Possible values are:
* java.util.Date (default) and java.sql.Timestamp.
*
* @param dateClass the new date class
* @param dateTimeClass the new class
*/
public void setPreferredDateClass(Class<? extends java.util.Date> dateClass) {
this.dateClass = dateClass;
public void setPreferredDateTimeClass(Class<? extends java.util.Date> dateTimeClass) {
this.dateTimeClass = dateTimeClass;
}
/**
* Generates models class skeletons for schemas and tables. If the table
* Generates models class skeletons for schemas and tables. If the table
* name is undefined, models will be generated for every table within the
* specified schema. Additionally, if no schema is defined, models will be
* specified schema. Additionally, if no schema is defined, models will be
* generated for all schemas and all tables.
*
* @param schema the schema name (optional)
......@@ -61,7 +59,7 @@ public class DbInspector {
String packageName, boolean annotateSchema, boolean trimStrings) {
try {
List<String> models = Utils.newArrayList();
List<TableInspector> tables = findTables(schema, table);
List<TableInspector> tables = getTables(schema, table);
for (TableInspector t : tables) {
t.read(metaData);
String model = t.generateModel(packageName, annotateSchema,
......@@ -78,13 +76,13 @@ public class DbInspector {
* Validates a model.
*
* @param <T> the model class
* @param model and instance of the model class
* @param throwOnError
* @return
* @param model an instance of the model class
* @param throwOnError if errors should cause validation to fail
* @return a list of validation remarks
*/
public <T> List<ValidationRemark> validateModel(T model, boolean throwOnError) {
try {
TableInspector inspector = findTable(model);
TableInspector inspector = getTable(model);
inspector.read(metaData);
@SuppressWarnings("unchecked")
Class<T> clazz = (Class<T>) model.getClass();
......@@ -103,14 +101,13 @@ public class DbInspector {
}
/**
* Attempts to find a table in the database based on the model definition.
* Get the table in the database based on the model definition.
*
* @param <T>
* @param model
* @return
* @throws SQLException
* @param <T> the model class
* @param model an instance of the model class
* @return the table inspector
*/
private <T> TableInspector findTable(T model) throws SQLException {
private <T> TableInspector getTable(T model) throws SQLException {
@SuppressWarnings("unchecked")
Class<T> clazz = (Class<T>) model.getClass();
TableDefinition<T> def = db.define(clazz);
......@@ -118,18 +115,19 @@ public class DbInspector {
String schema = (forceUpperCase && def.schemaName != null) ?
def.schemaName.toUpperCase() : def.schemaName;
String table = forceUpperCase ? def.tableName.toUpperCase() : def.tableName;
List<TableInspector> tables = findTables(schema, table);
List<TableInspector> tables = getTables(schema, table);
return tables.get(0);
}
/**
* Returns a list of tables
* Returns a list of tables. This method always returns at least one element.
* If no table is found, an exception is thrown.
*
* @param schema the schema name
* @param table the table name
* @return a list of table inspectors
* @return a list of table inspectors (always contains at least one element)
*/
private List<TableInspector> findTables(String schema, String table) throws SQLException {
private List<TableInspector> getTables(String schema, String table) throws SQLException {
ResultSet rs = null;
try {
rs = getMetaData().getSchemas();
......@@ -139,7 +137,6 @@ public class DbInspector {
}
JdbcUtils.closeSilently(rs);
// get JaQu Tables table name.
String jaquTables = DbVersion.class.getAnnotation(JQTable.class).name();
List<TableInspector> tables = Utils.newArrayList();
......@@ -151,9 +148,8 @@ public class DbInspector {
while (rs.next()) {
String t = rs.getString("TABLE_NAME");
if (!t.equalsIgnoreCase(jaquTables)) {
// Ignore JaQu versions table
tables.add(new TableInspector(s, t,
getMetaData().storesUpperCaseIdentifiers(), dateClass));
getMetaData().storesUpperCaseIdentifiers(), dateTimeClass));
}
}
}
......
......@@ -15,6 +15,7 @@ import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.h2.jaqu.TableDefinition.FieldDefinition;
import org.h2.util.StringUtils;
/**
* Utility methods for models related to type mapping, default value validation,
......@@ -115,7 +116,7 @@ public class ModelUtils {
* @param strictTypeMapping throws a RuntimeException if type is unsupported
* @return
*/
public static String getDataType(FieldDefinition fieldDef, boolean strictTypeMapping) {
static String getDataType(FieldDefinition fieldDef, boolean strictTypeMapping) {
Class<?> fieldClass = fieldDef.field.getType();
if (SUPPORTED_TYPES.containsKey(fieldClass)) {
String type = SUPPORTED_TYPES.get(fieldClass);
......@@ -132,15 +133,15 @@ public class ModelUtils {
}
/**
* Returns the Java class type for a given SQL type.
* Returns the Java class for a given SQL type.
*
* @param sqlType
* @param dateClass the preferred date class (java.util.Date or
* @param dateTimeClass the preferred date class (java.util.Date or
* java.sql.Timestamp)
* @return
*/
public static Class<?> getClassType(String sqlType,
Class<? extends java.util.Date> dateClass) {
static Class<?> getClassForSqlType(String sqlType,
Class<? extends java.util.Date> dateTimeClass) {
sqlType = sqlType.toUpperCase();
// TODO dropping "UNSIGNED" or parts like that could be trouble
sqlType = sqlType.split(" ")[0].trim();
......@@ -149,64 +150,64 @@ public class ModelUtils {
// convert the sqlType to a standard type
sqlType = SQL_TYPES.get(sqlType);
}
Class<?> mappedClazz = null;
Class<?> mappedClass = null;
for (Class<?> clazz : SUPPORTED_TYPES.keySet()) {
if (SUPPORTED_TYPES.get(clazz).equalsIgnoreCase(sqlType)) {
mappedClazz = clazz;
mappedClass = clazz;
break;
}
}
if (mappedClazz != null) {
if (mappedClazz.equals(java.util.Date.class)
|| mappedClazz.equals(java.sql.Timestamp.class)) {
return dateClass;
if (mappedClass != null) {
if (mappedClass.equals(java.util.Date.class)
|| mappedClass.equals(java.sql.Timestamp.class)) {
return dateTimeClass;
}
return mappedClazz;
return mappedClass;
}
return null;
}
/**
* Tries to create a CamelCase class name from a table.
* Tries to create a convert a SQL table name to a camel case class name.
*
* @param name
* @return
* @param tableName the SQL table name
* @return the class name
*/
public static String createClassName(String name) {
String[] chunks = name.split("_");
StringBuilder newName = new StringBuilder();
static String convertTableToClassName(String tableName) {
String[] chunks = StringUtils.arraySplit(tableName, '_', false);
StringBuilder className = new StringBuilder();
for (String chunk : chunks) {
if (chunk.length() == 0) {
// leading or trailing _
continue;
}
newName.append(Character.toUpperCase(chunk.charAt(0)));
newName.append(chunk.substring(1).toLowerCase());
className.append(Character.toUpperCase(chunk.charAt(0)));
className.append(chunk.substring(1).toLowerCase());
}
return newName.toString();
return className.toString();
}
/**
* Ensures that table column names don't collide with Java keywords.
* Ensures that SQL column names don't collide with Java keywords.
*
* @param col
* @return
* @param columnName the column name
* @return the Java field name
*/
public static String createFieldName(String col) {
String cn = col.toLowerCase();
if (KEYWORDS.contains(cn)) {
cn += "_value";
static String convertColumnToFieldName(String columnName) {
String lower = columnName.toLowerCase();
if (KEYWORDS.contains(lower)) {
lower += "Value";
}
return cn;
return lower;
}
/**
* Checks the formatting of JQColumn.defaultValue()
* Checks the formatting of JQColumn.defaultValue().
*
* @param defaultValue
* @return
* @param defaultValue the default value
* @return true if it is
*/
public static boolean isProperlyFormattedDefaultValue(String defaultValue) {
static boolean isProperlyFormattedDefaultValue(String defaultValue) {
if (isNullOrEmpty(defaultValue)) {
return true;
}
......@@ -217,13 +218,13 @@ public class ModelUtils {
}
/**
* Checks to see if the defaultValue matches the Class.
* Checks to see if the default value matches the class.
*
* @param modelClazz
* @param defaultValue
* @return
* @param modelClass the class
* @param defaultValue the value
* @return true if it does
*/
public static boolean isValidDefaultValue(Class<?> modelClazz,
static boolean isValidDefaultValue(Class<?> modelClass,
String defaultValue) {
if (defaultValue == null) {
......@@ -248,7 +249,7 @@ public class ModelUtils {
}
// STRING
if (modelClazz == String.class) {
if (modelClass == String.class) {
Pattern stringDefault = Pattern.compile("'(.|\\n)*'");
return stringDefault.matcher(defaultValue).matches();
}
......@@ -257,8 +258,8 @@ public class ModelUtils {
String timeRegex = "[0-2]{1}[0-9]{1}:[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}";
// TIMESTAMP
if (modelClazz == java.util.Date.class
|| modelClazz == java.sql.Timestamp.class) {
if (modelClass == java.util.Date.class
|| modelClass == java.sql.Timestamp.class) {
// this may be a little loose....
// 00-00-00 00:00:00
// 00/00/00T00:00:00
......@@ -268,7 +269,7 @@ public class ModelUtils {
}
// DATE
if (modelClazz == java.sql.Date.class) {
if (modelClass == java.sql.Date.class) {
// this may be a little loose....
// 00-00-00
// 00/00/00
......@@ -278,14 +279,14 @@ public class ModelUtils {
}
// TIME
if (modelClazz == java.sql.Time.class) {
if (modelClass == java.sql.Time.class) {
// 00:00:00
Pattern pattern = Pattern.compile("'" + timeRegex + "'");
return pattern.matcher(defaultValue).matches();
}
// NUMBER
if (Number.class.isAssignableFrom(modelClazz)) {
if (Number.class.isAssignableFrom(modelClass)) {
// strip single quotes
String unquoted = defaultValue;
if (unquoted.charAt(0) == '\'') {
......@@ -297,7 +298,7 @@ public class ModelUtils {
try {
// delegate to static valueOf() method to parse string
Method m = modelClazz.getMethod("valueOf", String.class);
Method m = modelClass.getMethod("valueOf", String.class);
Object o = m.invoke(null, unquoted);
} catch (NumberFormatException ex) {
return false;
......
......@@ -60,7 +60,7 @@ public interface SQLDialect {
/**
* Default implementation of an SQL dialect.
* Designed for an H2 database. May be suitable for others.
* Designed for an H2 database, and may be suitable for others.
*/
public static class DefaultSQLDialect implements SQLDialect {
......
......@@ -219,8 +219,8 @@ class TableDefinition<T> {
List<Field> classFields = Utils.newArrayList();
classFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
if (inheritColumns) {
Class<?> superClazz = clazz.getSuperclass();
classFields.addAll(Arrays.asList(superClazz.getDeclaredFields()));
Class<?> superClass = clazz.getSuperclass();
classFields.addAll(Arrays.asList(superClass.getDeclaredFields()));
}
for (Field f : classFields) {
......
......@@ -44,18 +44,18 @@ public class TableInspector {
private String schema;
private String table;
private boolean forceUpperCase;
private Class<? extends java.util.Date> dateClazz;
private Class<? extends java.util.Date> dateTimeClass;
private List<String> primaryKeys = Utils.newArrayList();
private Map<String, IndexInspector> indexes;
private Map<String, ColumnInspector> columns;
private final String eol = "\n";
TableInspector(String schema, String table, boolean forceUpperCase,
Class<? extends java.util.Date> dateClazz) {
Class<? extends java.util.Date> dateTimeClass) {
this.schema = schema;
this.table = table;
this.forceUpperCase = forceUpperCase;
this.dateClazz = dateClazz;
this.dateTimeClass = dateTimeClass;
}
/**
......@@ -122,7 +122,7 @@ public class TableInspector {
ColumnInspector col = new ColumnInspector();
col.name = rs.getString("COLUMN_NAME");
col.type = rs.getString("TYPE_NAME");
col.clazz = ModelUtils.getClassType(col.type, dateClazz);
col.clazz = ModelUtils.getClassForSqlType(col.type, dateTimeClass);
col.size = rs.getInt("COLUMN_SIZE");
col.allowNull = rs.getInt("NULLABLE") == DatabaseMetaData.columnNullable;
col.isAutoIncrement = rs.getBoolean("IS_AUTOINCREMENT");
......@@ -235,7 +235,7 @@ public class TableInspector {
}
// class declaration
String clazzName = ModelUtils.createClassName(table);
String clazzName = ModelUtils.convertTableToClassName(table);
model.append(format("public class {0} '{'", clazzName)).append(eol);
model.append(eol);
......@@ -288,7 +288,7 @@ public class TableInspector {
boolean trimStrings) {
StatementBuilder sb = new StatementBuilder();
Class<?> clazz = col.clazz;
String column = ModelUtils.createFieldName(col.name.toLowerCase());
String column = ModelUtils.convertColumnToFieldName(col.name.toLowerCase());
sb.append('\t');
if (clazz == null) {
// unsupported type
......@@ -426,7 +426,7 @@ public class TableInspector {
}
/**
* Validates a column against the model's field definition. Checks for
* Validates a column against the model's field definition. Checks for
* existence, supported type, type mapping, default value, defined lengths,
* primary key, autoincrement.
*/
......@@ -442,34 +442,34 @@ public class TableInspector {
return;
}
ColumnInspector col = columns.get(field);
Class<?> fieldClazz = fieldDef.field.getType();
Class<?> jdbcClazz = ModelUtils.getClassType(col.type, dateClazz);
Class<?> fieldClass = fieldDef.field.getType();
Class<?> jdbcClass = ModelUtils.getClassForSqlType(col.type, dateTimeClass);
// supported type check
// JaQu maps to VARCHAR for unsupported types.
if (fieldDef.dataType.equals("VARCHAR")
&& (fieldClazz != String.class)) {
&& (fieldClass != String.class)) {
remarks.add(error(table, fieldDef,
"JaQu does not currently implement support for "
+ fieldClazz.getName()).throwError(throwError));
+ fieldClass.getName()).throwError(throwError));
}
// number types
if (!fieldClazz.equals(jdbcClazz)) {
if (Number.class.isAssignableFrom(fieldClazz)) {
if (!fieldClass.equals(jdbcClass)) {
if (Number.class.isAssignableFrom(fieldClass)) {
remarks.add(warn(table, col,
format("Precision mismatch: ModelObject={0}, ColumnObject={1}",
fieldClazz.getSimpleName(), jdbcClazz.getSimpleName())));
fieldClass.getSimpleName(), jdbcClass.getSimpleName())));
} else {
if (!Date.class.isAssignableFrom(jdbcClazz)) {
if (!Date.class.isAssignableFrom(jdbcClass)) {
remarks.add(warn(table, col,
format("Object Mismatch: ModelObject={0}, ColumnObject={1}",
fieldClazz.getSimpleName(), jdbcClazz.getSimpleName())));
fieldClass.getSimpleName(), jdbcClass.getSimpleName())));
}
}
}
// string types
if (fieldClazz == String.class) {
if (fieldClass == String.class) {
if ((fieldDef.maxLength != col.size)
&& (col.size < Integer.MAX_VALUE)) {
remarks.add(warn(table, col,
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论