]> source.dussan.org Git - iciql.git/commitdiff
IQTable.primaryKey is now an array. Default values from objects.
authorJames Moger <james.moger@gmail.com>
Tue, 9 Aug 2011 15:28:48 +0000 (11:28 -0400)
committerJames Moger <james.moger@gmail.com>
Tue, 9 Aug 2011 15:28:48 +0000 (11:28 -0400)
Also fixed an error with allowing null objects. Noted rapid churn of
iciql in documentation. Changed build constants for next release.

16 files changed:
build.xml
docs/00_index.mkd
docs/01_model_classes.mkd
docs/05_releases.mkd
docs/resources/iciql.css
src/com/iciql/Constants.java
src/com/iciql/Db.java
src/com/iciql/DbVersion.java
src/com/iciql/Iciql.java
src/com/iciql/IciqlException.java
src/com/iciql/ModelUtils.java
src/com/iciql/TableDefinition.java
src/com/iciql/TableInspector.java
src/com/iciql/util/Utils.java
tests/com/iciql/test/DefaultValuesTest.java [new file with mode: 0644]
tests/com/iciql/test/models/DefaultValuesModel.java [new file with mode: 0644]

index 2c94cc4389a342562c7193291fd64b4f8380a889..9e54239a2fc27b2cb8242503c4bfa49ec9ff7a16 100644 (file)
--- a/build.xml
+++ b/build.xml
                        </filterchain>\r
                </loadfile>\r
 \r
-               <!-- extract iciql previous api version from source code -->\r
-               <loadfile property="iq.apiPrevious" srcfile="${basedir}/src/com/iciql/Constants.java">\r
-                       <filterchain>\r
-                               <linecontains>\r
-                                       <contains value="public static final String API_PREVIOUS = " />\r
-                               </linecontains>\r
-                               <striplinebreaks />\r
-                               <tokenfilter>\r
-                                       <replacestring from="public static final String API_PREVIOUS = &quot;" to="" />\r
-                                       <replacestring from="&quot;;" to="" />\r
-                                       <trim />\r
-                               </tokenfilter>\r
-                       </filterchain>\r
-               </loadfile>\r
-\r
                <property name="library.jar" value="${basedir}/iciql-${iq.version}.jar" />\r
                <property name="javadoc.jar" value="${basedir}/iciql-${iq.version}-javadoc.jar" />\r
                <property name="sources.jar" value="${basedir}/iciql-${iq.version}-sources.jar" />\r
                                \r
                        <!-- versioning -->\r
                                <param name="-since"/> <param name="api/v1.xml"/> <param name="v1" />\r
-                       <param name="-since"/> <param name="api/v${iq.apiPrevious}.xml"/> <param name="v${iq.apiPrevious}" />\r
+                               <param name="-since"/> <param name="api/v2.xml"/> <param name="v2" />\r
+                               <param name="-since"/> <param name="api/v3.xml"/> <param name="v3" />\r
                        <param name="-apiversion" value="v${iq.apiCurrent}"/>\r
                                \r
                                <param name="-apixml" value="api/v${iq.apiCurrent}.xml"/>\r
