aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJames Moger <james.moger@gmail.com>2011-08-04 14:10:59 -0400
committerJames Moger <james.moger@gmail.com>2011-08-04 14:10:59 -0400
commit3d1e36c31e2a8354e03cdfe12565503190c2e957 (patch)
treec81ed9b643c7f787f983e6199d352cf11b26a32f /src
parentd32c1f4d1eccbe0b9dd7c557d52879c8ec01069a (diff)
downloadiciql-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.java18
-rw-r--r--src/com/iciql/DbUpgrader.java4
-rw-r--r--src/com/iciql/Iciql.java85
-rw-r--r--src/com/iciql/TableDefinition.java72
-rw-r--r--src/com/iciql/TableInspector.java105
-rw-r--r--src/com/iciql/util/StatementBuilder.java8
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.