]> source.dussan.org Git - iciql.git/commitdiff
Customizable enumId() mapping (issue 2)
authorJames Moger <james.moger@gmail.com>
Fri, 5 Aug 2011 02:22:24 +0000 (22:22 -0400)
committerJames Moger <james.moger@gmail.com>
Fri, 5 Aug 2011 02:22:24 +0000 (22:22 -0400)
docs/01_model_classes.mkd
src/com/iciql/Iciql.java
src/com/iciql/IciqlException.java
src/com/iciql/ModelUtils.java
src/com/iciql/TableDefinition.java
src/com/iciql/util/Utils.java
tests/com/iciql/test/ModelsTest.java
tests/com/iciql/test/models/SupportedTypes.java

index 8afcfa829eaf5a92c913219ffdaf670994dc60a8..bf8d72cf97b3d13e98375e1802f9e8e231150bd5 100644 (file)
@@ -50,8 +50,14 @@ Alternatively, model classes can be automatically generated by iciql using the m
 <tr><td>byte []</td>\r
 <td>BLOB</td></tr>\r
 \r
-<tr><td>java.lang.Enum</td>\r
-<td>VARCHAR/TEXT *@IQEnum(STRING)* or INT *@IQEnum(ORDINAL)*</td></tr>\r
+<tr><td>java.lang.Enum.name()</td>\r
+<td>VARCHAR (maxLength > 0) or TEXT (maxLength == 0)<br/>EnumType.STRING</td></tr>\r
+\r
+<tr><td>java.lang.Enum.ordinal()</td>\r
+<td>INT<br/>EnumType.ORDINAL</td></tr>\r
+\r
+<tr><td>java.lang.Enum implements<br/>*com.iciql.Iciql.EnumId.enumId()*</td>\r
+<td>INT<br/>EnumType.ENUMID</td></tr>\r
 \r
 </table>\r
 \r
index 8d71aa6f46f4c2748b7ee3a0da5209f75493f9eb..ff2452ee2bf627e16a22e6b1d47f7da2bfdec0ab 100644 (file)
@@ -91,9 +91,22 @@ import java.lang.annotation.Target;
  * <td>byte []</td>\r
  * <td>BLOB</td>\r
  * </tr>\r
+ * <tr>\r
+ * <td>java.lang.Enum.name()</td>\r
+ * <td>VARCHAR (maxLength > 0) or TEXT (maxLength == 0)<br/>EnumType.STRING</td>\r
+ * </tr>\r
+ * <tr>\r
+ * <td>java.lang.Enum.ordinal()</td>\r
+ * <td>INT<br/>EnumType.ORDINAL</td>\r
+ * </tr>\r
+ * <tr>\r
+ * <td>java.lang.Enum implements<br/>com.iciql.Iciql.EnumID.enumId()</td>\r
+ * <td>INT<br/>EnumType.ENUMID</td>\r
+ * </tr>\r
+ * </tr>\r
  * </table>\r
  * <p>\r
- * Unsupported data types: java.lang.Enum, Array Types, and custom types.\r
+ * Unsupported data types: primitives, Array Types, and custom types.\r
  * <p>\r
  * Table and field mapping: by default, the mapped table name is the class name\r
  * and the public fields are reflectively mapped, by their name, to columns. As\r
@@ -373,15 +386,27 @@ public interface Iciql {
        }\r
 \r
        /**\r
-        * Enumeration representing now to map a java.lang.Enum to a column.\r
+        * Interface for using the EnumType.ENUMID enumeration mapping strategy.\r
+        * <p>\r
+        * Enumerations wishing to use EnumType.ENUMID must implement this\r
+        * interface.\r
+        */\r
+       public interface EnumId {\r
+               int enumId();\r
+       }\r
+\r
+       /**\r
+        * Enumeration representing how to map a java.lang.Enum to a column.\r
         * <p>\r
         * <ul>\r
-        * <li>STRING\r
-        * <li>ORDINAL\r
+        * <li>STRING - name() : string\r
+        * <li>ORDINAL - ordinal() : int\r
+        * <li>ENUMID - enumId() : int\r
         * </ul>\r
+        *  @see com.iciql.Iciql.EnumId interface\r
         */\r
        public enum EnumType {\r
-               STRING, ORDINAL;\r
+               STRING, ORDINAL, ENUMID;\r
        }\r
 \r
        /**\r
index 2aee36dea8582c5e21f1f3f1f1f39c2e0b0064a6..9f411d91828a9ef684a38fe06e1e7bf3b01ff988 100644 (file)
@@ -16,6 +16,8 @@
 \r
 package com.iciql;\r
 \r
+import java.text.MessageFormat;\r
+\r
 /**\r
  * Iciql wraps all exceptions with this class.\r
  */\r
