diff options
author | James Moger <james.moger@gmail.com> | 2011-08-04 14:10:59 -0400 |
---|---|---|
committer | James Moger <james.moger@gmail.com> | 2011-08-04 14:10:59 -0400 |
commit | 3d1e36c31e2a8354e03cdfe12565503190c2e957 (patch) | |
tree | c81ed9b643c7f787f983e6199d352cf11b26a32f /src | |
parent | d32c1f4d1eccbe0b9dd7c557d52879c8ec01069a (diff) | |
download | iciql-3d1e36c31e2a8354e03cdfe12565503190c2e957.tar.gz iciql-3d1e36c31e2a8354e03cdfe12565503190c2e957.zip |
Overhauling annotations.
* @IQSchema(name="public") -> @IQSchema("public")
* @IQDatabase(version=2) -> @IQVersion(2)
* @IQTable(version=2) -> @IQVersion(2)
* @IQIndex annotation simplified to be used for one index definition and
expanded to specify index name
* added @IQIndexes annotation to specify multiple IQIndex annotations
Diffstat (limited to 'src')
-rw-r--r-- | src/com/iciql/Db.java | 18 | ||||
-rw-r--r-- | src/com/iciql/DbUpgrader.java | 4 | ||||
-rw-r--r-- | src/com/iciql/Iciql.java | 85 | ||||
-rw-r--r-- | src/com/iciql/TableDefinition.java | 72 | ||||
-rw-r--r-- | src/com/iciql/TableInspector.java | 105 | ||||
-rw-r--r-- | src/com/iciql/util/StatementBuilder.java | 8 |
6 files changed, 152 insertions, 140 deletions
diff --git a/src/com/iciql/Db.java b/src/com/iciql/Db.java index 3f86d15..f70a37e 100644 --- a/src/com/iciql/Db.java +++ b/src/com/iciql/Db.java @@ -34,7 +34,7 @@ import java.util.Set; import javax.sql.DataSource;
import com.iciql.DbUpgrader.DefaultDbUpgrader;
-import com.iciql.Iciql.IQDatabase;
+import com.iciql.Iciql.IQVersion;
import com.iciql.Iciql.IQTable;
import com.iciql.SQLDialect.DefaultSQLDialect;
import com.iciql.SQLDialect.H2Dialect;
@@ -230,8 +230,8 @@ public class Db { // flag as checked immediately because calls are nested.
upgradeChecked.add(dbUpgrader.getClass());
- IQDatabase model = dbUpgrader.getClass().getAnnotation(IQDatabase.class);
- if (model.version() > 0) {
+ IQVersion model = dbUpgrader.getClass().getAnnotation(IQVersion.class);
+ if (model.value() > 0) {
DbVersion v = new DbVersion();
DbVersion dbVersion =
// (SCHEMA="" && TABLE="") == DATABASE
@@ -239,17 +239,17 @@ public class Db { if (dbVersion == null) {
// database has no version registration, but model specifies
// version: insert DbVersion entry and return.
- DbVersion newDb = new DbVersion(model.version());
+ DbVersion newDb = new DbVersion(model.value());
insert(newDb);
} else {
// database has a version registration:
// check to see if upgrade is required.
- if ((model.version() > dbVersion.version) && (dbUpgrader != null)) {
+ if ((model.value() > dbVersion.version) && (dbUpgrader != null)) {
// database is an older version than the model
boolean success = dbUpgrader
- .upgradeDatabase(this, dbVersion.version, model.version());
+ .upgradeDatabase(this, dbVersion.version, model.value());
if (success) {
- dbVersion.version = model.version();
+ dbVersion.version = model.value();
update(dbVersion);
}
}
@@ -316,8 +316,8 @@ public class Db { }
public synchronized void setDbUpgrader(DbUpgrader upgrader) {
- if (!upgrader.getClass().isAnnotationPresent(IQDatabase.class)) {
- throw new IciqlException("DbUpgrader must be annotated with " + IQDatabase.class.getSimpleName());
+ if (!upgrader.getClass().isAnnotationPresent(IQVersion.class)) {
+ throw new IciqlException("DbUpgrader must be annotated with " + IQVersion.class.getSimpleName());
}
this.dbUpgrader = upgrader;
upgradeChecked.clear();
diff --git a/src/com/iciql/DbUpgrader.java b/src/com/iciql/DbUpgrader.java index c4ab36b..1303f4e 100644 --- a/src/com/iciql/DbUpgrader.java +++ b/src/com/iciql/DbUpgrader.java @@ -17,7 +17,7 @@ package com.iciql; -import com.iciql.Iciql.IQDatabase; +import com.iciql.Iciql.IQVersion; /** * Interface which defines a class to handle table changes based on model @@ -65,7 +65,7 @@ public interface DbUpgrader { * The default database upgrader. It throws runtime exception instead of * handling upgrade requests. */ - @IQDatabase(version = 0) + @IQVersion(0) public static class DefaultDbUpgrader implements DbUpgrader { public boolean upgradeDatabase(Db db, int fromVersion, int toVersion) { diff --git a/src/com/iciql/Iciql.java b/src/com/iciql/Iciql.java index 7267d33..35ad8cc 100644 --- a/src/com/iciql/Iciql.java +++ b/src/com/iciql/Iciql.java @@ -140,11 +140,13 @@ import java.lang.annotation.Target; public interface Iciql {
/**
- * An annotation for a database.
+ * An annotation for an iciql version.
+ * <p>
+ * @IQVersion(1)
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
- public @interface IQDatabase {
+ public @interface IQVersion {
/**
* If set to a non-zero value, iciql maintains a "_iq_versions" table
@@ -153,12 +155,14 @@ public interface Iciql { * statements. Default: 0. You must specify a DbUpgrader on your Db
* object to use this parameter.
*/
- int version() default 0;
+ int value() default 0;
}
/**
* An annotation for a schema.
+ * <p>
+ * @IQSchema("PUBLIC")
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@@ -167,7 +171,7 @@ public interface Iciql { /**
* The schema may be optionally specified. Default: unspecified.
*/
- String name() default "";
+ String value() default "";
}
@@ -180,58 +184,54 @@ public interface Iciql { /**
* An index annotation.
+ * <p>
+ * <ul>
+ * <li>@IQIndex("name")
+ * <li>@IQIndex({"street", "city"})
+ * <li>@IQIndex(name="streetidx", value={"street", "city"})
+ * <li>@IQIndex(name="addressidx", type=IndexType.UNIQUE, value={"house_number", "street", "city"})
+ * </ul>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface IQIndex {
/**
- * Standard indexes may be optionally specified.
- * <ul>
- * <li>standard = "id, name"</li>
- * <li>standard = "id name"</li>
- * <li>standard = { "id name", "date" }</li>
- * </ul>
- * Standard indexes may still be added in the define() method if the
- * model class is not annotated with IQTable. Default: unspecified.
+ * Index name. If null or empty, iciql will generate one.
*/
- String[] standard() default {};
+ String name() default "";
/**
- * Unique indexes may be optionally specified.
+ * Type of the index.
* <ul>
- * <li>unique = "id, name"</li>
- * <li>unique = "id name"</li>
- * <li>unique = { "id name", "date" }</li>
+ * <li>com.iciql.iciql.IndexType.STANDARD
+ * <li>com.iciql.iciql.IndexType.UNIQUE
+ * <li>com.iciql.iciql.IndexType.HASH
+ * <li>com.iciql.iciql.IndexType.UNIQUE_HASH
* </ul>
- * Unique indexes may still be added in the define() method if the model
- * class is not annotated with IQTable. Default: unspecified.
+ *
+ * HASH indexes may only be valid for single column indexes.
+ *
*/
- String[] unique() default {};
+ IndexType type() default IndexType.STANDARD;
/**
- * Hash indexes may be optionally specified.
+ * Columns to include in index.
* <ul>
- * <li>hash = "name"
- * <li>hash = { "name", "date" }
+ * <li>single column index: value = "id"
+ * <li>multiple column index: value = { "id", "name", "date" }
* </ul>
- * Hash indexes may still be added in the define() method if the model
- * class is not annotated with IQTable. Default: unspecified.
*/
- String[] hash() default {};
-
- /**
- * Unique hash indexes may be optionally specified.
- * <ul>
- * <li>uniqueHash = "id"
- * <li>uniqueHash = "name"
- * <li>uniqueHash = { "id", "name" }
- * </ul>
- * Unique hash indexes may still be added in the define() method if the
- * model class is not annotated with IQTable. Default: unspecified.
- */
- String[] uniqueHash() default {};
+ String[] value() default {};
+ }
+ /**
+ * Annotation to specify multiple indexes.
+ */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.TYPE)
+ public @interface IQIndexes {
+ IQIndex[] value() default {};
}
/**
@@ -295,15 +295,6 @@ public interface Iciql { * databases. Default: false.
*/
boolean memoryTable() default false;
-
- /**
- * If non-zero, iciql will maintain a "_iq_versions" table within your
- * database. The version number is used to call to a registered
- * DbUpgrader implementation to perform relevant ALTER statements.
- * Default: 0. You must specify a DbUpgrader on your Db object to use
- * this parameter.
- */
- int version() default 0;
}
/**
diff --git a/src/com/iciql/TableDefinition.java b/src/com/iciql/TableDefinition.java index 883ce33..456d0f4 100644 --- a/src/com/iciql/TableDefinition.java +++ b/src/com/iciql/TableDefinition.java @@ -27,11 +27,13 @@ import java.util.IdentityHashMap; import java.util.List;
import java.util.Map;
-import com.iciql.Iciql.IndexType;
import com.iciql.Iciql.IQColumn;
import com.iciql.Iciql.IQIndex;
+import com.iciql.Iciql.IQIndexes;
import com.iciql.Iciql.IQSchema;
import com.iciql.Iciql.IQTable;
+import com.iciql.Iciql.IQVersion;
+import com.iciql.Iciql.IndexType;
import com.iciql.util.StatementBuilder;
import com.iciql.util.StatementLogger;
import com.iciql.util.StringUtils;
@@ -133,9 +135,9 @@ class TableDefinition<T> { List<FieldDefinition> getFields() {
return fields;
}
-
+
FieldDefinition getField(String name) {
- for (FieldDefinition field:fields) {
+ for (FieldDefinition field : fields) {
if (field.columnName.equalsIgnoreCase(name)) {
return field;
}
@@ -199,7 +201,7 @@ class TableDefinition<T> { */
void addIndex(IndexType type, Object[] modelFields) {
List<String> columnNames = mapColumnNames(modelFields);
- addIndex(type, columnNames);
+ addIndex(null, type, columnNames);
}
/**
@@ -210,9 +212,13 @@ class TableDefinition<T> { * @param columnNames
* the ordered list of column names
*/
- void addIndex(IndexType type, List<String> columnNames) {
+ void addIndex(String name, IndexType type, List<String> columnNames) {
IndexDefinition index = new IndexDefinition();
- index.indexName = tableName + "_" + indexes.size();
+ if (StringUtils.isNullOrEmpty(name)) {
+ index.indexName = tableName + "_" + indexes.size();
+ } else {
+ index.indexName = name;
+ }
index.columnNames = Utils.newArrayList(columnNames);
index.type = type;
indexes.add(index);
@@ -376,7 +382,7 @@ class TableDefinition<T> { }
buff.append(')');
stat.setSQL(buff.toString());
-
+
StatementLogger.merge(stat.getSQL());
stat.executeUpdate();
}
@@ -524,10 +530,10 @@ class TableDefinition<T> { }
/**
- * Retrieve list of columns from index definition.
+ * Retrieve list of columns from primary key definition.
*
* @param index
- * the index columns, separated by space
+ * the primary key columns, separated by space
* @return the column list
*/
private List<String> getColumns(String index) {
@@ -554,8 +560,8 @@ class TableDefinition<T> { if (clazz.isAnnotationPresent(IQSchema.class)) {
IQSchema schemaAnnotation = clazz.getAnnotation(IQSchema.class);
// setup schema name mapping, if properly annotated
- if (!StringUtils.isNullOrEmpty(schemaAnnotation.name())) {
- schemaName = schemaAnnotation.name();
+ if (!StringUtils.isNullOrEmpty(schemaAnnotation.value())) {
+ schemaName = schemaAnnotation.value();
}
}
@@ -571,8 +577,11 @@ class TableDefinition<T> { createTableIfRequired = tableAnnotation.createIfRequired();
// model version
- if (tableAnnotation.version() > 0) {
- tableVersion = tableAnnotation.version();
+ if (clazz.isAnnotationPresent(IQVersion.class)) {
+ IQVersion versionAnnotation = clazz.getAnnotation(IQVersion.class);
+ if (versionAnnotation.value() > 0) {
+ tableVersion = versionAnnotation.value();
+ }
}
// setup the primary index, if properly annotated
@@ -583,34 +592,27 @@ class TableDefinition<T> { }
if (clazz.isAnnotationPresent(IQIndex.class)) {
- IQIndex indexAnnotation = clazz.getAnnotation(IQIndex.class);
-
- // setup the indexes, if properly annotated
- addIndexes(IndexType.STANDARD, indexAnnotation.standard());
- addIndexes(IndexType.UNIQUE, indexAnnotation.unique());
- addIndexes(IndexType.HASH, indexAnnotation.hash());
- addIndexes(IndexType.UNIQUE_HASH, indexAnnotation.uniqueHash());
+ // single table index
+ IQIndex index = clazz.getAnnotation(IQIndex.class);
+ addIndex(index);
}
- }
- void addIndexes(IndexType type, String[] indexes) {
- for (String index : indexes) {
- List<String> validatedColumns = getColumns(index);
- if (validatedColumns == null) {
- return;
+ if (clazz.isAnnotationPresent(IQIndexes.class)) {
+ // multiple table indexes
+ IQIndexes indexes = clazz.getAnnotation(IQIndexes.class);
+ for (IQIndex index : indexes.value()) {
+ addIndex(index);
}
- addIndex(type, validatedColumns);
}
}
- List<IndexDefinition> getIndexes(IndexType type) {
- List<IndexDefinition> list = Utils.newArrayList();
- for (IndexDefinition def : indexes) {
- if (def.type.equals(type)) {
- list.add(def);
- }
- }
- return list;
+ void addIndex(IQIndex index) {
+ List<String> columns = Arrays.asList(index.value());
+ addIndex(index.name(), index.type(), columns);
+ }
+
+ List<IndexDefinition> getIndexes() {
+ return indexes;
}
void initObject(Object obj, Map<Object, FieldDefinition> map) {
diff --git a/src/com/iciql/TableInspector.java b/src/com/iciql/TableInspector.java index f920315..8e537b4 100644 --- a/src/com/iciql/TableInspector.java +++ b/src/com/iciql/TableInspector.java @@ -23,6 +23,7 @@ import static com.iciql.ValidationRemark.warn; import static com.iciql.util.JdbcUtils.closeSilently; import static com.iciql.util.StringUtils.isNullOrEmpty; import static java.text.MessageFormat.format; + import java.lang.reflect.Modifier; import java.sql.DatabaseMetaData; import java.sql.ResultSet; @@ -34,14 +35,16 @@ import java.util.List; import java.util.Map; import java.util.Set; -import com.iciql.Iciql.IndexType; import com.iciql.Iciql.IQColumn; import com.iciql.Iciql.IQIndex; +import com.iciql.Iciql.IQIndexes; import com.iciql.Iciql.IQSchema; import com.iciql.Iciql.IQTable; +import com.iciql.Iciql.IndexType; import com.iciql.TableDefinition.FieldDefinition; import com.iciql.TableDefinition.IndexDefinition; import com.iciql.util.StatementBuilder; +import com.iciql.util.StringUtils; import com.iciql.util.Utils; /** @@ -175,8 +178,10 @@ public class TableInspector { Set<String> imports = Utils.newHashSet(); imports.add(IQSchema.class.getCanonicalName()); imports.add(IQTable.class.getCanonicalName()); + imports.add(IQIndexes.class.getCanonicalName()); imports.add(IQIndex.class.getCanonicalName()); - imports.add(IQColumn.class.getCanonicalName()); + imports.add(IQColumn.class.getCanonicalName()); + imports.add(IndexType.class.getCanonicalName()); // fields StringBuilder fields = new StringBuilder(); @@ -207,7 +212,7 @@ public class TableInspector { model.append('@').append(IQSchema.class.getSimpleName()); model.append('('); AnnotationBuilder ap = new AnnotationBuilder(); - ap.addParameter("name", schema); + ap.addParameter(null, schema); model.append(ap); model.append(')').append(eol); } @@ -233,17 +238,11 @@ public class TableInspector { model.append(ap); model.append(')').append(eol); + // @IQIndexes // @IQIndex - ap = new AnnotationBuilder(); - generateIndexAnnotations(ap, "standard", IndexType.STANDARD); - generateIndexAnnotations(ap, "unique", IndexType.UNIQUE); - generateIndexAnnotations(ap, "hash", IndexType.HASH); - generateIndexAnnotations(ap, "uniqueHash", IndexType.UNIQUE_HASH); - if (ap.length() > 0) { - model.append('@').append(IQIndex.class.getSimpleName()); - model.append('('); - model.append(ap); - model.append(')').append(eol); + String indexAnnotations = generateIndexAnnotations(); + if (!StringUtils.isNullOrEmpty(indexAnnotations)) { + model.append(indexAnnotations); } // class declaration @@ -269,32 +268,50 @@ public class TableInspector { * * @param ap */ - void generateIndexAnnotations(AnnotationBuilder ap, String parameter, IndexType type) { - List<IndexInspector> list = getIndexes(type); - if (list.size() == 0) { + String generateIndexAnnotations() { + if (indexes == null || indexes.size() == 0) { // no matching indexes - return; + return null; } - if (list.size() == 1) { - ap.addParameter(parameter, list.get(0).getColumnsString()); + AnnotationBuilder ap = new AnnotationBuilder(); + if (indexes.size() == 1) { + // single index + ap.append(generateIndexAnnotation(indexes.get(0))); + ap.append(eol); } else { - List<String> parameters = Utils.newArrayList(); - for (IndexInspector index : list) { - parameters.add(index.getColumnsString()); + // multiple indexes + ap.append('@').append(IQIndexes.class.getSimpleName()); + ap.append("({"); + ap.resetCount(); + for (IndexInspector index : indexes.values()) { + ap.appendExceptFirst(", "); + ap.append(generateIndexAnnotation(index)); } - ap.addParameter(parameter, parameters); + ap.append("})").append(eol); } - + return ap.toString(); } - private List<IndexInspector> getIndexes(IndexType type) { - List<IndexInspector> list = Utils.newArrayList(); - for (IndexInspector index : indexes.values()) { - if (index.type.equals(type)) { - list.add(index); - } + private String generateIndexAnnotation(IndexInspector index) { + AnnotationBuilder ap = new AnnotationBuilder(); + ap.append('@').append(IQIndex.class.getSimpleName()); + ap.append('('); + ap.resetCount(); + if (!StringUtils.isNullOrEmpty(index.name)) { + ap.addParameter("name", index.name); + } + if (!index.type.equals(IndexType.STANDARD)) { + ap.addParameter("type", IndexType.class.getSimpleName() + "." + index.type.name()); + } + if (ap.getCount() > 0) { + // multiple fields specified + ap.addParameter("values", index.columns); + } else { + // default value + ap.addParameter(null, index.columns); } - return list; + ap.append(')'); + return ap.toString(); } private StatementBuilder generateColumn(Set<String> imports, ColumnInspector col, boolean trimStrings) { @@ -424,11 +441,10 @@ public class TableInspector { */ private <T> void validate(List<ValidationRemark> remarks, TableDefinition<T> def, IndexInspector index, boolean throwError) { - List<IndexDefinition> defIndexes = def.getIndexes(IndexType.STANDARD); - List<IndexInspector> dbIndexes = getIndexes(IndexType.STANDARD); - if (defIndexes.size() > dbIndexes.size()) { + List<IndexDefinition> defIndexes = def.getIndexes(); + if (defIndexes.size() > indexes.size()) { remarks.add(warn(table, IndexType.STANDARD.name(), "More model indexes than database indexes")); - } else if (defIndexes.size() < dbIndexes.size()) { + } else if (defIndexes.size() < indexes.size()) { remarks.add(warn(table, IndexType.STANDARD.name(), "Model class is missing indexes")); } // TODO complete index validation. @@ -583,15 +599,6 @@ public class TableInspector { public void addColumn(ResultSet rs) throws SQLException { columns.add(rs.getString("COLUMN_NAME")); } - - public String getColumnsString() { - StatementBuilder sb = new StatementBuilder(); - for (String col : columns) { - sb.appendExceptFirst(", "); - sb.append(col); - } - return sb.toString().trim(); - } } /** @@ -629,19 +636,23 @@ public class TableInspector { * parameter list. */ private static class AnnotationBuilder extends StatementBuilder { + AnnotationBuilder() { super(); } void addParameter(String parameter) { + appendExceptFirst(", "); append(parameter); } <T> void addParameter(String parameter, T value) { appendExceptFirst(", "); - append(parameter); - append('='); + if (!StringUtils.isNullOrEmpty(parameter)) { + append(parameter); + append('='); + } if (value instanceof List) { append("{ "); List<?> list = (List<?>) value; @@ -663,7 +674,7 @@ public class TableInspector { if (value instanceof String) { append('\"'); } - // TODO escape + // TODO escape append(value.toString().trim()); if (value instanceof String) { append('\"'); diff --git a/src/com/iciql/util/StatementBuilder.java b/src/com/iciql/util/StatementBuilder.java index c2974ae..65c0679 100644 --- a/src/com/iciql/util/StatementBuilder.java +++ b/src/com/iciql/util/StatementBuilder.java @@ -99,6 +99,14 @@ public class StatementBuilder { builder.append(x); return this; } + + /** + * Returns the current value of the loop counter. + * @return the loop counter + */ + public int getCount() { + return index; + } /** * Reset the loop counter. |