summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Moger <james.moger@gmail.com>2011-08-04 22:22:24 -0400
committerJames Moger <james.moger@gmail.com>2011-08-04 22:22:24 -0400
commita1ab11053107c8995b3f3e850fa14a2374c2013a (patch)
tree750b96cfd386187d2086760d9e1b716e77f785db
parentb055a2a49335c78fdc754e38a7e8ab863b2a5515 (diff)
downloadiciql-a1ab11053107c8995b3f3e850fa14a2374c2013a.tar.gz
iciql-a1ab11053107c8995b3f3e850fa14a2374c2013a.zip
Customizable enumId() mapping (issue 2)
-rw-r--r--docs/01_model_classes.mkd10
-rw-r--r--src/com/iciql/Iciql.java35
-rw-r--r--src/com/iciql/IciqlException.java7
-rw-r--r--src/com/iciql/ModelUtils.java1
-rw-r--r--src/com/iciql/TableDefinition.java16
-rw-r--r--src/com/iciql/util/Utils.java45
-rw-r--r--tests/com/iciql/test/ModelsTest.java2
-rw-r--r--tests/com/iciql/test/models/SupportedTypes.java27
8 files changed, 112 insertions, 31 deletions
diff --git a/docs/01_model_classes.mkd b/docs/01_model_classes.mkd
index 8afcfa8..bf8d72c 100644
--- a/docs/01_model_classes.mkd
+++ b/docs/01_model_classes.mkd
@@ -50,8 +50,14 @@ Alternatively, model classes can be automatically generated by iciql using the m
<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>
+<tr><td>java.lang.Enum.name()</td>
+<td>VARCHAR (maxLength > 0) or TEXT (maxLength == 0)<br/>EnumType.STRING</td></tr>
+
+<tr><td>java.lang.Enum.ordinal()</td>
+<td>INT<br/>EnumType.ORDINAL</td></tr>
+
+<tr><td>java.lang.Enum implements<br/>*com.iciql.Iciql.EnumId.enumId()*</td>
+<td>INT<br/>EnumType.ENUMID</td></tr>
</table>
diff --git a/src/com/iciql/Iciql.java b/src/com/iciql/Iciql.java
index 8d71aa6..ff2452e 100644
--- a/src/com/iciql/Iciql.java
+++ b/src/com/iciql/Iciql.java
@@ -91,9 +91,22 @@ import java.lang.annotation.Target;
* <td>byte []</td>
* <td>BLOB</td>
* </tr>
+ * <tr>
+ * <td>java.lang.Enum.name()</td>
+ * <td>VARCHAR (maxLength > 0) or TEXT (maxLength == 0)<br/>EnumType.STRING</td>
+ * </tr>
+ * <tr>
+ * <td>java.lang.Enum.ordinal()</td>
+ * <td>INT<br/>EnumType.ORDINAL</td>
+ * </tr>
+ * <tr>
+ * <td>java.lang.Enum implements<br/>com.iciql.Iciql.EnumID.enumId()</td>
+ * <td>INT<br/>EnumType.ENUMID</td>
+ * </tr>
+ * </tr>
* </table>
* <p>
- * Unsupported data types: java.lang.Enum, Array Types, and custom types.
+ * Unsupported data types: primitives, 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
@@ -373,15 +386,27 @@ public interface Iciql {
}
/**
- * Enumeration representing now to map a java.lang.Enum to a column.
+ * Interface for using the EnumType.ENUMID enumeration mapping strategy.
+ * <p>
+ * Enumerations wishing to use EnumType.ENUMID must implement this
+ * interface.
+ */
+ public interface EnumId {
+ int enumId();
+ }
+
+ /**
+ * Enumeration representing how to map a java.lang.Enum to a column.
* <p>
* <ul>
- * <li>STRING
- * <li>ORDINAL
+ * <li>STRING - name() : string
+ * <li>ORDINAL - ordinal() : int
+ * <li>ENUMID - enumId() : int
* </ul>
+ * @see com.iciql.Iciql.EnumId interface
*/
public enum EnumType {
- STRING, ORDINAL;
+ STRING, ORDINAL, ENUMID;
}
/**
diff --git a/src/com/iciql/IciqlException.java b/src/com/iciql/IciqlException.java
index 2aee36d..9f411d9 100644
--- a/src/com/iciql/IciqlException.java
+++ b/src/com/iciql/IciqlException.java
@@ -16,6 +16,8 @@
package com.iciql;
+import java.text.MessageFormat;
+
/**
* Iciql wraps all exceptions with this class.
*/
@@ -23,8 +25,9 @@ public class IciqlException extends RuntimeException {
private static final long serialVersionUID = 1L;
- public IciqlException(String message) {
- super(message);
+ public IciqlException(String message, Object... parameters) {
+ super(parameters.length > 0 ? MessageFormat.format(message, parameters) : message);
+
}
public IciqlException(Throwable t) {
diff --git a/src/com/iciql/ModelUtils.java b/src/com/iciql/ModelUtils.java
index 45a4882..9cbd295 100644
--- a/src/com/iciql/ModelUtils.java
+++ b/src/com/iciql/ModelUtils.java
@@ -149,6 +149,7 @@ class ModelUtils {
}
return "VARCHAR";
case ORDINAL:
+ case ENUMID:
return "INT";
}
}
diff --git a/src/com/iciql/TableDefinition.java b/src/com/iciql/TableDefinition.java
index a38ac51..72b5348 100644
--- a/src/com/iciql/TableDefinition.java
+++ b/src/com/iciql/TableDefinition.java
@@ -27,6 +27,7 @@ import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
+import com.iciql.Iciql.EnumId;
import com.iciql.Iciql.EnumType;
import com.iciql.Iciql.IQColumn;
import com.iciql.Iciql.IQEnum;
@@ -97,8 +98,15 @@ class TableDefinition<T> {
if (!field.isAccessible()) {
field.setAccessible(true);
}
- o = Utils.convert(o, field.getType());
+ Class<?> targetType = field.getType();
+ if (targetType.isEnum()) {
+ o = Utils.convertEnum(o, targetType, enumType);
+ } else {
+ o = Utils.convert(o, targetType);
+ }
field.set(obj, o);
+ } catch (IciqlException e) {
+ throw e;
} catch (Exception e) {
throw new IciqlException(e);
}
@@ -344,6 +352,12 @@ class TableDefinition<T> {
return iqenum.name();
case ORDINAL:
return iqenum.ordinal();
+ case ENUMID:
+ if (!EnumId.class.isAssignableFrom(value.getClass())) {
+ throw new IciqlException(field.field.getName() + " does not implement EnumId!");
+ }
+ EnumId enumid = (EnumId) value;
+ return enumid.enumId();
}
}
if (field.trimString && field.maxLength > 0) {
diff --git a/src/com/iciql/util/Utils.java b/src/com/iciql/util/Utils.java
index 39875fb..302dd4d 100644
--- a/src/com/iciql/util/Utils.java
+++ b/src/com/iciql/util/Utils.java
@@ -37,6 +37,8 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
+import com.iciql.Iciql.EnumId;
+import com.iciql.Iciql.EnumType;
import com.iciql.IciqlException;
/**
@@ -209,10 +211,7 @@ 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)) {
@@ -257,16 +256,18 @@ public class Utils {
}
}
}
-
- throw new IciqlException("Can not convert the value " + o + " from " + currentType + " to "
- + targetType);
+ throw new IciqlException("Can not convert the value {0} from {1} to {2}", o, currentType, targetType);
}
-
- private static Object convertEnum(Object o, Class<?> targetType) {
+
+ public static Object convertEnum(Object o, Class<?> targetType, EnumType type) {
if (o == null) {
return null;
}
Class<?> currentType = o.getClass();
+ if (targetType.isAssignableFrom(currentType)) {
+ return o;
+ }
+
// convert from VARCHAR/TEXT/INT to Enum
Enum<?>[] values = (Enum[]) targetType.getEnumConstants();
if (Clob.class.isAssignableFrom(currentType)) {
@@ -297,16 +298,28 @@ public class Utils {
} 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;
+ if (type.equals(EnumType.ORDINAL)) {
+ // ORDINAL mapping
+ for (Enum<?> value : values) {
+ if (value.ordinal() == n) {
+ return value;
+ }
+ }
+ } else 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() == n) {
+ return value;
+ }
}
}
}
- throw new IciqlException("Can not convert the value " + o + " from " + currentType + " to "
- + targetType);
+ throw new IciqlException("Can not convert the value {0} from {1} to {2}", o, currentType, targetType);
}
/**
diff --git a/tests/com/iciql/test/ModelsTest.java b/tests/com/iciql/test/ModelsTest.java
index bafc3e0..716b1bc 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(1838, models.get(0).length());
+ assertEquals(1904, models.get(0).length());
}
@Test
diff --git a/tests/com/iciql/test/models/SupportedTypes.java b/tests/com/iciql/test/models/SupportedTypes.java
index bb5ecc6..97a8675 100644
--- a/tests/com/iciql/test/models/SupportedTypes.java
+++ b/tests/com/iciql/test/models/SupportedTypes.java
@@ -21,6 +21,7 @@ import java.math.BigDecimal;
import java.util.List;
import java.util.Random;
+import com.iciql.Iciql.EnumId;
import com.iciql.Iciql.EnumType;
import com.iciql.Iciql.IQColumn;
import com.iciql.Iciql.IQEnum;
@@ -51,8 +52,8 @@ public class SupportedTypes {
}
/**
- * Test of @IQEnum annotated enumeration.
- * This strategy is the default strategy for all fields of the Tree enum.
+ * 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.
@@ -60,8 +61,19 @@ public class SupportedTypes {
* Here ORDINAL specifies that this enum will be mapped to an INT column.
*/
@IQEnum(EnumType.ORDINAL)
- public enum Tree {
- PINE, OAK, BIRCH, WALNUT, MAPLE;
+ public enum Tree implements EnumId {
+ PINE(10), OAK(20), BIRCH(30), WALNUT(40), MAPLE(50);
+
+ private int enumid;
+
+ Tree(int id) {
+ this.enumid = id;
+ }
+
+ @Override
+ public int enumId() {
+ return enumid;
+ }
}
@IQColumn(primaryKey = true, autoIncrement = true)
@@ -121,6 +133,11 @@ public class SupportedTypes {
// @IQEnum is set on the enumeration definition and is shared
// by all uses of Tree as an @IQColumn
private Tree myFavoriteTree;
+
+ @IQEnum(EnumType.ENUMID)
+ @IQColumn
+ // override the default enum strategy and use the custom enumid
+ private Tree myOtherFavoriteTree;
public static List<SupportedTypes> createList() {
List<SupportedTypes> list = Utils.newArrayList();
@@ -150,6 +167,7 @@ public class SupportedTypes {
s.myFavoriteFlower = Flower.MUM;
s.myOtherFavoriteFlower = Flower.MARIGOLD;
s.myFavoriteTree = Tree.BIRCH;
+ s.myOtherFavoriteTree = Tree.WALNUT;
return s;
}
@@ -172,6 +190,7 @@ public class SupportedTypes {
same &= myFavoriteFlower.equals(s.myFavoriteFlower);
same &= myOtherFavoriteFlower.equals(s.myOtherFavoriteFlower);
same &= myFavoriteTree.equals(s.myFavoriteTree);
+ same &= myOtherFavoriteTree.equals(s.myOtherFavoriteTree);
return same;
}