<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
* <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
}\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
\r
package com.iciql;\r
\r
+import java.text.MessageFormat;\r
+\r
/**\r
* Iciql wraps all exceptions with this class.\r
*/\r
\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
}
return "VARCHAR";
case ORDINAL:
+ case ENUMID:
return "INT";
}
}
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
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
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
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
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
}\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
} 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
true);
assertEquals(1, models.size());
// a poor test, but a start
- assertEquals(1838, models.get(0).length());
+ assertEquals(1904, models.get(0).length());
}
@Test
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;
}
/**
- * 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.
* 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)
// @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();
s.myFavoriteFlower = Flower.MUM;
s.myOtherFavoriteFlower = Flower.MARIGOLD;
s.myFavoriteTree = Tree.BIRCH;
+ s.myOtherFavoriteTree = Tree.WALNUT;
return s;
}
same &= myFavoriteFlower.equals(s.myFavoriteFlower);
same &= myOtherFavoriteFlower.equals(s.myOtherFavoriteFlower);
same &= myFavoriteTree.equals(s.myFavoriteTree);
+ same &= myOtherFavoriteTree.equals(s.myOtherFavoriteTree);
return same;
}