]> source.dussan.org Git - iciql.git/commitdiff
Attempt defaultValue instantiation if object is null && spec'd NOT NULL v0.7.6
authorJames Moger <james.moger@gmail.com>
Wed, 21 Dec 2011 20:20:42 +0000 (15:20 -0500)
committerJames Moger <james.moger@gmail.com>
Wed, 21 Dec 2011 20:20:42 +0000 (15:20 -0500)
This is only attempted on db.insert and db.update.

docs/05_releases.mkd
src/com/iciql/Constants.java
src/com/iciql/ModelUtils.java
src/com/iciql/TableDefinition.java

index ebc1fae3294c8553be3c50c66fa5f9a617c6ddf4..33a3e6a4015e3fbab6d0ebef711f17a6f279da45 100644 (file)
@@ -6,6 +6,10 @@
 \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
+- Iciql now tries to instantiate a default value from an annotated default value IFF the field object is null, it is specified *nullable = false*, and a defaultValue exists.  This only applies to *db.insert* or *db.update*.\r
+\r
+**0.7.5** &nbsp; *released 2011-12-12*\r
+\r
 - Iciql now identifies wildcard queries and builds a dynamic column lookup.  Otherwise, the original field-position-based approach is used.  This corrects the performance regression released in 0.7.4 while still fixing the wildcard statement column mapping problem. \r
 \r
 **0.7.4** &nbsp; *released 2011-12-06*\r
index 4034b3b3bfa0b1fe3bead6eca785bf7759075cb8..b0c26d8d4c804842ddd4fd801f5b77c68a3dd0fe 100644 (file)
@@ -25,11 +25,11 @@ 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.7.5";\r
+       public static final String VERSION = "0.7.6";\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-12-12";\r
+       public static final String VERSION_DATE = "2011-12-21";\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
index 678e7af973340ae46f93c0e5a6bd889583f34da4..72e9690d8ed00f999d8ebdf207af374166336540 100644 (file)
@@ -21,6 +21,7 @@ import static com.iciql.util.StringUtils.isNullOrEmpty;
 
 import java.lang.reflect.Method;
 import java.math.BigDecimal;
+import java.text.DateFormat;
 import java.text.MessageFormat;
 import java.text.SimpleDateFormat;
 import java.util.Arrays;
@@ -223,7 +224,7 @@ class ModelUtils {
                                // leading or trailing _
                                continue;
                        }
