summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Moger <james.moger@gmail.com>2011-08-04 17:58:22 -0400
committerJames Moger <james.moger@gmail.com>2011-08-04 17:58:22 -0400
commitb055a2a49335c78fdc754e38a7e8ab863b2a5515 (patch)
tree50c1e4bec870701e81e3bbcdde7c90d9a9119f52
parent3d1e36c31e2a8354e03cdfe12565503190c2e957 (diff)
downloadiciql-b055a2a49335c78fdc754e38a7e8ab863b2a5515.tar.gz
iciql-b055a2a49335c78fdc754e38a7e8ab863b2a5515.zip
BLOB support (issue 1) and Enum support (issue 2). Documentation.
-rw-r--r--build.xml4
-rw-r--r--docs/01_model_classes.mkd17
-rw-r--r--docs/05_releases.mkd2
-rw-r--r--src/com/iciql/Iciql.java52
-rw-r--r--src/com/iciql/ModelUtils.java38
-rw-r--r--src/com/iciql/Query.java3
-rw-r--r--src/com/iciql/TableDefinition.java38
-rw-r--r--src/com/iciql/TableInspector.java6
-rw-r--r--src/com/iciql/build/BuildSite.java7
-rw-r--r--src/com/iciql/util/Utils.java111
-rw-r--r--tests/com/iciql/test/ModelsTest.java2
-rw-r--r--tests/com/iciql/test/models/ProductAnnotationOnly.java3
-rw-r--r--tests/com/iciql/test/models/SupportedTypes.java64
13 files changed, 331 insertions, 16 deletions
diff --git a/build.xml b/build.xml
index 8c7eaec..18698c6 100644
--- a/build.xml
+++ b/build.xml
@@ -282,6 +282,10 @@
<arg value="--substitute" />
<arg value="%ENDCODE%=&lt;/pre&gt;" />
+
+ <arg value="--regex" />
+ <arg value="&quot;\b(issue)(\s*[#]?|-){0,1}(\d+)\b!!!&lt;a href='http://code.google.com/p/iciql/issues/detail?id=$3'&gt;issue $3&lt;/a&gt;&quot;" />
+
</java>
</target>
diff --git a/docs/01_model_classes.mkd b/docs/01_model_classes.mkd
index a0db6a1..8afcfa8 100644
--- a/docs/01_model_classes.mkd
+++ b/docs/01_model_classes.mkd
@@ -47,6 +47,12 @@ Alternatively, model classes can be automatically generated by iciql using the m
<tr><td>java.util.Date</td>
<td>TIMESTAMP</td></tr>
+<tr><td>byte []</td>
+<td>BLOB</td></tr>
+
+<tr><td>java.lang.Enum</td>
+<td>VARCHAR/TEXT *@IQEnum(STRING)* or INT *@IQEnum(ORDINAL)*</td></tr>
+
</table>
**NOTE:**<br/>
@@ -55,7 +61,6 @@ Please consult the `com.iciql.ModelUtils` class for details.
### Unsupported Types
- Java primitives (use their object counterparts instead)
-- binary types (BLOB, etc)
- array types
- custom types
@@ -83,7 +88,9 @@ The recommended approach to setup a model class is to annotate the class and fie
### Example Annotated Model
%BEGINCODE%
+import com.iciql.Iciql.EnumType;
import com.iciql.Iciql.IQColumn;
+import com.iciql.Iciql.IQEnum;
import com.iciql.Iciql.IQIndex;
import com.iciql.Iciql.IQTable;
@@ -94,6 +101,11 @@ import com.iciql.Iciql.IQTable;
})
public class Product {
+ @IQEnum(EnumType.ORDINAL)
+ public enum Availability {
+ ACTIVE, DISCONTINUED;
+ }
+
@IQColumn(primaryKey = true)
public Integer productId;
@@ -111,6 +123,9 @@ public class Product {
@IQColumn
private Integer reorderQuantity;
+
+ @IQColumn
+ private Availability availability;
public Product() {
// default constructor
diff --git a/docs/05_releases.mkd b/docs/05_releases.mkd
index db29860..50fda43 100644
--- a/docs/05_releases.mkd
+++ b/docs/05_releases.mkd
@@ -3,6 +3,8 @@
### Current Release
**%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%*
+- added BLOB support (issue 1)
+- added java.lang.Enum support (issue 2)
- api change release (API v2)
- annotations overhaul to reduce verbosity
- @IQSchema(name="public") -> @IQSchema("public")
diff --git a/src/com/iciql/Iciql.java b/src/com/iciql/Iciql.java
index 35ad8cc..8d71aa6 100644
--- a/src/com/iciql/Iciql.java
+++ b/src/com/iciql/Iciql.java
@@ -87,9 +87,13 @@ import java.lang.annotation.Target;
* <td>java.util.Date</td>
* <td>TIMESTAMP</td>
* </tr>
+ * <tr>
+ * <td>byte []</td>
+ * <td>BLOB</td>
+ * </tr>
* </table>
* <p>
- * Unsupported data types: binary types (BLOB, etc), and custom types.
+ * Unsupported data types: java.lang.Enum, Array Types, and custom types.
* <p>
* Table and field mapping: by default, the mapped table name is the class name
* and the public fields are reflectively mapped, by their name, to columns. As
@@ -142,6 +146,7 @@ public interface Iciql {
/**
* An annotation for an iciql version.
* <p>
+ *
* @IQVersion(1)
*/
@Retention(RetentionPolicy.RUNTIME)
@@ -162,6 +167,7 @@ public interface Iciql {
/**
* An annotation for a schema.
* <p>
+ *
* @IQSchema("PUBLIC")
*/
@Retention(RetentionPolicy.RUNTIME)
@@ -189,7 +195,8 @@ public interface Iciql {
* <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"})
+ * <li>@IQIndex(name="addressidx", type=IndexType.UNIQUE,
+ * value={"house_number", "street", "city"})
* </ul>
*/
@Retention(RetentionPolicy.RUNTIME)
@@ -366,6 +373,47 @@ public interface Iciql {
}
/**
+ * Enumeration representing now to map a java.lang.Enum to a column.
+ * <p>
+ * <ul>
+ * <li>STRING
+ * <li>ORDINAL
+ * </ul>
+ */
+ public enum EnumType {
+ STRING, ORDINAL;
+ }
+
+ /**
+ * Annotation to define how a java.lang.Enum is mapped to a column.
+ * <p>
+ * This annotation can be used on:
+ * <ul>
+ * <li>a field instance of an enumeration type
+ * <li>on the enumeration class declaration
+ * </ul>
+ * If you choose to annotate the class declaration, that will be the default
+ * mapping strategy for all @IQColumn instances of the enum. This can still
+ * be overridden for an individual field by specifying the IQEnum
+ * annotation.
+ * <p>
+ * The default mapping is by STRING.
+ *
+ * <pre>
+ * IQEnum(EnumType.STRING)
+ * </pre>
+ *
+ * A string mapping will generate either a VARCHAR, if IQColumn.maxLength >
+ * 0 or a TEXT column if IQColumn.maxLength == 0
+ *
+ */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ ElementType.FIELD, ElementType.TYPE })
+ public @interface IQEnum {
+ EnumType value() default EnumType.STRING;
+ }
+
+ /**
* This method is called to let the table define the primary key, indexes,
* and the table name.
*/
diff --git a/src/com/iciql/ModelUtils.java b/src/com/iciql/ModelUtils.java
index 6b28f0e..45a4882 100644
--- a/src/com/iciql/ModelUtils.java
+++ b/src/com/iciql/ModelUtils.java
@@ -57,7 +57,7 @@ class ModelUtils {
m.put(java.util.Date.class, "TIMESTAMP");
m.put(java.sql.Date.class, "DATE");
m.put(java.sql.Time.class, "TIME");
- // TODO add blobs, binary types, custom types?
+ m.put(byte[].class, "BLOB");
}
/**
@@ -111,14 +111,21 @@ class ModelUtils {
// date
m.put("DATETIME", "TIMESTAMP");
m.put("SMALLDATETIME", "TIMESTAMP");
+
+ // binary types
+ m.put("TINYBLOB", "BLOB");
+ m.put("MEDIUMBLOB", "BLOB");
+ m.put("LONGBLOB", "BLOB");
+ m.put("IMAGE", "BLOB");
+ m.put("OID", "BLOB");
}
- private static final List<String> KEYWORDS = Arrays.asList("abstract", "assert", "boolean", "break", "byte",
- "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "else", "enum",
- "extends", "final", "finally", "float", "for", "goto", "if", "implements", "import", "instanceof", "int",
- "interface", "long", "native", "new", "package", "private", "protected", "public", "return", "short",
- "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "try",
- "void", "volatile", "while", "false", "null", "true");
+ private static final List<String> KEYWORDS = Arrays.asList("abstract", "assert", "boolean", "break",
+ "byte", "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "else",
+ "enum", "extends", "final", "finally", "float", "for", "goto", "if", "implements", "import",
+ "instanceof", "int", "interface", "long", "native", "new", "package", "private", "protected",
+ "public", "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this",
+ "throw", "throws", "transient", "try", "void", "volatile", "while", "false", "null", "true");
/**
* Returns a SQL type mapping for a Java class.
@@ -131,6 +138,20 @@ class ModelUtils {
*/
static String getDataType(FieldDefinition fieldDef, boolean strictTypeMapping) {
Class<?> fieldClass = fieldDef.field.getType();
+ if (fieldClass.isEnum()) {
+ if (fieldDef.enumType == null) {
+ throw new IciqlException(fieldDef.field.getName() + " enum field does not specify @IQEnum!");
+ }
+ switch (fieldDef.enumType) {
+ case STRING:
+ if (fieldDef.maxLength <= 0) {
+ return "TEXT";
+ }
+ return "VARCHAR";
+ case ORDINAL:
+ return "INT";
+ }
+ }
if (SUPPORTED_TYPES.containsKey(fieldClass)) {
String type = SUPPORTED_TYPES.get(fieldClass);
if (type.equals("VARCHAR") && fieldDef.maxLength <= 0) {
@@ -228,7 +249,8 @@ class ModelUtils {
}
Pattern literalDefault = Pattern.compile("'.*'");
Pattern functionDefault = Pattern.compile("[^'].*[^']");
- return literalDefault.matcher(defaultValue).matches() || functionDefault.matcher(defaultValue).matches();
+ return literalDefault.matcher(defaultValue).matches()
+ || functionDefault.matcher(defaultValue).matches();
}
/**
diff --git a/src/com/iciql/Query.java b/src/com/iciql/Query.java
index 97e143b..d9dc84f 100644
--- a/src/com/iciql/Query.java
+++ b/src/com/iciql/Query.java
@@ -18,6 +18,7 @@
package com.iciql;
import java.lang.reflect.Field;
+import java.sql.Blob;
import java.sql.Clob;
import java.sql.ResultSet;
import java.sql.SQLException;
@@ -223,6 +224,8 @@ public class Query<T> {
Object o = rs.getObject(1);
if (Clob.class.isAssignableFrom(o.getClass())) {
value = (X) Utils.convert(o, String.class);
+ } else if (Blob.class.isAssignableFrom(o.getClass())) {
+ value = (X) Utils.convert(o, byte[].class);
} else {
value = (X) o;
}
diff --git a/src/com/iciql/TableDefinition.java b/src/com/iciql/TableDefinition.java
index 456d0f4..a38ac51 100644
--- a/src/com/iciql/TableDefinition.java
+++ b/src/com/iciql/TableDefinition.java
@@ -27,7 +27,9 @@ import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
+import com.iciql.Iciql.EnumType;
import com.iciql.Iciql.IQColumn;
+import com.iciql.Iciql.IQEnum;
import com.iciql.Iciql.IQIndex;
import com.iciql.Iciql.IQIndexes;
import com.iciql.Iciql.IQSchema;
@@ -74,6 +76,7 @@ class TableDefinition<T> {
boolean trimString;
boolean allowNull;
String defaultValue;
+ EnumType enumType;
Object getValue(Object obj) {
try {
@@ -264,6 +267,7 @@ class TableDefinition<T> {
int maxLength = 0;
boolean trimString = false;
boolean allowNull = true;
+ EnumType enumType = null;
String defaultValue = "";
boolean hasAnnotation = f.isAnnotationPresent(IQColumn.class);
if (hasAnnotation) {
@@ -278,6 +282,21 @@ class TableDefinition<T> {
allowNull = col.allowNull();
defaultValue = col.defaultValue();
}
+
+ // configure Java -> SQL enum mapping
+ if (f.getType().isEnum()) {
+ if (f.getType().isAnnotationPresent(IQEnum.class)) {
+ // enum definition is annotated for all instances
+ IQEnum iqenum = f.getType().getAnnotation(IQEnum.class);
+ enumType = iqenum.value();
+ }
+ if (f.isAnnotationPresent(IQEnum.class)) {
+ // this instance of the enum is annotated
+ IQEnum iqenum = f.getAnnotation(IQEnum.class);
+ enumType = iqenum.value();
+ }
+ }
+
boolean isPublic = Modifier.isPublic(f.getModifiers());
boolean reflectiveMatch = isPublic && !byAnnotationsOnly;
if (reflectiveMatch || hasAnnotation) {
@@ -290,6 +309,7 @@ class TableDefinition<T> {
fieldDef.trimString = trimString;
fieldDef.allowNull = allowNull;
fieldDef.defaultValue = defaultValue;
+ fieldDef.enumType = enumType;
fieldDef.dataType = ModelUtils.getDataType(fieldDef, strictTypeMapping);
fields.add(fieldDef);
}
@@ -306,10 +326,26 @@ class TableDefinition<T> {
}
/**
- * Optionally truncates strings to the maximum length
+ * Optionally truncates strings to the maximum length and converts
+ * java.lang.Enum types to Strings or Integers.
*/
private Object getValue(Object obj, FieldDefinition field) {
Object value = field.getValue(obj);
+ if (field.enumType != null) {
+ // convert enumeration to INT or STRING
+ Enum<?> iqenum = (Enum<?>) value;
+ switch (field.enumType) {
+ case STRING:
+ if (field.trimString && field.maxLength > 0) {
+ if (iqenum.name().length() > field.maxLength) {
+ return iqenum.name().substring(0, field.maxLength);
+ }
+ }
+ return iqenum.name();
+ case ORDINAL:
+ return iqenum.ordinal();
+ }
+ }
if (field.trimString && field.maxLength > 0) {
if (value instanceof String) {
// clip strings
diff --git a/src/com/iciql/TableInspector.java b/src/com/iciql/TableInspector.java
index 8e537b4..879e23a 100644
--- a/src/com/iciql/TableInspector.java
+++ b/src/com/iciql/TableInspector.java
@@ -324,8 +324,12 @@ public class TableInspector {
clazz = Object.class;
sb.append("// unsupported type " + col.type);
} else {
+ // Imports
+ // don't import byte []
+ if (!clazz.equals(byte[].class)) {
+ imports.add(clazz.getCanonicalName());
+ }
// @IQColumn
- imports.add(clazz.getCanonicalName());
sb.append('@').append(IQColumn.class.getSimpleName());
// IQColumn annotation parameters
diff --git a/src/com/iciql/build/BuildSite.java b/src/com/iciql/build/BuildSite.java
index 0686def..4ff5e68 100644
--- a/src/com/iciql/build/BuildSite.java
+++ b/src/com/iciql/build/BuildSite.java
@@ -189,6 +189,10 @@ public class BuildSite {
String[] kv = token.split("=", 2);
content = content.replace(kv[0], kv[1]);
}
+ for (String token : params.regex) {
+ String[] kv = token.split("!!!", 2);
+ content = content.replaceAll(kv[0], kv[1]);
+ }
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(new File(destinationFolder,
fileName)), Charset.forName("UTF-8"));
@@ -315,6 +319,9 @@ public class BuildSite {
@Parameter(names = { "--nomarkdown" }, description = "%STARTTOKEN%:%ENDTOKEN%", required = false)
public List<String> nomarkdown = new ArrayList<String>();
+
+ @Parameter(names = { "--regex" }, description = "searchPattern!!!replacePattern", required = false)
+ public List<String> regex = new ArrayList<String>();
}
}
diff --git a/src/com/iciql/util/Utils.java b/src/com/iciql/util/Utils.java
index 3a600fa..39875fb 100644
--- a/src/com/iciql/util/Utils.java
+++ b/src/com/iciql/util/Utils.java
@@ -17,12 +17,15 @@
package com.iciql.util;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.Reader;
import java.io.StringWriter;
import java.lang.reflect.Constructor;
import java.math.BigDecimal;
import java.math.BigInteger;
+import java.sql.Blob;
import java.sql.Clob;
import java.util.ArrayList;
import java.util.Collection;
@@ -148,6 +151,12 @@ public class Utils {
return (T) new java.sql.Timestamp(COUNTER.getAndIncrement());
} else if (clazz == java.util.Date.class) {
return (T) new java.util.Date(COUNTER.getAndIncrement());
+ } else if (clazz == byte[].class) {
+ return (T) new byte[0];
+ } else if (clazz.isEnum()) {
+ // enums can not be instantiated reflectively
+ // return first constant as reference
+ return clazz.getEnumConstants()[0];
} else if (clazz == List.class) {
return (T) new ArrayList();
}
@@ -200,6 +209,11 @@ public class Utils {
if (targetType.isAssignableFrom(currentType)) {
return o;
}
+ // convert enum
+ if (targetType.isEnum()) {
+ return convertEnum(o, targetType);
+ }
+ // convert from CLOB/TEXT/VARCHAR to String
if (targetType == String.class) {
if (Clob.class.isAssignableFrom(currentType)) {
Clob c = (Clob) o;
@@ -212,6 +226,8 @@ public class Utils {
}
return o.toString();
}
+
+ // convert from number to number
if (Number.class.isAssignableFrom(currentType)) {
Number n = (Number) o;
if (targetType == Byte.class) {
@@ -228,6 +244,67 @@ public class Utils {
return n.floatValue();
}
}
+
+ // convert from BLOB
+ if (targetType == byte[].class) {
+ if (Blob.class.isAssignableFrom(currentType)) {
+ Blob b = (Blob) o;
+ try {
+ InputStream is = b.getBinaryStream();
+ return readBlobAndClose(is, -1);
+ } catch (Exception e) {
+ throw new IciqlException("Error converting BLOB to byte[]: " + e.toString(), e);
+ }
+ }
+ }
+
+ throw new IciqlException("Can not convert the value " + o + " from " + currentType + " to "
+ + targetType);
+ }
+
+ private static Object convertEnum(Object o, Class<?> targetType) {
+ if (o == null) {
+ return null;
+ }
+ Class<?> currentType = o.getClass();
+ // convert from VARCHAR/TEXT/INT to Enum
+ Enum<?>[] values = (Enum[]) targetType.getEnumConstants();
+ if (Clob.class.isAssignableFrom(currentType)) {
+ // TEXT/CLOB field
+ Clob c = (Clob) o;
+ String name = null;
+ try {
+ Reader r = c.getCharacterStream();
+ name = readStringAndClose(r, -1);
+ } catch (Exception e) {
+ throw new IciqlException("Error converting CLOB to String: " + e.toString(), e);
+ }
+
+ // find name match
+ 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;
+ }
+ }
+ } else if (Number.class.isAssignableFrom(currentType)) {
+ // INT field
+ int n = ((Number) o).intValue();
+
+ // ORDINAL mapping
+ for (Enum<?> value : values) {
+ if (value.ordinal() == n) {
+ return value;
+ }
+ }
+ }
throw new IciqlException("Can not convert the value " + o + " from " + currentType + " to "
+ targetType);
}
@@ -264,4 +341,38 @@ public class Utils {
in.close();
}
}
+
+ /**
+ * Read a number of bytes from a stream and close it.
+ *
+ * @param in
+ * the stream
+ * @param length
+ * the maximum number of bytes to read, or -1 to read until the
+ * end of file
+ * @return the string read
+ */
+ public static byte[] readBlobAndClose(InputStream in, int length) throws IOException {
+ try {
+ if (length <= 0) {
+ length = Integer.MAX_VALUE;
+ }
+ int block = Math.min(BUFFER_BLOCK_SIZE, 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);
+ len = in.read(buff, 0, len);
+ if (len < 0) {
+ break;
+ }
+ out.write(buff, 0, len);
+ length -= len;
+ }
+ return out.toByteArray();
+ } finally {
+ in.close();
+ }
+ }
}
diff --git a/tests/com/iciql/test/ModelsTest.java b/tests/com/iciql/test/ModelsTest.java
index 851da92..bafc3e0 100644
--- a/tests/com/iciql/test/ModelsTest.java
+++ b/tests/com/iciql/test/ModelsTest.java
@@ -115,7 +115,7 @@ public class ModelsTest {
true);
assertEquals(1, models.size());
// a poor test, but a start
- assertEquals(1564, models.get(0).length());
+ assertEquals(1838, models.get(0).length());
}
@Test
diff --git a/tests/com/iciql/test/models/ProductAnnotationOnly.java b/tests/com/iciql/test/models/ProductAnnotationOnly.java
index 6b8d420..caf07c7 100644
--- a/tests/com/iciql/test/models/ProductAnnotationOnly.java
+++ b/tests/com/iciql/test/models/ProductAnnotationOnly.java
@@ -31,8 +31,7 @@ import com.iciql.Iciql.IndexType;
*/
@IQTable(name = "AnnotatedProduct", primaryKey = "id")
-@IQIndexes({ @IQIndex({ "name", "cat" }),
- @IQIndex(name = "nameidx", type = IndexType.HASH, value = "name") })
+@IQIndexes({ @IQIndex({ "name", "cat" }), @IQIndex(name = "nameidx", type = IndexType.HASH, value = "name") })
public class ProductAnnotationOnly {
@IQColumn(autoIncrement = true)
diff --git a/tests/com/iciql/test/models/SupportedTypes.java b/tests/com/iciql/test/models/SupportedTypes.java
index 66c25d4..bb5ecc6 100644
--- a/tests/com/iciql/test/models/SupportedTypes.java
+++ b/tests/com/iciql/test/models/SupportedTypes.java
@@ -21,7 +21,9 @@ import java.math.BigDecimal;
import java.util.List;
import java.util.Random;
+import com.iciql.Iciql.EnumType;
import com.iciql.Iciql.IQColumn;
+import com.iciql.Iciql.IQEnum;
import com.iciql.Iciql.IQIndex;
import com.iciql.Iciql.IQIndexes;
import com.iciql.Iciql.IQTable;
@@ -39,6 +41,29 @@ public class SupportedTypes {
public static final SupportedTypes SAMPLE = new SupportedTypes();
+ /**
+ * Test of plain enumeration.
+ *
+ * Each field declaraton of this enum must specify a mapping strategy.
+ */
+ public enum Flower {
+ ROSE, TULIP, MUM, PETUNIA, MARIGOLD, DAFFODIL;
+ }
+
+ /**
+ * 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.ORDINAL)
+ public enum Tree {
+ PINE, OAK, BIRCH, WALNUT, MAPLE;
+ }
+
@IQColumn(primaryKey = true, autoIncrement = true)
public Integer id;
@@ -81,6 +106,22 @@ public class SupportedTypes {
@IQColumn
private java.sql.Timestamp mySqlTimestamp;
+ @IQColumn
+ private byte[] myBlob;
+
+ @IQEnum(EnumType.STRING)
+ @IQColumn(trimString = true, maxLength = 25)
+ private Flower myFavoriteFlower;
+
+ @IQEnum(EnumType.ORDINAL)
+ @IQColumn
+ private Flower myOtherFavoriteFlower;
+
+ @IQColumn(maxLength = 25)
+ // @IQEnum is set on the enumeration definition and is shared
+ // by all uses of Tree as an @IQColumn
+ private Tree myFavoriteTree;
+
public static List<SupportedTypes> createList() {
List<SupportedTypes> list = Utils.newArrayList();
for (int i = 0; i < 10; i++) {
@@ -105,6 +146,10 @@ public class SupportedTypes {
s.mySqlDate = new java.sql.Date(rand.nextLong());
s.mySqlTime = new java.sql.Time(rand.nextLong());
s.mySqlTimestamp = new java.sql.Timestamp(rand.nextLong());
+ s.myBlob = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ s.myFavoriteFlower = Flower.MUM;
+ s.myOtherFavoriteFlower = Flower.MARIGOLD;
+ s.myFavoriteTree = Tree.BIRCH;
return s;
}
@@ -123,9 +168,28 @@ public class SupportedTypes {
same &= mySqlDate.toString().equals(s.mySqlDate.toString());
same &= mySqlTime.toString().equals(s.mySqlTime.toString());
same &= myString.equals(s.myString);
+ same &= compare(myBlob, s.myBlob);
+ same &= myFavoriteFlower.equals(s.myFavoriteFlower);
+ same &= myOtherFavoriteFlower.equals(s.myOtherFavoriteFlower);
+ same &= myFavoriteTree.equals(s.myFavoriteTree);
return same;
}
+ private boolean compare(byte[] a, byte[] b) {
+ if (b == null) {
+ return false;
+ }
+ if (a.length != b.length) {
+ return false;
+ }
+ for (int i = 0; i < a.length; i++) {
+ if (a[i] != b[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
/**
* This class demonstrates the table upgrade.
*/