From: James Moger Date: Mon, 6 Oct 2014 16:46:50 +0000 (-0400) Subject: Support generic types for EnumId mapping X-Git-Tag: v1.3.0~7 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=6889aa2e367d4658105c1bc2514afccb425770f3;p=iciql.git Support generic types for EnumId mapping --- diff --git a/releases.moxie b/releases.moxie index 10bf70f..b81afc4 100644 --- a/releases.moxie +++ b/releases.moxie @@ -5,7 +5,7 @@ r21: { title: ${project.name} ${project.version} released id: ${project.version} date: ${project.buildDate} - note: ~ + note: "If you are upgrading and using EnumId mapping you will have to update your models to define the target class for the enumid mapping." html: ~ text: ~ security: ~ @@ -13,11 +13,13 @@ r21: { - Return null NPE in selectFirst() if list is empty (pr-5) - Fix Moxie toolkit download URL (pr-6) - Be more careful with primitive numeric type rollovers - changes: ~ + changes: + - Revised EnumId interface to support generic types additions: - Add syntax for IN and NOT IN (pr-7) - Add support for nested AND/OR conditions (pr-8) - Add support for mapping SQL BOOLEAN to primitive numeric types, not just object numeric types + - Add support for customizing EnumId mapping, you can now map enum constants to values of your choice as long as they are a standard type dependencyChanges: - H2 1.4 - HSQLDB 2.3 diff --git a/src/main/java/com/iciql/Iciql.java b/src/main/java/com/iciql/Iciql.java index 9f73ffa..521e460 100644 --- a/src/main/java/com/iciql/Iciql.java +++ b/src/main/java/com/iciql/Iciql.java @@ -171,7 +171,7 @@ import java.lang.annotation.Target; *

* Automatic model generation: you may automatically generate model classes as * strings with the Db and DbInspector objects: - * + * *

  * Db db = Db.open("jdbc:h2:mem:", "sa", "sa");
  * DbInspector inspector = new DbInspector(db);
@@ -179,10 +179,10 @@ import java.lang.annotation.Target;
  *         inspector.generateModel(schema, table, packageName,
  *         annotateSchema, trimStrings)
  * 
- * + * * Or you may use the GenerateModels tool to generate and save your classes to * the file system: - * + * *
  * java -jar iciql.jar
  *      -url "jdbc:h2:mem:"
@@ -190,10 +190,10 @@ import java.lang.annotation.Target;
  *      -package packageName -folder destination
  *      -annotateSchema false -trimStrings true
  * 
- * + * * Model validation: you may validate your model class with DbInspector object. * The DbInspector will report errors, warnings, and suggestions: - * + * *
  * Db db = Db.open("jdbc:h2:mem:", "sa", "sa");
  * DbInspector inspector = new DbInspector(db);
@@ -208,7 +208,7 @@ public interface Iciql {
 	/**
 	 * An annotation for an iciql version.
 	 * 

- * + * * @IQVersion(1) */ @Retention(RetentionPolicy.RUNTIME) @@ -229,7 +229,7 @@ public interface Iciql { /** * An annotation for a schema. *

- * + * * @IQSchema("PUBLIC") */ @Retention(RetentionPolicy.RUNTIME) @@ -278,9 +278,9 @@ public interface Iciql { *

  • com.iciql.iciql.IndexType.HASH *
  • com.iciql.iciql.IndexType.UNIQUE_HASH * - * + * * HASH indexes may only be valid for single column indexes. - * + * */ IndexType type() default IndexType.STANDARD; @@ -307,21 +307,21 @@ public interface Iciql { public static enum ConstraintUpdateType { UNSET, CASCADE, RESTRICT, SET_NULL, NO_ACTION, SET_DEFAULT; } - + /** * Enumeration defining the deferrability. */ public static enum ConstraintDeferrabilityType { UNSET, DEFERRABLE_INITIALLY_DEFERRED, DEFERRABLE_INITIALLY_IMMEDIATE, NOT_DEFERRABLE; } - + /** * A foreign key constraint annotation. *

    *

      *
    • @IQContraintForeignKey( - * foreignColumns = { "idaccount"}, - * referenceName = "account", + * foreignColumns = { "idaccount"}, + * referenceName = "account", * referenceColumns = { "id" }, * deleteType = ConstrainDeleteType.CASCADE, * updateType = ConstraintUpdateType.NO_ACTION ) @@ -372,7 +372,7 @@ public interface Iciql { *
    */ ConstraintDeferrabilityType deferrabilityType() default ConstraintDeferrabilityType.UNSET; - + /** * The source table for the columns defined as foreign. */ @@ -391,7 +391,7 @@ public interface Iciql { * The reference table for the columns defined as references. */ String referenceName() default ""; - + /** * Columns defined as 'references'. *
      @@ -410,7 +410,7 @@ public interface Iciql { public @interface IQContraintsForeignKey { IQContraintForeignKey[] value() default {}; } - + /** * A unique constraint annotation. *

      @@ -447,7 +447,7 @@ public interface Iciql { public @interface IQContraintsUnique { IQContraintUnique[] value() default {}; } - + /** * Annotation to define a view. */ @@ -463,7 +463,7 @@ public interface Iciql { * model class is not annotated with IQView. Default: unspecified. */ String name() default ""; - + /** * The source table for the view. *

      @@ -491,7 +491,7 @@ public interface Iciql { */ boolean annotationsOnly() default true; } - + /** * String snippet defining SQL constraints for a field. Use "this" as * a placeholder for the column name. "this" will be substituted at @@ -507,8 +507,8 @@ public interface Iciql { public @interface IQConstraint { String value() default ""; - } - + } + /** * Annotation to specify multiple indexes. */ @@ -657,7 +657,7 @@ public interface Iciql { */ String defaultValue() default ""; - } + } /** * Interface for using the EnumType.ENUMID enumeration mapping strategy. @@ -665,19 +665,22 @@ public interface Iciql { * Enumerations wishing to use EnumType.ENUMID must implement this * interface. */ - public interface EnumId { - int enumId(); + public interface EnumId { + X enumId(); + Class enumIdClass(); } + + /** * Enumeration representing how to map a java.lang.Enum to a column. *

      *

        *
      • NAME - name() : string *
      • ORDINAL - ordinal() : int - *
      • ENUMID - enumId() : int + *
      • ENUMID - enumId() : X *
      - * + * * @see com.iciql.Iciql.EnumId interface */ public enum EnumType { @@ -700,14 +703,14 @@ public interface Iciql { * annotation. *

      * The default mapping is by NAME. - * + * *

       	 * IQEnum(EnumType.NAME)
       	 * 
      - * + * * A string mapping will generate either a VARCHAR, if IQColumn.length > 0 * or a TEXT column if IQColumn.length == 0 - * + * */ @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.FIELD, ElementType.TYPE }) @@ -720,9 +723,9 @@ public interface Iciql { */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) - public @interface IQIgnore{ + public @interface IQIgnore{ } - + /** * This method is called to let the table define the primary key, indexes, * and the table name. diff --git a/src/main/java/com/iciql/ModelUtils.java b/src/main/java/com/iciql/ModelUtils.java index 56e6440..c3fd847 100644 --- a/src/main/java/com/iciql/ModelUtils.java +++ b/src/main/java/com/iciql/ModelUtils.java @@ -147,7 +147,7 @@ class ModelUtils { /** * Returns a SQL type mapping for a Java class. - * + * * @param fieldDef * the field to map * @return @@ -157,8 +157,14 @@ class ModelUtils { if (fieldClass.isEnum()) { switch (fieldDef.enumType) { case ORDINAL: - case ENUMID: return "INT"; + case ENUMID: + String sqlType = SUPPORTED_TYPES.get(fieldDef.enumTypeClass); + if (sqlType == null) { + throw new IciqlException("Unsupported enum mapping type {0} for {1}", + fieldDef.enumTypeClass, fieldDef.columnName); + } + return sqlType; case NAME: default: return "VARCHAR"; @@ -172,7 +178,7 @@ class ModelUtils { /** * Returns the Java class for a given SQL type. - * + * * @param sqlType * @param dateTimeClass * the preferred date class (java.util.Date or @@ -211,7 +217,7 @@ class ModelUtils { /** * Tries to create a convert a SQL table name to a camel case class name. - * + * * @param tableName * the SQL table name * @return the class name @@ -239,7 +245,7 @@ class ModelUtils { /** * Ensures that SQL column names don't collide with Java keywords. - * + * * @param columnName * the column name * @return the Java field name @@ -254,7 +260,7 @@ class ModelUtils { /** * Converts a DEFAULT clause value into an object. - * + * * @param field * definition * @return object @@ -360,7 +366,7 @@ class ModelUtils { /** * Converts the object into a DEFAULT clause value. - * + * * @param o * the default object * @return the value formatted for a DEFAULT clause @@ -395,7 +401,7 @@ class ModelUtils { /** * Checks the formatting of IQColumn.defaultValue(). - * + * * @param defaultValue * the default value * @return true if it is @@ -412,7 +418,7 @@ class ModelUtils { /** * Checks to see if the default value matches the class. - * + * * @param modelClass * the class * @param defaultValue diff --git a/src/main/java/com/iciql/TableDefinition.java b/src/main/java/com/iciql/TableDefinition.java index e0cc169..0cb1ad2 100644 --- a/src/main/java/com/iciql/TableDefinition.java +++ b/src/main/java/com/iciql/TableDefinition.java @@ -37,11 +37,11 @@ import com.iciql.Iciql.EnumId; import com.iciql.Iciql.EnumType; import com.iciql.Iciql.IQColumn; import com.iciql.Iciql.IQConstraint; +import com.iciql.Iciql.IQContraintForeignKey; import com.iciql.Iciql.IQContraintUnique; +import com.iciql.Iciql.IQContraintsForeignKey; import com.iciql.Iciql.IQContraintsUnique; import com.iciql.Iciql.IQEnum; -import com.iciql.Iciql.IQContraintForeignKey; -import com.iciql.Iciql.IQContraintsForeignKey; import com.iciql.Iciql.IQIgnore; import com.iciql.Iciql.IQIndex; import com.iciql.Iciql.IQIndexes; @@ -58,7 +58,7 @@ import com.iciql.util.Utils; /** * A table definition contains the index definitions of a table, the field * definitions, the table name, and other meta data. - * + * * @param * the table type */ @@ -79,7 +79,7 @@ public class TableDefinition { /** * The meta data of a constraint on foreign key. */ - + public static class ConstraintForeignKeyDefinition { public String constraintName; @@ -90,18 +90,18 @@ public class TableDefinition { public ConstraintUpdateType updateType = ConstraintUpdateType.UNSET; public ConstraintDeferrabilityType deferrabilityType = ConstraintDeferrabilityType.UNSET; } - + /** * The meta data of a unique constraint. */ - + public static class ConstraintUniqueDefinition { public String constraintName; public List uniqueColumns; } - - + + /** * The meta data of a field. */ @@ -118,6 +118,7 @@ public class TableDefinition { boolean nullable; String defaultValue; EnumType enumType; + Class enumTypeClass; boolean isPrimitive; String constraint; @@ -161,12 +162,12 @@ public class TableDefinition { throw new IciqlException(e); } } - + @Override public int hashCode() { return columnName.hashCode(); } - + @Override public boolean equals(Object o) { if (o instanceof FieldDefinition) { @@ -228,7 +229,7 @@ public class TableDefinition { /** * Define a primary key by the specified model fields. - * + * * @param modelFields * the ordered list of model fields */ @@ -239,7 +240,7 @@ public class TableDefinition { /** * Define a primary key by the specified column names. - * + * * @param columnNames * the ordered list of column names */ @@ -270,7 +271,7 @@ public class TableDefinition { /** * Defines an index with the specified model fields. - * + * * @param name * the index name (optional) * @param type @@ -285,7 +286,7 @@ public class TableDefinition { /** * Defines an index with the specified column names. - * + * * @param type * the index type (STANDARD, HASH, UNIQUE, UNIQUE_HASH) * @param columnNames @@ -305,7 +306,7 @@ public class TableDefinition { /** * Defines an unique constraint with the specified model fields. - * + * * @param name * the constraint name (optional) * @param modelFields @@ -318,7 +319,7 @@ public class TableDefinition { /** * Defines an unique constraint. - * + * * @param name * @param columnNames */ @@ -335,7 +336,7 @@ public class TableDefinition { /** * Defines a foreign key constraint with the specified model fields. - * + * * @param name * the constraint name (optional) * @param modelFields @@ -426,7 +427,7 @@ public class TableDefinition { if (inheritColumns) { Class superClass = clazz.getSuperclass(); classFields.addAll(Arrays.asList(superClass.getDeclaredFields())); - + if (superClass.isAnnotationPresent(IQView.class)) { IQView superView = superClass.getAnnotation(IQView.class); if (superView.inheritColumns()) { @@ -461,6 +462,7 @@ public class TableDefinition { boolean trim = false; boolean nullable = !f.getType().isPrimitive(); EnumType enumType = null; + Class enumTypeClass = null; String defaultValue = ""; String constraint = ""; // configure Java -> SQL enum mapping @@ -476,6 +478,11 @@ public class TableDefinition { IQEnum iqenum = f.getAnnotation(IQEnum.class); enumType = iqenum.value(); } + + if (EnumId.class.isAssignableFrom(f.getType())) { + // custom enumid mapping + enumTypeClass = ((EnumId) f.getType().getEnumConstants()[0]).enumIdClass(); + } } // try using default object @@ -515,7 +522,7 @@ public class TableDefinition { defaultValue = col.defaultValue(); } } - + boolean hasConstraint = f.isAnnotationPresent(IQConstraint.class); if (hasConstraint) { IQConstraint con = f.getAnnotation(IQConstraint.class); @@ -539,13 +546,14 @@ public class TableDefinition { fieldDef.nullable = nullable; fieldDef.defaultValue = defaultValue; fieldDef.enumType = enumType; + fieldDef.enumTypeClass = enumTypeClass; fieldDef.dataType = ModelUtils.getDataType(fieldDef); fieldDef.constraint = constraint; uniqueFields.add(fieldDef); } } fields.addAll(uniqueFields); - + List primaryKey = Utils.newArrayList(); int primitiveBoolean = 0; for (FieldDefinition fieldDef : fields) { @@ -623,7 +631,7 @@ public class TableDefinition { if (!EnumId.class.isAssignableFrom(value.getClass())) { throw new IciqlException(field.field.getName() + " does not implement EnumId!"); } - EnumId enumid = (EnumId) value; + EnumId enumid = (EnumId) value; return enumid.enumId(); } } @@ -643,7 +651,7 @@ public class TableDefinition { // return the value unchanged return value; } - + PreparedStatement createInsertStatement(Db db, Object obj, boolean returnKey) { SQLStatement stat = new SQLStatement(db); StatementBuilder buff = new StatementBuilder("INSERT INTO "); @@ -896,7 +904,7 @@ public class TableDefinition { } } } - + // create foreign keys constraints for (ConstraintForeignKeyDefinition constraint : constraintsForeignKey) { stat = new SQLStatement(db); @@ -1004,17 +1012,17 @@ public class TableDefinition { viewTableName = parentView.tableName(); } } - + if (StringUtils.isNullOrEmpty(viewTableName)) { // still missing view table name throw new IciqlException("View model class \"{0}\" is missing a table name!", tableName); } } - + // allow control over createTableIfRequired() createIfRequired = viewAnnotation.create(); } - + if (clazz.isAnnotationPresent(IQIndex.class)) { // single table index IQIndex index = clazz.getAnnotation(IQIndex.class); @@ -1028,7 +1036,7 @@ public class TableDefinition { addIndex(index); } } - + if (clazz.isAnnotationPresent(IQContraintUnique.class)) { // single table unique constraint IQContraintUnique constraint = clazz.getAnnotation(IQContraintUnique.class); @@ -1042,7 +1050,7 @@ public class TableDefinition { addConstraintUnique(constraint); } } - + if (clazz.isAnnotationPresent(IQContraintForeignKey.class)) { // single table constraint IQContraintForeignKey constraint = clazz.getAnnotation(IQContraintForeignKey.class); @@ -1056,7 +1064,7 @@ public class TableDefinition { addConstraintForeignKey(constraint); } } - + } private void addConstraintForeignKey(IQContraintForeignKey constraint) { @@ -1064,15 +1072,15 @@ public class TableDefinition { List referenceColumns = Arrays.asList(constraint.referenceColumns()); addConstraintForeignKey(constraint.name(), foreignColumns, constraint.referenceName(), referenceColumns, constraint.deleteType(), constraint.updateType(), constraint.deferrabilityType()); } - + private void addConstraintUnique(IQContraintUnique constraint) { List uniqueColumns = Arrays.asList(constraint.uniqueColumns()); addConstraintUnique(constraint.name(), uniqueColumns); } - + /** * Defines a foreign key constraint with the specified parameters. - * + * * @param name * name of the constraint * @param foreignColumns @@ -1119,11 +1127,11 @@ public class TableDefinition { List getContraintsUnique() { return constraintsUnique; } - + List getContraintsForeignKey() { return constraintsForeignKey; } - + private void initObject(Object obj, Map map) { for (FieldDefinition def : fields) { Object newValue = def.initWithNewObject(obj); @@ -1152,13 +1160,13 @@ public class TableDefinition { * JaQu assumed that you can always use the integer index of the * reflectively mapped field definition to determine position in the result * set. - * + * * This is not always true. - * + * * iciql identifies when a select * query is executed and maps column names * to a column index from the result set. If the select statement is * explicit, then the standard assumed column index is used instead. - * + * * @param rs * @return */ diff --git a/src/main/java/com/iciql/util/Utils.java b/src/main/java/com/iciql/util/Utils.java index 64fe6b3..5b2914a 100644 --- a/src/main/java/com/iciql/util/Utils.java +++ b/src/main/java/com/iciql/util/Utils.java @@ -135,8 +135,8 @@ public class Utils { } } throw new IciqlException(e, - "Missing default constructor? Exception trying to instantiate {0}: {1}", - clazz.getName(), e.getMessage()); + "Missing default constructor? Exception trying to instantiate {0}: {1}", clazz.getName(), + e.getMessage()); } } }; @@ -214,8 +214,7 @@ public class Utils { } } } - throw new IciqlException(e, - "Missing default constructor?! Exception trying to instantiate {0}: {1}", + throw new IciqlException(e, "Missing default constructor?! Exception trying to instantiate {0}: {1}", clazz.getName(), e.getMessage()); } } @@ -337,7 +336,7 @@ public class Utils { if (!EnumId.class.isAssignableFrom(o.getClass())) { throw new IciqlException("Can not convert the enum {0} using ENUMID", o); } - EnumId enumid = (EnumId) o; + EnumId enumid = (EnumId) o; return enumid.enumId(); case NAME: default: @@ -367,17 +366,39 @@ public class Utils { } // find name match - for (Enum value : values) { - if (value.name().equalsIgnoreCase(name)) { - return value; + if (type.equals(EnumType.ENUMID)) { + // ENUMID mapping + for (Enum value : values) { + EnumId enumid = (EnumId) value; + if (enumid.enumId().equals(name)) { + return value; + } + } + } else if (type.equals(EnumType.NAME)) { + // standard Enum.name() mapping + for (Enum value : values) { + if (value.name().equalsIgnoreCase(name)) { + return value; + } } } } else if (String.class.isAssignableFrom(currentType)) { // VARCHAR field String name = (String) o; - for (Enum value : values) { - if (value.name().equalsIgnoreCase(name)) { - return value; + if (type.equals(EnumType.ENUMID)) { + // ENUMID mapping + for (Enum value : values) { + EnumId enumid = (EnumId) value; + if (enumid.enumId().equals(name)) { + return value; + } + } + } else if (type.equals(EnumType.NAME)) { + // standard Enum.name() mapping + for (Enum value : values) { + if (value.name().equalsIgnoreCase(name)) { + return value; + } } } } else if (Number.class.isAssignableFrom(currentType)) { @@ -397,8 +418,23 @@ public class Utils { } // ENUMID mapping for (Enum value : values) { - EnumId enumid = (EnumId) value; - if (enumid.enumId() == n) { + EnumId enumid = (EnumId) value; + if (enumid.enumId().equals(n)) { + return value; + } + } + } + } else { + // custom object mapping + if (type.equals(EnumType.ENUMID)) { + if (!EnumId.class.isAssignableFrom(targetType)) { + throw new IciqlException("Can not convert the value {0} from {1} to {2} using ENUMID", o, + currentType, targetType); + } + // ENUMID mapping + for (Enum value : values) { + EnumId enumid = (EnumId) value; + if (enumid.enumId().equals(o)) { return value; } } @@ -456,8 +492,7 @@ public class Utils { length = Integer.MAX_VALUE; } int block = Math.min(BUFFER_BLOCK_SIZE, length); - ByteArrayOutputStream out = new ByteArrayOutputStream(length == Integer.MAX_VALUE ? block - : length); + ByteArrayOutputStream out = new ByteArrayOutputStream(length == Integer.MAX_VALUE ? block : length); byte[] buff = new byte[block]; while (length > 0) { int len = Math.min(block, length); diff --git a/src/test/java/com/iciql/test/EnumsTest.java b/src/test/java/com/iciql/test/EnumsTest.java index d8a0589..8e1f90e 100644 --- a/src/test/java/com/iciql/test/EnumsTest.java +++ b/src/test/java/com/iciql/test/EnumsTest.java @@ -31,6 +31,7 @@ import com.iciql.test.models.EnumModels; import com.iciql.test.models.EnumModels.EnumIdModel; import com.iciql.test.models.EnumModels.EnumOrdinalModel; import com.iciql.test.models.EnumModels.EnumStringModel; +import com.iciql.test.models.EnumModels.Genus; import com.iciql.test.models.EnumModels.Tree; /** @@ -58,6 +59,7 @@ public class EnumsTest { testIntEnums(new EnumIdModel()); testIntEnums(new EnumOrdinalModel()); testStringEnums(new EnumStringModel()); + testStringEnumIds(new EnumStringModel()); } private void testIntEnums(EnumModels e) { @@ -110,7 +112,31 @@ public class EnumsTest { list = db.from(e).where(e.tree()).between(Tree.MAPLE).and(Tree.PINE).select(); assertEquals(3, list.size()); } - + + private void testStringEnumIds(EnumModels e) { + // ensure all records inserted + long count = db.from(e).selectCount(); + assertEquals(5, count); + + // special case: + // value is first enum constant which is also the alias object. + // the first enum constant is used as the alias because we can not + // instantiate an enum reflectively. + EnumModels firstEnumValue = db.from(e).where(e.genus()).is(Genus.PINUS).selectFirst(); + assertEquals(Tree.PINE, firstEnumValue.tree()); + assertEquals(Genus.PINUS, firstEnumValue.genus()); + + EnumModels model = db.from(e).where(e.genus()).is(Genus.JUGLANS).selectFirst(); + + assertEquals(400, model.id.intValue()); + assertEquals(Tree.WALNUT, model.tree()); + assertEquals(Genus.JUGLANS, model.genus()); + + List list = db.from(e).where(e.genus()).isNot(Genus.BETULA).select(); + assertEquals(count - 1, list.size()); + + } + @Test public void testMultipleEnumInstances() { BadEnums b = new BadEnums(); @@ -121,7 +147,7 @@ public class EnumsTest { assertTrue(e.getMessage(), e.getMessage().startsWith("Can not explicitly reference Tree")); } } - + public static class BadEnums { Tree tree1 = Tree.BIRCH; Tree tree2 = Tree.MAPLE; diff --git a/src/test/java/com/iciql/test/models/EnumModels.java b/src/test/java/com/iciql/test/models/EnumModels.java index a865f6c..2320734 100644 --- a/src/test/java/com/iciql/test/models/EnumModels.java +++ b/src/test/java/com/iciql/test/models/EnumModels.java @@ -34,14 +34,14 @@ public abstract class EnumModels { /** * Test of @IQEnum annotated enumeration. This strategy is the default * strategy for all fields of the Tree enum. - * + * * Individual Tree field declarations can override this strategy by * specifying a different @IQEnum annotation. - * + * * Here ORDINAL specifies that this enum will be mapped to an INT column. */ @IQEnum(EnumType.ENUMID) - public enum Tree implements EnumId { + public enum Tree implements EnumId { PINE(10), OAK(20), BIRCH(30), WALNUT(40), MAPLE(50); private int enumid; @@ -51,9 +51,39 @@ public abstract class EnumModels { } @Override - public int enumId() { + public Integer enumId() { return enumid; } + + @Override + public Class enumIdClass() { + return Integer.class; + } + + } + + /** + * Enum for testing custom ENUMID mapping. + */ + @IQEnum(EnumType.ENUMID) + public enum Genus implements EnumId { + PINUS("pinaceae"), QUERCUS("fagaceae"), BETULA("betulaceae"), JUGLANS("juglandaceae"), ACER("aceraceae"); + + private String family; + + Genus(String id) { + this.family = id; + } + + @Override + public String enumId() { + return family; + } + + @Override + public Class enumIdClass() { + return String.class; + } } @IQColumn(primaryKey = true) @@ -61,6 +91,8 @@ public abstract class EnumModels { public abstract Tree tree(); + public abstract Genus genus(); + /** * Test model for enum-as-enumid. */ @@ -72,12 +104,18 @@ public abstract class EnumModels { @IQColumn private Tree tree; + // no need to specify ENUMID type as the enumeration definition + // specifies it. + @IQColumn + private Genus genus; + public EnumIdModel() { } - public EnumIdModel(int id, Tree tree) { + public EnumIdModel(int id, Tree tree, Genus genus) { this.id = id; this.tree = tree; + this.genus = genus; } @Override @@ -85,10 +123,17 @@ public abstract class EnumModels { return tree; } + @Override + public Genus genus() { + return genus; + } + public static List createList() { - return Arrays.asList(new EnumIdModel(400, Tree.WALNUT), new EnumIdModel(200, Tree.OAK), - new EnumIdModel(500, Tree.MAPLE), new EnumIdModel(300, Tree.BIRCH), new EnumIdModel(100, - Tree.PINE)); + return Arrays.asList(new EnumIdModel(400, Tree.WALNUT, Genus.JUGLANS), + new EnumIdModel(200, Tree.OAK, Genus.QUERCUS), + new EnumIdModel(500, Tree.MAPLE, Genus.ACER), + new EnumIdModel(300, Tree.BIRCH, Genus.BETULA), + new EnumIdModel(100, Tree.PINE, Genus.PINUS)); } } @@ -103,10 +148,13 @@ public abstract class EnumModels { @IQColumn private Tree tree; + @IQColumn + private Genus genus; + public EnumOrdinalModel() { } - public EnumOrdinalModel(int id, Tree tree) { + public EnumOrdinalModel(int id, Tree tree, Genus genus) { this.id = id; this.tree = tree; } @@ -116,10 +164,17 @@ public abstract class EnumModels { return tree; } + @Override + public Genus genus() { + return genus; + } + public static List createList() { - return Arrays.asList(new EnumOrdinalModel(400, Tree.WALNUT), new EnumOrdinalModel(200, Tree.OAK), - new EnumOrdinalModel(500, Tree.MAPLE), new EnumOrdinalModel(300, Tree.BIRCH), - new EnumOrdinalModel(100, Tree.PINE)); + return Arrays.asList(new EnumOrdinalModel(400, Tree.WALNUT, Genus.JUGLANS), + new EnumOrdinalModel(200, Tree.OAK, Genus.QUERCUS), + new EnumOrdinalModel(500, Tree.MAPLE, Genus.ACER), + new EnumOrdinalModel(300, Tree.BIRCH, Genus.BETULA), + new EnumOrdinalModel(100, Tree.PINE, Genus.PINUS)); } } @@ -135,12 +190,16 @@ public abstract class EnumModels { @IQColumn(length = 25) private Tree tree; + @IQColumn(trim = true, length = 25) + private Genus genus; + public EnumStringModel() { } - public EnumStringModel(int id, Tree tree) { + public EnumStringModel(int id, Tree tree, Genus genus) { this.id = id; this.tree = tree; + this.genus = genus; } @Override @@ -148,10 +207,17 @@ public abstract class EnumModels { return tree; } + @Override + public Genus genus() { + return genus; + } + public static List createList() { - return Arrays.asList(new EnumStringModel(400, Tree.WALNUT), new EnumStringModel(200, Tree.OAK), - new EnumStringModel(500, Tree.MAPLE), new EnumStringModel(300, Tree.BIRCH), - new EnumStringModel(100, Tree.PINE)); + return Arrays.asList(new EnumStringModel(400, Tree.WALNUT, Genus.JUGLANS), + new EnumStringModel(200, Tree.OAK, Genus.QUERCUS), + new EnumStringModel(500, Tree.MAPLE, Genus.ACER), + new EnumStringModel(300, Tree.BIRCH, Genus.BETULA), + new EnumStringModel(100, Tree.PINE, Genus.PINUS)); } } }