index 3371ce2f50d02497ebe28b7a6644affeff7efd4c..06bec5b47dcb3ca72b2952404665192cc7b6474c 100644 (file)
@@ -46,6 +46,8 @@ iciql requires a Java 6 Runtime Environment (JRE) or a Java 6 Development Kit (J
  \r
 ### Current Release\r
 \r
+<span class="warning">iciql is undergoing rapid development so api and configuration are subject to change from release to release</span>\r
+\r
 **%VERSION%** ([zip](http://code.google.com/p/iciql/downloads/detail?name=%ZIP%)|[jar](http://code.google.com/p/iciql/downloads/detail?name=%JAR%)) &nbsp; *released %BUILDDATE%*\r
 \r
 issues, binaries, & source @ [Google Code][googlecode]<br/>\r
index 846ef6c2b4dabfc11db6c75e2be7b680b1827aa8..274cb92f44506c05ef3079cbb2b12ed5348eb924 100644 (file)
@@ -143,6 +143,7 @@ The recommended approach to setup a model class is to annotate the class and fie
 ### advantages\r
 \r
 - annotated fields may have any scope\r
+- annotated fields may specify default values\r
 - annotated models support annotated field inheritance making it possible to design a single base class that defines the fields and then create table subclasses that specify the table mappings.\r
 - model runtime dependency is limited to the small, portable `com.iciql.Iciql` class file which contains the annotation definitions\r
 \r
@@ -151,6 +152,24 @@ The recommended approach to setup a model class is to annotate the class and fie
 - more verbose model classes\r
 - indexes are defined using "fragile" string column names\r
 - compound primary keys are defined using "fragile" string column names\r
+\r
+### default values\r
+\r
+You may specify default values for an @IQColumn by either:\r
+\r
+1. specifying the default value string within your annotation<br/>\r
+%BEGINCODE%\r
+// notice the single ticks!\r
+@IQColumn(defaultValue="'2000-01-01 00:00:00'")\r
+Date myDate;\r
+%ENDCODE%\r
+2. setting a default object on the field<br/>\r
+%BEGINCODE%\r
+@IQColumn\r
+Date myDate = new Date(100, 0, 1);\r
+%ENDCODE%\r
+\r
+If you want to specify a database-specific variable or function as your default value (e.g. CURRENT_TIMESTAMP) you must do that within the annotation.  Also note that the IQColumn.defaultValue must be a well-formatted SQL DEFAULT expression whereas object defaults will be automatically converted to an SQL DEFAULT expression.\r
  \r
 ### Example Annotated Model\r
 %BEGINCODE%\r
index b060fd2e872f2ffceea576a3e8dffcd7c6bf3874..8d1295bb12fb8773ae931997ee698b61025671f6 100644 (file)
@@ -2,8 +2,26 @@
 \r
 ### Current Release\r
 \r
+<span class="warning">iciql is undergoing rapid development so api and configuration are subject to change from release to release</span>\r
+\r
 **%VERSION%** ([zip](http://code.google.com/p/iciql/downloads/detail?name=%ZIP%)|[jar](http://code.google.com/p/iciql/downloads/detail?name=%JAR%)) &nbsp; *released %BUILDDATE%*\r
 \r
+- api change release (API v4)\r
+- allow using objects to assign default values<br/>\r
+%BEGINCODE%\r
+// CREATE TABLE ... myDate DATETIME DEFAULT '2000-02-01 00:00:00'\r
+@IQColumn\r
+Date myDate = new Date(100, 1, 1);\r
+%ENDCODE%\r
+- changed @IQTable.primaryKey definition to use array of column names<br/>\r
+%BEGINCODE%\r
+@IQTable( primaryKey = {"name", "nickname"})\r
+%ENDCODE%\r
+\r
+### Older Releases\r
+\r
+**0.6.3** &nbsp; *released 2011-08-08*\r
+\r
 - api change release (API v3)\r
 - finished enum support (issue 4)\r
 - added UUID type support (H2 databases only)\r
@@ -11,8 +29,6 @@
 - added *between(A y).and(A z)* condition syntax\r
 - moved dialects into separate package\r
 \r
-### Older Releases\r
-\r
 **0.6.2** &nbsp; *released 2011-08-05*\r
 \r
 - api change release (API v2)\r
index 7f8a48b913b9a49aba09fb42256df76194efbaaa..3ba942b1dbae7eac1623a448983925c726eb2311 100644 (file)
@@ -77,6 +77,11 @@ a:hover, a:visited, a:active {
        color: #880000;\r
 }\r
 \r
+span.warning {\r
+       font-weight: bold;\r
+       color: #f00000;\r
+}\r
+\r
 img.logo {\r
        margin-top:-8px;\r
        float: right;\r
index 809c06ccb4504dbfcdff7b504482050d552ea702..917fcb0a277b0115ab578a9f742f9c73ce6c7679 100644 (file)
@@ -25,18 +25,14 @@ public class Constants {
 \r
        // The build script extracts this exact line so be careful editing it\r
        // and only use A-Z a-z 0-9 .-_ in the string.\r
-       public static final String VERSION = "0.6.3";\r
+       public static final String VERSION = "0.6.4-SNAPSHOT";\r
 \r
        // The build script extracts this exact line so be careful editing it\r
        // and only use A-Z a-z 0-9 .-_ in the string.\r
-       public static final String VERSION_DATE = "2011-08-08";\r
-       \r
-       // The build script extracts this exact line so be careful editing it\r
-       // and only use A-Z a-z 0-9 .-_ in the string.\r
-       public static final String API_CURRENT = "3";\r
+       public static final String VERSION_DATE = "PENDING";\r
 \r
        // The build script extracts this exact line so be careful editing it\r
        // and only use A-Z a-z 0-9 .-_ in the string.\r
-       public static final String API_PREVIOUS = "2";\r
+       public static final String API_CURRENT = "4";\r
 \r
 }\r
index 121e50c866f901ef70844cade4ba74d0768764e2..621e8257abe07db630a1d6f1743fbeb47b565da5 100644 (file)
@@ -114,7 +114,7 @@ public class Db {
                return TOKENS.get(x);\r
        }\r
 \r
-       private static <T> T instance(Class<T> clazz) {\r
+       static <T> T instance(Class<T> clazz) {\r
                try {\r
                        return clazz.newInstance();\r
                } catch (Exception e) {\r
index ff72ec0cbc847425ad51a91408fe970a792fba98..2a8aa442001808d02206e80c2c91a6841e497975 100644 (file)
@@ -23,7 +23,7 @@ import com.iciql.Iciql.IQTable;
 /**
  * A system table to track database and table versions.
  */
-@IQTable(name = "_iq_versions", primaryKey = "schemaName tableName", memoryTable = true)
+@IQTable(name = "_iq_versions", primaryKey = { "schemaName", "tableName"}, memoryTable = true)
 public class DbVersion {
 
        @IQColumn(name = "schemaName", length = 255, allowNull = false)
index 64c2158f956c9be0c117426aeebef915f5161ea9..2eaf78311d4efb47aabdeaa7158d673ccc8ddc6c 100644 (file)
@@ -35,7 +35,9 @@ import java.lang.annotation.Target;
  * <p>\r
  * Fully Supported Data Types:\r
  * <table>\r
- * <tr><th colspan="2">All Databases</th></tr>\r
+ * <tr>\r
+ * <th colspan="2">All Databases</th>\r
+ * </tr>\r
  * <tr>\r
  * <td>java.lang.String</td>\r
  * <td>VARCHAR (length > 0) or TEXT (length == 0)</td>\r
@@ -104,7 +106,9 @@ import java.lang.annotation.Target;
  * <td>INT<br/>\r
  * EnumType.ENUMID</td>\r
  * </tr>\r
- * <tr><th colspan="2">H2 Databases</th></tr>\r
+ * <tr>\r
+ * <th colspan="2">H2 Databases</th>\r
+ * </tr>\r
  * <tr>\r
  * <td>java.util.UUID</td>\r
  * <td>UUID</td>\r
@@ -117,22 +121,38 @@ import java.lang.annotation.Target;
  * BUT these field types may not be used to specify compile-time clauses or\r
  * constraints.\r
  * <table>\r
- * <tr><td>byte []</td>\r
- * <td>BLOB</td></tr>\r
- * <tr><td>boolean</td>\r
- * <td>BIT</td></tr>\r
- * <tr><td>byte</td>\r
- * <td>TINYINT</td></tr>\r
- * <tr><td>short</td>\r
- * <td>SMALLINT</td></tr>\r
- * <tr><td>int</td>\r
- * <td>INT</td></tr>\r
- * <tr><td>long</td>\r
- * <td>BIGINT</td></tr>\r
- * <tr><td>float</td>\r
- * <td>REAL</td></tr>\r
- * <tr><td>double</td>\r
- * <td>DOUBLE</td></tr>\r
+ * <tr>\r
+ * <td>byte []</td>\r
+ * <td>BLOB</td>\r
+ * </tr>\r
+ * <tr>\r
+ * <td>boolean</td>\r
+ * <td>BIT</td>\r
+ * </tr>\r
+ * <tr>\r
+ * <td>byte</td>\r
+ * <td>TINYINT</td>\r
+ * </tr>\r
+ * <tr>\r
+ * <td>short</td>\r
+ * <td>SMALLINT</td>\r
+ * </tr>\r
+ * <tr>\r
+ * <td>int</td>\r
+ * <td>INT</td>\r
+ * </tr>\r
+ * <tr>\r
+ * <td>long</td>\r
+ * <td>BIGINT</td>\r
+ * </tr>\r
+ * <tr>\r
+ * <td>float</td>\r
+ * <td>REAL</td>\r
+ * </tr>\r
+ * <tr>\r
+ * <td>double</td>\r
+ * <td>DOUBLE</td>\r
+ * </tr>\r
  * </table>\r
  * <p>\r
  * Table and field mapping: by default, the mapped table name is the class name\r
@@ -302,13 +322,13 @@ public interface Iciql {
                 * then no primary key is set by the IQTable annotation. You may specify\r
                 * a composite primary key.\r
                 * <ul>\r
-                * <li>primaryKey = "id, name"\r
-                * <li>primaryKey = "id name"\r
+                * <li>single column primaryKey: value = "id"\r
+                * <li>compound primary key: value = { "id", "name" }\r
                 * </ul>\r
                 * The primary key may still be overridden in the define() method if the\r
                 * model class is not annotated with IQTable. Default: unspecified.\r
                 */\r
-               String primaryKey() default "";\r
+               String[] primaryKey() default {};\r
 \r
                /**\r
                 * The inherit columns allows this model class to inherit columns from\r
@@ -406,6 +426,11 @@ public interface Iciql {
                 * if the default value is specified, and auto increment is disabled,\r
                 * and primary key is disabled, then this value is included in the\r
                 * "DEFAULT ..." phrase of a column during the CREATE TABLE process.\r
+                * <p>\r
+                * Alternatively, you may specify a default object value on the field\r
+                * and this will be converted to a properly formatted DEFAULT expression\r
+                * during the CREATE TABLE process.\r
+                * <p>\r
                 * Default: unspecified (null).\r
                 */\r
                String defaultValue() default "";\r
@@ -435,7 +460,7 @@ public interface Iciql {
         */\r
        public enum EnumType {\r
                NAME, ORDINAL, ENUMID;\r
-               \r
+\r
                public static final EnumType DEFAULT_TYPE = NAME;\r
        }\r
 \r
index 9f411d91828a9ef684a38fe06e1e7bf3b01ff988..1e2a890c5a9674a2629acb1fde7433a3415458d2 100644 (file)
@@ -30,6 +30,11 @@ public class IciqlException extends RuntimeException {
 \r
        }\r
 \r
+       public IciqlException(Throwable t, String message, Object... parameters) {\r
+               super(parameters.length > 0 ? MessageFormat.format(message, parameters) : message, t);\r
+\r
+       }\r
+\r
        public IciqlException(Throwable t) {\r
                super(t);\r
        }\r
index 579c7f6e723a104a4c68cf1b3fd239cf034b146e..2e42a7d4cbfe1739e5b6172a221cc76a28307741 100644 (file)
@@ -21,14 +21,16 @@ import static com.iciql.util.StringUtils.isNullOrEmpty;
 
 import java.lang.reflect.Method;
 import java.math.BigDecimal;
+import java.text.MessageFormat;
+import java.text.SimpleDateFormat;
 import java.util.Arrays;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 import java.util.regex.Pattern;
 
-import com.iciql.Iciql.EnumType;
 import com.iciql.TableDefinition.FieldDefinition;
 import com.iciql.util.StringUtils;
 
@@ -61,7 +63,7 @@ class ModelUtils {
                m.put(java.sql.Time.class, "TIME");
                m.put(byte[].class, "BLOB");
                m.put(UUID.class, "UUID");
-               
+
                // map primitives
                m.put(boolean.class, m.get(Boolean.class));
                m.put(byte.class, m.get(Byte.class));
@@ -201,9 +203,9 @@ class ModelUtils {
                                // do not map from SQL TYPE to primitive type
                                continue;
                        }
-                       if (SUPPORTED_TYPES.get(clazz).equalsIgnoreCase(sqlType)) {                             
+                       if (SUPPORTED_TYPES.get(clazz).equalsIgnoreCase(sqlType)) {
                                mappedClass = clazz;
-                               
+
                                break;
                        }
                }
@@ -252,6 +254,41 @@ class ModelUtils {
                return lower;
        }
 
+       /**
+        * Converts the object into a DEFAULT clause value.
+        * 
+        * @param o
+        *            the default object
+        * @return the value formatted for a DEFAULT clause
+        */
+       static String formatDefaultValue(Object o) {
+               Class<?> objectClass = o.getClass();
+               String value = null;
+               if (Number.class.isAssignableFrom(objectClass)) {
+                       // NUMBER
+                       value = ((Number) o).toString();
+               } else if (java.sql.Date.class.isAssignableFrom(objectClass)) {
+                       // DATE
+                       value = new SimpleDateFormat("yyyy-MM-dd").format((Date) o);
+               } else if (java.sql.Time.class.isAssignableFrom(objectClass)) {
+                       // TIME
+                       value = new SimpleDateFormat("HH:mm:ss").format((Date) o);
+               } else if (Date.class.isAssignableFrom(objectClass)) {
+                       // DATETIME
+                       value = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date) o);
+               } else if (String.class.isAssignableFrom(objectClass)) {
+                       // STRING
+                       value = o.toString();
+               } else if (Boolean.class.isAssignableFrom(objectClass)) {
+                       // BOOLEAN
+                       value = o.toString();
+               }
+               if (value == null) {
+                       return "''";
+               }
+               return MessageFormat.format("''{0}''", value);
+       }
+
        /**
         * Checks the formatting of IQColumn.defaultValue().
         * 
index 7b3e1e436ad67e01310460a2cba79cd2ee5aff0e..6e25c91ff892f6e0d5a4839144f6f4fbb12ee873 100644 (file)
@@ -267,6 +267,7 @@ public class TableDefinition<T> {
                        classFields.addAll(Arrays.asList(superClass.getDeclaredFields()));\r
                }\r
 \r
+               T defaultObject = Db.instance(clazz);\r
                for (Field f : classFields) {\r
                        // default to field name\r
                        String columnName = f.getName();\r
@@ -277,6 +278,21 @@ public class TableDefinition<T> {
                        boolean allowNull = true;\r
                        EnumType enumType = null;\r
                        String defaultValue = "";\r
+                       // configure Java -> SQL enum mapping\r
+                       if (f.getType().isEnum()) {\r
+                               enumType = EnumType.DEFAULT_TYPE;\r
+                               if (f.getType().isAnnotationPresent(IQEnum.class)) {\r
+                                       // enum definition is annotated for all instances\r
+                                       IQEnum iqenum = f.getType().getAnnotation(IQEnum.class);\r
+                                       enumType = iqenum.value();\r
+                               }\r
+                               if (f.isAnnotationPresent(IQEnum.class)) {\r
+                                       // this instance of the enum is annotated\r
+                                       IQEnum iqenum = f.getAnnotation(IQEnum.class);\r
+                                       enumType = iqenum.value();\r
+                               }\r
+                       }\r
+\r
                        boolean hasAnnotation = f.isAnnotationPresent(IQColumn.class);\r
                        if (hasAnnotation) {\r
                                IQColumn col = f.getAnnotation(IQColumn.class);\r
@@ -288,21 +304,29 @@ public class TableDefinition<T> {
                                maxLength = col.length();\r
                                trimString = col.trim();\r
                                allowNull = col.allowNull();\r
-                               defaultValue = col.defaultValue();\r
-                       }\r
 \r
-                       // configure Java -> SQL enum mapping\r
-                       if (f.getType().isEnum()) {\r
-                               enumType = EnumType.DEFAULT_TYPE;\r
-                               if (f.getType().isAnnotationPresent(IQEnum.class)) {\r
-                                       // enum definition is annotated for all instances\r
-                                       IQEnum iqenum = f.getType().getAnnotation(IQEnum.class);\r
-                                       enumType = iqenum.value();\r
+                               // try using default object\r
+                               try {\r
+                                       f.setAccessible(true);\r
+                                       Object value = f.get(defaultObject);\r
+                                       if (value != null) {\r
+                                               if (value.getClass().isEnum()) {\r
+                                                       // enum default, convert to target type\r
+                                                       Enum<?> anEnum = (Enum<?>) value;\r
+                                                       Object o = Utils.convertEnum(anEnum, enumType);\r
+                                                       defaultValue = ModelUtils.formatDefaultValue(o);\r
+                                               } else {\r
+                                                       // object default\r
+                                                       defaultValue = ModelUtils.formatDefaultValue(value);\r
+                                               }\r
+                                       }\r
+                               } catch (IllegalAccessException e) {\r
+                                       throw new IciqlException(e, "Failed to get default object for {0}", columnName);\r
                                }\r
-                               if (f.isAnnotationPresent(IQEnum.class)) {\r
-                                       // this instance of the enum is annotated\r
-                                       IQEnum iqenum = f.getAnnotation(IQEnum.class);\r
-                                       enumType = iqenum.value();\r
+\r
+                               // annotation overrides\r
+                               if (!StringUtils.isNullOrEmpty(col.defaultValue())) {\r
+                                       defaultValue = col.defaultValue();\r
                                }\r
                        }\r
 \r
@@ -340,6 +364,9 @@ public class TableDefinition<T> {
         */\r
        private Object getValue(Object obj, FieldDefinition field) {\r
                Object value = field.getValue(obj);\r
+               if (value == null) {\r
+                       return value;\r
+               }\r
                if (field.enumType != null) {\r
                        // convert enumeration to INT or STRING\r
                        Enum<?> iqenum = (Enum<?>) value;\r
@@ -352,13 +379,13 @@ public class TableDefinition<T> {
                                }\r
                                return iqenum.name();\r
                        case ORDINAL:\r
-                               return iqenum.ordinal();                        \r
+                               return iqenum.ordinal();\r
                        case ENUMID:\r
                                if (!EnumId.class.isAssignableFrom(value.getClass())) {\r
                                        throw new IciqlException(field.field.getName() + " does not implement EnumId!");\r
                                }\r
                                EnumId enumid = (EnumId) value;\r
-                               return enumid.enumId();                 \r
+                               return enumid.enumId();\r
                        }\r
                }\r
                if (field.trimString && field.maxLength > 0) {\r
@@ -580,30 +607,6 @@ public class TableDefinition<T> {
                return this;\r
        }\r
 \r
-       /**\r
-        * Retrieve list of columns from primary key definition.\r
-        * \r
-        * @param index\r
-        *            the primary key columns, separated by space\r
-        * @return the column list\r
-        */\r
-       private List<String> getColumns(String index) {\r
-               List<String> cols = Utils.newArrayList();\r
-               if (index == null || index.length() == 0) {\r
-                       return null;\r
-               }\r
-               String[] cs = index.split("(,|\\s)");\r
-               for (String c : cs) {\r
-                       if (c != null && c.trim().length() > 0) {\r
-                               cols.add(c.trim());\r
-                       }\r
-               }\r
-               if (cols.size() == 0) {\r
-                       return null;\r
-               }\r
-               return cols;\r
-       }\r
-\r
        void mapObject(Object obj) {\r
                fieldMap.clear();\r
                initObject(obj, fieldMap);\r
@@ -636,8 +639,9 @@ public class TableDefinition<T> {
                        }\r
 \r
                        // setup the primary index, if properly annotated\r
-                       List<String> primaryKey = getColumns(tableAnnotation.primaryKey());\r
-                       if (primaryKey != null) {\r
+                       if (tableAnnotation.primaryKey().length > 0) {\r
+                               List<String> primaryKey = Utils.newArrayList();\r
+                               primaryKey.addAll(Arrays.asList(tableAnnotation.primaryKey()));\r
                                setPrimaryKey(primaryKey);\r
                        }\r
                }\r
index 080e20e80972f5082fef643155b21e37afb6f371..6ec848d10f362fde40286bbcc58fbd31b2a5db08 100644 (file)
@@ -226,11 +226,15 @@ public class TableInspector {
                ap.addParameter("name", table);
 
                if (primaryKeys.size() > 1) {
-                       StringBuilder pk = new StringBuilder();
+                       StatementBuilder pk = new StatementBuilder();
+                       pk.append("{ ");
                        for (String key : primaryKeys) {
-                               pk.append(key).append(' ');
+                               pk.appendExceptFirst(", ");
+                               pk.append("\"");
+                               pk.append(key);
+                               pk.append("\"");
                        }
-                       pk.trimToSize();
+                       pk.append(" }");
                        ap.addParameter("primaryKey", pk.toString());
                }
 
@@ -328,8 +332,8 @@ public class TableInspector {
                        // Imports
                        // don't import primitives, java.lang classes, or byte []
                        if (clazz.getPackage() == null) {
-                       } else if (clazz.getPackage().getName().equals("java.lang")) {                          
-                       } else if (clazz.equals(byte[].class)) {                                
+                       } else if (clazz.getPackage().getName().equals("java.lang")) {
+                       } else if (clazz.equals(byte[].class)) {
                        } else {
                                imports.add(clazz.getCanonicalName());
                        }
@@ -508,13 +512,12 @@ public class TableInspector {
                                remarks.add(warn(
                                                table,
                                                col,
-                                               format("{0}.maxLength={1}, ColumnMaxLength={2}", IQColumn.class.getSimpleName(),
+                                               format("{0}.length={1}, ColumnMaxLength={2}", IQColumn.class.getSimpleName(),
                                                                fieldDef.maxLength, col.size)));
                        }
                        if (fieldDef.maxLength > 0 && !fieldDef.trimString) {
-                               remarks.add(consider(table, col,
-                                               format("{0}.truncateToMaxLength=true" + " will prevent IciqlExceptions on"
-                                                               + " INSERT or UPDATE, but will clip data!", IQColumn.class.getSimpleName())));
+                               remarks.add(consider(table, col, format("{0}.trim=true will prevent IciqlExceptions on"
+                                               + " INSERT or UPDATE, but will clip data!", IQColumn.class.getSimpleName())));
                        }
                }
 
@@ -523,55 +526,58 @@ public class TableInspector {
                        remarks.add(warn(
                                        table,
                                        col,
-                                       format("{0}.isAutoIncrement={1}" + " while Column autoIncrement={2}",
+                                       format("{0}.autoIncrement={1}" + " while Column autoIncrement={2}",
                                                        IQColumn.class.getSimpleName(), fieldDef.isAutoIncrement, col.isAutoIncrement)));
                }
                // default value
                if (!col.isAutoIncrement && !col.isPrimaryKey) {
+                       String defaultValue = null;
+                       if (fieldDef.defaultValue != null && fieldDef.defaultValue instanceof String) {
+                               defaultValue = fieldDef.defaultValue.toString();
+                       }
                        // check Model.defaultValue format
-                       if (!ModelUtils.isProperlyFormattedDefaultValue(fieldDef.defaultValue)) {
+                       if (!ModelUtils.isProperlyFormattedDefaultValue(defaultValue)) {
                                remarks.add(error(
                                                table,
                                                col,
                                                format("{0}.defaultValue=\"{1}\"" + " is improperly formatted!",
-                                                               IQColumn.class.getSimpleName(), fieldDef.defaultValue))
-                                               .throwError(throwError));
+                                                               IQColumn.class.getSimpleName(), defaultValue)).throwError(throwError));
                                // next field
                                return;
                        }
                        // compare Model.defaultValue to Column.defaultValue
-                       if (isNullOrEmpty(fieldDef.defaultValue) && !isNullOrEmpty(col.defaultValue)) {
+                       if (isNullOrEmpty(defaultValue) && !isNullOrEmpty(col.defaultValue)) {
                                // Model.defaultValue is NULL, Column.defaultValue is NOT NULL
                                remarks.add(warn(
                                                table,
                                                col,
                                                format("{0}.defaultValue=\"\"" + " while column default=\"{1}\"",
                                                                IQColumn.class.getSimpleName(), col.defaultValue)));
-                       } else if (!isNullOrEmpty(fieldDef.defaultValue) && isNullOrEmpty(col.defaultValue)) {
+                       } else if (!isNullOrEmpty(defaultValue) && isNullOrEmpty(col.defaultValue)) {
                                // Column.defaultValue is NULL, Model.defaultValue is NOT NULL
                                remarks.add(warn(
                                                table,
                                                col,
                                                format("{0}.defaultValue=\"{1}\"" + " while column default=\"\"",
-                                                               IQColumn.class.getSimpleName(), fieldDef.defaultValue)));
-                       } else if (!isNullOrEmpty(fieldDef.defaultValue) && !isNullOrEmpty(col.defaultValue)) {
-                               if (!fieldDef.defaultValue.equals(col.defaultValue)) {
+                                                               IQColumn.class.getSimpleName(), defaultValue)));
+                       } else if (!isNullOrEmpty(defaultValue) && !isNullOrEmpty(col.defaultValue)) {
+                               if (!defaultValue.equals(col.defaultValue)) {
                                        // Model.defaultValue != Column.defaultValue
                                        remarks.add(warn(
                                                        table,
                                                        col,
                                                        format("{0}.defaultValue=\"{1}\"" + " while column default=\"{2}\"",
-                                                                       IQColumn.class.getSimpleName(), fieldDef.defaultValue, col.defaultValue)));
+                                                                       IQColumn.class.getSimpleName(), defaultValue, col.defaultValue)));
                                }
                        }
 
                        // sanity check Model.defaultValue literal value
-                       if (!ModelUtils.isValidDefaultValue(fieldDef.field.getType(), fieldDef.defaultValue)) {
+                       if (!ModelUtils.isValidDefaultValue(fieldDef.field.getType(), defaultValue)) {
                                remarks.add(error(
                                                table,
                                                col,
                                                format("{0}.defaultValue=\"{1}\" is invalid!", IQColumn.class.getSimpleName(),
-                                                               fieldDef.defaultValue)));
+                                                               defaultValue)));
                        }
                }
        }
index 32377423a54adf48996404d392a115e3c8ca8588..fa794cfb3276eb31e1f366a901a562bb43bd0bc9 100644 (file)
@@ -116,7 +116,7 @@ public class Utils {
                                                        }\r
                                                }\r
                                        }\r
-                                       throw new IciqlException("Exception trying to create " + clazz.getName() + ": " + e, e);\r
+                                       throw new IciqlException("Missing default constructor?  Exception trying to create " + clazz.getName() + ": " + e, e);\r
                                }\r
                        }\r
                };\r
diff --git a/tests/com/iciql/test/DefaultValuesTest.java b/tests/com/iciql/test/DefaultValuesTest.java
new file mode 100644 (file)
index 0000000..b39dd7c
--- /dev/null
@@ -0,0 +1,61 @@
+/*\r
+ * Copyright 2011 James Moger.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+package com.iciql.test;\r
+\r
+import static org.junit.Assert.assertTrue;\r
+\r
+import java.util.List;\r
+\r
+import org.junit.Test;\r
+\r
+import com.iciql.Db;\r
+import com.iciql.DbInspector;\r
+import com.iciql.ValidationRemark;\r
+import com.iciql.test.models.DefaultValuesModel;\r
+\r
+/**\r
+ * Tests default object values.\r
+ */\r
+public class DefaultValuesTest {\r
+\r
+       @Test\r
+       public void testDefaultObjectValues() {\r
+               Db db = Db.open("jdbc:h2:mem:", "sa", "sa");\r
+\r
+               // insert random model\r
+               DefaultValuesModel model = new DefaultValuesModel();\r
+               db.insert(model);\r
+\r
+               DefaultValuesModel v = new DefaultValuesModel();\r
+\r
+               // retrieve model and compare\r
+               DefaultValuesModel retrievedModel = db.from(v).selectFirst();\r
+               assertTrue(model.myInteger.equals(retrievedModel.myInteger));\r
+               assertTrue(model.myDate.equals(retrievedModel.myDate));\r
+               assertTrue(model.myEnumIdTree.equals(retrievedModel.myEnumIdTree));\r
+               assertTrue(model.myNameTree.equals(retrievedModel.myNameTree));\r
+               assertTrue(model.myOrdinalTree.equals(retrievedModel.myOrdinalTree));\r
+               assertTrue(retrievedModel.myNullTree == null);\r
+\r
+               DbInspector inspector = new DbInspector(db);\r
+               List<ValidationRemark> remarks = inspector.validateModel(model, false);\r
+               db.close();\r
+               for (ValidationRemark remark : remarks) {\r
+                       System.out.println(remark.toString());\r
+               }\r
+       }\r
+}\r
diff --git a/tests/com/iciql/test/models/DefaultValuesModel.java b/tests/com/iciql/test/models/DefaultValuesModel.java
new file mode 100644 (file)
index 0000000..2669257
--- /dev/null
@@ -0,0 +1,58 @@
+/*\r
+ * Copyright 2011 James Moger.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.iciql.test.models;\r
+\r
+import java.util.Date;\r
+\r
+import com.iciql.Iciql.EnumType;\r
+import com.iciql.Iciql.IQColumn;\r
+import com.iciql.Iciql.IQEnum;\r
+import com.iciql.Iciql.IQTable;\r
+import com.iciql.test.models.EnumModels.Tree;\r
+\r
+/**\r
+ * Default values model.\r
+ */\r
+@IQTable(name = "DefaultValuesTest")\r
+public class DefaultValuesModel {\r
+\r
+       @IQColumn(primaryKey = true, autoIncrement = true)\r
+       public Long myLong;\r
+       \r
+       @SuppressWarnings("deprecation")\r
+       @IQColumn\r
+       public Date myDate = new Date(100, 7, 1);\r
+       \r
+       @IQColumn\r
+       public Integer myInteger = 12345;\r
+       \r
+       @IQColumn\r
+       public Tree myEnumIdTree = Tree.WALNUT;\r
+\r
+       @IQColumn\r
+       @IQEnum(EnumType.NAME)\r
+       public Tree myNameTree = Tree.MAPLE;\r
+\r
+       @IQColumn\r
+       @IQEnum(EnumType.ORDINAL)\r
+       public Tree myOrdinalTree = Tree.PINE;\r
+\r
+       @IQColumn(allowNull = true)\r
+       public Tree myNullTree;\r
+\r
+       public DefaultValuesModel() {\r
+       }\r
+}\r