-                       String [] subchunks = StringUtils.arraySplit(chunk, ' ', false);
+                       String[] subchunks = StringUtils.arraySplit(chunk, ' ', false);
                        for (String subchunk : subchunks) {
                                if (subchunk.length() == 0) {
                                        // leading or trailing space
@@ -251,6 +252,112 @@ class ModelUtils {
                return lower;
        }
 
+       /**
+        * Converts a DEFAULT clause value into an object.
+        * 
+        * @param field
+        *            definition
+        * @return object
+        */
+       static Object getDefaultValue(FieldDefinition def, Class<? extends Date> dateTimeClass) {
+               Class<?> valueType = getClassForSqlType(def.dataType, dateTimeClass);
+               if (String.class.isAssignableFrom(valueType)) {
+                       if (StringUtils.isNullOrEmpty(def.defaultValue)) {
+                               // literal default must be specified within single quotes
+                               return null;
+                       }
+                       if (def.defaultValue.charAt(0) == '\''
+                                       && def.defaultValue.charAt(def.defaultValue.length() - 1) == '\'') {
+                               // strip leading and trailing single quotes
+                               return def.defaultValue.substring(1, def.defaultValue.length() - 2);
+                       }
+                       return def.defaultValue;
+               }
+
+               if (StringUtils.isNullOrEmpty(def.defaultValue)) {
+                       // can not create object from empty string
+                       return null;
+               }
+
+               // strip leading and trailing single quotes
+               String content = def.defaultValue;
+               if (content.charAt(0) == '\'') {
+                       content = content.substring(1);
+               }
+               if (content.charAt(content.length() - 1) == '\'') {
+                       content = content.substring(0, content.length() - 2);
+               }
+
+               if (StringUtils.isNullOrEmpty(content)) {
+                       // can not create object from empty string
+                       return null;
+               }
+
+               if (Boolean.class.isAssignableFrom(valueType) || boolean.class.isAssignableFrom(valueType)) {
+                       return Boolean.parseBoolean(content);
+               }
+
+               if (Number.class.isAssignableFrom(valueType)) {
+                       try {
+                               // delegate to static valueOf() method to parse string
+                               Method m = valueType.getMethod("valueOf", String.class);
+                               return m.invoke(null, content);
+                       } catch (NumberFormatException e) {
+                               throw new IciqlException(e, "Failed to parse {0} as a number!", def.defaultValue);
+                       } catch (Throwable t) {
+                       }
+               }
+
+               String dateRegex = "[0-9]{1,4}[-/\\.][0-9]{1,2}[-/\\.][0-9]{1,2}";
+               String timeRegex = "[0-2]{1}[0-9]{1}:[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}";
+
+               if (java.sql.Date.class.isAssignableFrom(valueType)) {
+                       // this may be a little loose....
+                       // 00-00-00
+                       // 00/00/00
+                       // 00.00.00
+                       Pattern pattern = Pattern.compile(dateRegex);
+                       if (pattern.matcher(content).matches()) {
+                               DateFormat df = DateFormat.getDateInstance();
+                               try {
+                                       return df.parse(content);
+                               } catch (Exception e) {
+                                       throw new IciqlException(e, "Failed to parse {0} as a date!", def.defaultValue);
+                               }
+                       }
+               }
+
+               if (java.sql.Time.class.isAssignableFrom(valueType)) {
+                       // 00:00:00
+                       Pattern pattern = Pattern.compile(timeRegex);
+                       if (pattern.matcher(content).matches()) {
+                               DateFormat df = DateFormat.getTimeInstance();
+                               try {
+                                       return df.parse(content);
+                               } catch (Exception e) {
+                                       throw new IciqlException(e, "Failed to parse {0} as a time!", def.defaultValue);
+                               }
+                       }
+               }
+
+               if (java.util.Date.class.isAssignableFrom(valueType)) {
+                       // this may be a little loose....
+                       // 00-00-00 00:00:00
+                       // 00/00/00T00:00:00
+                       // 00.00.00T00:00:00
+                       Pattern pattern = Pattern.compile(dateRegex + "." + timeRegex);
+                       if (pattern.matcher(content).matches()) {
+                               DateFormat df = DateFormat.getDateTimeInstance();
+                               try {
+                                       return df.parse(content);
+                               } catch (Exception e) {
+                                       throw new IciqlException(e, "Failed to parse {0} as a datetimestamp!", def.defaultValue);
+                               }
+                       }
+               }
+               return content;
+       }
+
        /**
         * Converts the object into a DEFAULT clause value.
         * 
index f8238e5b933e1094950b01f25dabefbc4f0fa8c4..f7bbc1395992dd3515a0afa6d6c341a5abc9cfe5 100644 (file)
@@ -486,6 +486,10 @@ public class TableDefinition<T> {
                        buff.appendExceptFirst(", ");\r
                        buff.append('?');\r
                        Object value = getValue(obj, field);\r
+                       if (value == null && !field.nullable) {\r
+                               // try to interpret and instantiate a default value\r
+                               value = ModelUtils.getDefaultValue(field, db.getDialect().getDateTimeClass());\r
+                       }\r
                        stat.addParameter(value);\r
                }\r
                buff.append(')');\r
@@ -509,6 +513,19 @@ public class TableDefinition<T> {
                                // skip null object autoincrement values\r
                                return true;\r
                        }\r
+               } else {\r
+                       // conditionally skip insert of null\r
+                       Object value = getValue(obj, field);\r
+                       if (value == null) {\r
+                               if (field.nullable) {\r
+                                       // skip null assignment, field is nullable\r
+                                       return true;\r
+                               } else if (StringUtils.isNullOrEmpty(field.defaultValue)) {\r
+                                       IciqlLogger.warn("no default value, skipping null insert assignment for {0}.{1}",\r
+                                                       tableName, field.columnName);\r
+                                       return true;\r
+                               }\r
+                       }\r
                }\r
                return false;\r
        }\r
@@ -536,10 +553,14 @@ public class TableDefinition<T> {
 \r
                for (FieldDefinition field : fields) {\r
                        if (!field.isPrimaryKey) {\r
+                               Object value = getValue(obj, field);\r
+                               if (value == null && !field.nullable) {\r
+                                       // try to interpret and instantiate a default value\r
+                                       value = ModelUtils.getDefaultValue(field, db.getDialect().getDateTimeClass());\r
+                               }\r
                                buff.appendExceptFirst(", ");\r
                                buff.append(db.getDialect().prepareColumnName(field.columnName));\r
                                buff.append(" = ?");\r
-                               Object value = getValue(obj, field);\r
                                stat.addParameter(value);\r
                        }\r
                }\r