@@ -23,8 +25,9 @@ public class IciqlException extends RuntimeException {
 \r
        private static final long serialVersionUID = 1L;\r
 \r
-       public IciqlException(String message) {\r
-               super(message);\r
+       public IciqlException(String message, Object... parameters) {\r
+               super(parameters.length > 0 ? MessageFormat.format(message, parameters) : message);\r
+\r
        }\r
 \r
        public IciqlException(Throwable t) {\r
index 45a488272ff86b923f5dea879f8293fdab9851c2..9cbd295bb58b626895b409b5adfab95ee8ee9f28 100644 (file)
@@ -149,6 +149,7 @@ class ModelUtils {
                                }
                                return "VARCHAR";
                        case ORDINAL:
+                       case ENUMID:
                                return "INT";
                        }
                }
index a38ac51a1242c2f7fb8bddd6b9217f4159077bd6..72b53482cabff45152e7b9e32507658207d35e0e 100644 (file)
@@ -27,6 +27,7 @@ import java.util.IdentityHashMap;
 import java.util.List;\r
 import java.util.Map;\r
 \r
+import com.iciql.Iciql.EnumId;\r
 import com.iciql.Iciql.EnumType;\r
 import com.iciql.Iciql.IQColumn;\r
 import com.iciql.Iciql.IQEnum;\r
@@ -97,8 +98,15 @@ class TableDefinition<T> {
                                if (!field.isAccessible()) {\r
                                        field.setAccessible(true);\r
                                }\r
-                               o = Utils.convert(o, field.getType());\r
+                               Class<?> targetType = field.getType();\r
+                               if (targetType.isEnum()) {\r
+                                       o = Utils.convertEnum(o, targetType, enumType);\r
+                               } else {\r
+                                       o = Utils.convert(o, targetType);\r
+                               }\r
                                field.set(obj, o);\r
+                       } catch (IciqlException e) {\r
+                               throw e;\r
                        } catch (Exception e) {\r
                                throw new IciqlException(e);\r
                        }\r
@@ -344,6 +352,12 @@ class TableDefinition<T> {
                                return iqenum.name();\r
                        case 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
                        }\r
                }\r
                if (field.trimString && field.maxLength > 0) {\r
index 39875fbb3d6f9de9f1716ca90ff76fd0652e30fe..302dd4d14ef25746c112816a043ebe3c6030b055 100644 (file)
@@ -37,6 +37,8 @@ import java.util.List;
 import java.util.Map;\r
 import java.util.concurrent.atomic.AtomicLong;\r
 \r
+import com.iciql.Iciql.EnumId;\r
+import com.iciql.Iciql.EnumType;\r
 import com.iciql.IciqlException;\r
 \r
 /**\r
@@ -209,10 +211,7 @@ public class Utils {
                if (targetType.isAssignableFrom(currentType)) {\r
                        return o;\r
                }\r
-               // convert enum\r
-               if (targetType.isEnum()) {\r
-                       return convertEnum(o, targetType);\r
-               }\r
+\r
                // convert from CLOB/TEXT/VARCHAR to String\r
                if (targetType == String.class) {\r
                        if (Clob.class.isAssignableFrom(currentType)) {\r
@@ -257,16 +256,18 @@ public class Utils {
                                }\r
                        }\r
                }\r
-\r
-               throw new IciqlException("Can not convert the value " + o + " from " + currentType + " to "\r
-                               + targetType);\r
+               throw new IciqlException("Can not convert the value {0} from {1} to {2}", o, currentType, targetType);\r
        }\r
-       \r
-       private static Object convertEnum(Object o, Class<?> targetType) {\r
+\r
+       public static Object convertEnum(Object o, Class<?> targetType, EnumType type) {\r
                if (o == null) {\r
                        return null;\r
                }\r
                Class<?> currentType = o.getClass();\r
+               if (targetType.isAssignableFrom(currentType)) {\r
+                       return o;\r
+               }\r
+\r
                // convert from VARCHAR/TEXT/INT to Enum\r
                Enum<?>[] values = (Enum[]) targetType.getEnumConstants();\r
                if (Clob.class.isAssignableFrom(currentType)) {\r
@@ -297,16 +298,28 @@ public class Utils {
                } else if (Number.class.isAssignableFrom(currentType)) {\r
                        // INT field\r
                        int n = ((Number) o).intValue();\r
-\r
-                       // ORDINAL mapping\r
-                       for (Enum<?> value : values) {\r
-                               if (value.ordinal() == n) {\r
-                                       return value;\r
+                       if (type.equals(EnumType.ORDINAL)) {\r
+                               // ORDINAL mapping\r
+                               for (Enum<?> value : values) {\r
+                                       if (value.ordinal() == n) {\r
+                                               return value;\r
+                                       }\r
+                               }\r
+                       } else if (type.equals(EnumType.ENUMID)) {\r
+                               if (!EnumId.class.isAssignableFrom(targetType)) {\r
+                                       throw new IciqlException("Can not convert the value {0} from {1} to {2} using ENUMID", o,\r
+                                                       currentType, targetType);\r
+                               }\r
+                               // ENUMID mapping\r
+                               for (Enum<?> value : values) {\r
+                                       EnumId enumid = (EnumId) value;\r
+                                       if (enumid.enumId() == n) {\r
+                                               return value;\r
+                                       }\r
                                }\r
                        }\r
                }\r
-               throw new IciqlException("Can not convert the value " + o + " from " + currentType + " to "\r
-                               + targetType);\r
+               throw new IciqlException("Can not convert the value {0} from {1} to {2}", o, currentType, targetType);\r
        }\r
 \r
        /**\r
index bafc3e00bd0af911ac6bf26e5fd8a0c77679e941..716b1bc50c003ce72953784aa7e22400fd996c5b 100644 (file)
@@ -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
index bb5ecc6904d5cd4a5c3eaf7e69b4ecdf6ed91bf7..97a867502d44c9f81acb372c0ec753bac234aed1 100644 (file)
@@ -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;
        }