Push the notNull property of nested fields into the leaf-level columns

If a nested field is marked @Column(notNull=false) then its leaf
level columns must accept a NULL value.

Signed-off-by: Shawn O. Pearce <sop@google.com>
diff --git a/src/com/google/gwtorm/jdbc/gen/AccessGen.java b/src/com/google/gwtorm/jdbc/gen/AccessGen.java
index 2fd4c60..f4001d9 100644
--- a/src/com/google/gwtorm/jdbc/gen/AccessGen.java
+++ b/src/com/google/gwtorm/jdbc/gen/AccessGen.java
@@ -287,7 +287,7 @@
       cols.addAll(model.getDependentFields());
       cols.addAll(model.getRowVersionFields());
       for (final ColumnModel field : cols) {
-        if (field.isNested() && field.getColumnAnnotation().notNull()) {
+        if (field.isNested() && field.isNotNull()) {
           for (final ColumnModel c : field.getAllLeafColumns()) {
             cgs.setFieldReference(c);
             dialect.getSqlTypeInfo(c).generatePreparedStatementSet(cgs);
@@ -397,7 +397,7 @@
           dialect.getSqlTypeInfo(c).generateResultSetGet(cgs);
         }
 
-        if (!field.getColumnAnnotation().notNull()) {
+        if (!field.isNotNull()) {
           final Label islive = new Label();
           cgs.pushSqlHandle();
           mv.visitMethodInsn(INVOKEINTERFACE, Type.getType(ResultSet.class)
diff --git a/src/com/google/gwtorm/schema/ColumnModel.java b/src/com/google/gwtorm/schema/ColumnModel.java
index 23e166b..1cb84e9 100644
--- a/src/com/google/gwtorm/schema/ColumnModel.java
+++ b/src/com/google/gwtorm/schema/ColumnModel.java
@@ -29,6 +29,7 @@
   protected Collection<ColumnModel> nestedColumns;
   protected boolean rowVersion;
   protected boolean inPrimaryKey;
+  protected boolean notNull;
 
   protected ColumnModel() {
     nestedColumns = Collections.<ColumnModel> emptyList();
@@ -43,6 +44,7 @@
     column = col;
     origName = Util.any(column.name(), Util.makeSqlFriendly(fieldName));
     columnName = origName;
+    notNull = column.notNull();
   }
 
   protected void initNestedColumns(final Collection<? extends ColumnModel> col)
@@ -54,6 +56,14 @@
 
     nestedColumns = new ArrayList<ColumnModel>(col);
     recomputeColumnNames();
+    if (!isNotNull()) {
+      // If we permit NULL we need to make sure our contained columns
+      // would also accept NULL, even if they wouldn't otherwise.
+      //
+      for (final ColumnModel c : getAllLeafColumns()) {
+        c.notNull = false;
+      }
+    }
   }
 
   private void recomputeColumnNames() {
@@ -129,6 +139,10 @@
     return column;
   }
 
+  public boolean isNotNull() {
+    return notNull;
+  }
+
   public abstract String getFieldName();
 
   public abstract Class<?> getPrimitiveType();
diff --git a/src/com/google/gwtorm/schema/sql/SqlByteArrayTypeInfo.java b/src/com/google/gwtorm/schema/sql/SqlByteArrayTypeInfo.java
index b7f0758..24b60c1 100644
--- a/src/com/google/gwtorm/schema/sql/SqlByteArrayTypeInfo.java
+++ b/src/com/google/gwtorm/schema/sql/SqlByteArrayTypeInfo.java
@@ -14,7 +14,6 @@
 
 package com.google.gwtorm.schema.sql;
 
-import com.google.gwtorm.client.Column;
 import com.google.gwtorm.jdbc.gen.CodeGenSupport;
 import com.google.gwtorm.schema.ColumnModel;
 
@@ -43,10 +42,9 @@
 
   @Override
   public String getSqlType(final ColumnModel col, final SqlDialect dialect) {
-    final Column column = col.getColumnAnnotation();
     final StringBuilder r = new StringBuilder();
     r.append(dialect.getSqlTypeName(getSqlTypeConstant()));
-    if (column.notNull()) {
+    if (col.isNotNull()) {
       r.append(" DEFAULT ''");
       r.append(" NOT NULL");
     }
diff --git a/src/com/google/gwtorm/schema/sql/SqlDateTypeInfo.java b/src/com/google/gwtorm/schema/sql/SqlDateTypeInfo.java
index 0ed0258..127befe 100644
--- a/src/com/google/gwtorm/schema/sql/SqlDateTypeInfo.java
+++ b/src/com/google/gwtorm/schema/sql/SqlDateTypeInfo.java
@@ -14,7 +14,6 @@
 
 package com.google.gwtorm.schema.sql;
 
-import com.google.gwtorm.client.Column;
 import com.google.gwtorm.schema.ColumnModel;
 
 import java.sql.Types;
@@ -32,10 +31,9 @@
 
   @Override
   public String getSqlType(final ColumnModel col, final SqlDialect dialect) {
-    final Column column = col.getColumnAnnotation();
     final StringBuilder r = new StringBuilder();
     r.append(dialect.getSqlTypeName(getSqlTypeConstant()));
-    if (column.notNull()) {
+    if (col.isNotNull()) {
       r.append(" DEFAULT '1900-01-01'");
       r.append(" NOT NULL");
     }
diff --git a/src/com/google/gwtorm/schema/sql/SqlStringTypeInfo.java b/src/com/google/gwtorm/schema/sql/SqlStringTypeInfo.java
index d23c7ea..2ca7522 100644
--- a/src/com/google/gwtorm/schema/sql/SqlStringTypeInfo.java
+++ b/src/com/google/gwtorm/schema/sql/SqlStringTypeInfo.java
@@ -54,7 +54,7 @@
       r.append(dialect.getSqlTypeName(Types.LONGVARCHAR));
     }
 
-    if (column.notNull()) {
+    if (col.isNotNull()) {
       r.append(" DEFAULT ''");
       r.append(" NOT NULL");
     }
diff --git a/src/com/google/gwtorm/schema/sql/SqlTimestampTypeInfo.java b/src/com/google/gwtorm/schema/sql/SqlTimestampTypeInfo.java
index d5646a7..9a71ad3 100644
--- a/src/com/google/gwtorm/schema/sql/SqlTimestampTypeInfo.java
+++ b/src/com/google/gwtorm/schema/sql/SqlTimestampTypeInfo.java
@@ -14,7 +14,6 @@
 
 package com.google.gwtorm.schema.sql;
 
-import com.google.gwtorm.client.Column;
 import com.google.gwtorm.schema.ColumnModel;
 
 import java.sql.Types;
@@ -32,10 +31,9 @@
 
   @Override
   public String getSqlType(final ColumnModel col, final SqlDialect dialect) {
-    final Column column = col.getColumnAnnotation();
     final StringBuilder r = new StringBuilder();
     r.append(dialect.getSqlTypeName(getSqlTypeConstant()));
-    if (column.notNull()) {
+    if (col.isNotNull()) {
       r.append(" DEFAULT '1900-01-01 00:00:00'");
       r.append(" NOT NULL");
     }