Browse Source

Customizable enumId() mapping (issue 2)

tags/v0.6.0
James Moger 13 years ago
parent
commit
a1ab110531

+ 8
- 2
docs/01_model_classes.mkd View File

@@ -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>

+ 30
- 5
src/com/iciql/Iciql.java View File

@@ -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;
}
/**

+ 5
- 2
src/com/iciql/IciqlException.java View File

@@ -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) {

+ 1
- 0
src/com/iciql/ModelUtils.java View File

@@ -149,6 +149,7 @@ class ModelUtils {
}
return "VARCHAR";
case ORDINAL:
case ENUMID:
return "INT";
}
}

+ 15
- 1
src/com/iciql/TableDefinition.java View File

@@ -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) {

+ 29
- 16
src/com/iciql/util/Utils.java View File

@@ -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);
}
/**

+ 1
- 1
tests/com/iciql/test/ModelsTest.java View 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

+ 23
- 4
tests/com/iciql/test/models/SupportedTypes.java View 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;
}


Loading…
Cancel
Save