You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@empire-db.apache.org by do...@apache.org on 2019/11/22 10:49:30 UTC
[empire-db] branch master updated: EMPIREDB-304 improved enum type
support
This is an automated email from the ASF dual-hosted git repository.
doebele pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/empire-db.git
The following commit(s) were added to refs/heads/master by this push:
new 0beefec EMPIREDB-304 improved enum type support
0beefec is described below
commit 0beefec77d107c041fc006eaa15fe8acf61e016b
Author: Rainer Döbele <do...@apache.org>
AuthorDate: Fri Nov 22 11:49:26 2019 +0100
EMPIREDB-304
improved enum type support
---
.../empire/jsf2/controls/RadioInputControl.java | 30 +------
.../empire/jsf2/controls/SelectInputControl.java | 43 ++--------
.../empire/jsf2/utils/TagEncodingHelper.java | 6 ++
.../org/apache/empire/commons/ObjectUtils.java | 43 ++++++++++
.../main/java/org/apache/empire/data/Column.java | 9 ++-
.../org/apache/empire/data/bean/BeanProperty.java | 14 +++-
.../main/java/org/apache/empire/db/DBColumn.java | 14 +++-
.../main/java/org/apache/empire/db/DBRecord.java | 21 +++--
.../java/org/apache/empire/db/DBRecordData.java | 91 +++++++++-------------
.../java/org/apache/empire/db/DBTableColumn.java | 10 ++-
10 files changed, 151 insertions(+), 130 deletions(-)
diff --git a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/controls/RadioInputControl.java b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/controls/RadioInputControl.java
index 334ae22..b43fbdc 100644
--- a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/controls/RadioInputControl.java
+++ b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/controls/RadioInputControl.java
@@ -19,7 +19,6 @@
package org.apache.empire.jsf2.controls;
import java.io.IOException;
-import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.List;
@@ -35,9 +34,7 @@ import org.apache.empire.commons.ObjectUtils;
import org.apache.empire.commons.OptionEntry;
import org.apache.empire.commons.Options;
import org.apache.empire.data.Column;
-import org.apache.empire.exceptions.InternalException;
import org.apache.empire.exceptions.InvalidArgumentException;
-import org.apache.empire.exceptions.ItemNotFoundException;
import org.apache.empire.exceptions.UnexpectedReturnValueException;
import org.apache.empire.jsf2.app.TextResolver;
import org.slf4j.Logger;
@@ -329,30 +326,9 @@ public class RadioInputControl extends InputControl
@Override
protected Object parseInputValue(String value, InputInfo ii)
{
- Object enumType = ii.getColumn().getAttribute(Column.COLATTR_ENUMTYPE);
- if (enumType != null)
- { try
- { // get enum
- Class<?> enumClass = (Class<?>) enumType;
- Field field = enumClass.getDeclaredField(value);
- return field.get(null);
- }
- catch (NoSuchFieldException e)
- {
- throw new ItemNotFoundException(value);
- }
- catch (SecurityException e)
- {
- throw new InternalException(e);
- }
- catch (IllegalArgumentException e)
- {
- throw new InternalException(e);
- }
- catch (IllegalAccessException e)
- {
- throw new InternalException(e);
- }
+ if (ii.getColumn().isEnum())
+ { // convert to enum
+ return ObjectUtils.getEnum(ii.getColumn().getEnumType(), value);
}
return value;
}
diff --git a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/controls/SelectInputControl.java b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/controls/SelectInputControl.java
index 70fae41..91a89e1 100644
--- a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/controls/SelectInputControl.java
+++ b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/controls/SelectInputControl.java
@@ -325,17 +325,10 @@ public class SelectInputControl extends InputControl
{
if ((value instanceof Number))
{ // Check whether it's an Enum
- Object enumType = ii.getColumn().getAttribute(Column.COLATTR_ENUMTYPE);
- if ((enumType instanceof Class<?>))
- { // Convert ordinal value to Enum
- int ordinal = ObjectUtils.getInteger(value);
- @SuppressWarnings("unchecked")
- Class<? extends Enum<?>> enumTypeClazz = (Class<? extends Enum<?>>)enumType;
- Enum<?>[] items = enumTypeClazz.getEnumConstants();
- if (ordinal>=0 && ordinal<items.length)
- value = items[ordinal].name();
- else
- log.warn("Enum lookup failed. Ordinal {} out of range.", ordinal);
+ if (ii.getColumn().isEnum())
+ { // Convert ordinal value to Enum-name
+ Enum<?> enumVal = ObjectUtils.getEnum(ii.getColumn().getEnumType(), value);
+ value = enumVal.name();
}
}
// the value
@@ -356,31 +349,9 @@ public class SelectInputControl extends InputControl
@Override
protected Object parseInputValue(String value, InputInfo ii)
{
- Object enumType = ii.getColumn().getAttribute(Column.COLATTR_ENUMTYPE);
- if (enumType != null)
- {
- try
- { // get enum
- Class<?> enumClass = (Class<?>) enumType;
- Field field = enumClass.getDeclaredField(value);
- return field.get(null);
- }
- catch (NoSuchFieldException e)
- {
- throw new ItemNotFoundException(value);
- }
- catch (SecurityException e)
- {
- throw new InternalException(e);
- }
- catch (IllegalArgumentException e)
- {
- throw new InternalException(e);
- }
- catch (IllegalAccessException e)
- {
- throw new InternalException(e);
- }
+ if (ii.getColumn().isEnum())
+ { // convert to enum
+ return ObjectUtils.getEnum(ii.getColumn().getEnumType(), value);
}
return value;
}
diff --git a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java
index c28bb2e..a8b6429 100644
--- a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java
+++ b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java
@@ -176,6 +176,12 @@ public class TagEncodingHelper implements NamingContainer
}
@Override
+ public Class<Enum<?>> getEnumType()
+ {
+ return getSourceColumn().getEnumType();
+ }
+
+ @Override
public Object validate(Object value)
{
log.warn("validate not supported for {}", expr.getName());
diff --git a/empire-db/src/main/java/org/apache/empire/commons/ObjectUtils.java b/empire-db/src/main/java/org/apache/empire/commons/ObjectUtils.java
index 8a6a3c8..8ce8f1a 100644
--- a/empire-db/src/main/java/org/apache/empire/commons/ObjectUtils.java
+++ b/empire-db/src/main/java/org/apache/empire/commons/ObjectUtils.java
@@ -35,6 +35,7 @@ import org.apache.commons.beanutils.MethodUtils;
import org.apache.empire.exceptions.EmpireException;
import org.apache.empire.exceptions.InternalException;
import org.apache.empire.exceptions.InvalidArgumentException;
+import org.apache.empire.exceptions.ItemNotFoundException;
import org.apache.empire.exceptions.NotSupportedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -445,6 +446,48 @@ public final class ObjectUtils
}
/**
+ * Converts an object to an enum of the given type
+ * @param enumType the enum type
+ * @param value the value to convert
+ * @return the enum
+ */
+ @SuppressWarnings("unchecked")
+ public static <T extends Enum<?>> T getEnum(Class<T> enumType, Object value)
+ { // check for null
+ if (isEmpty(value))
+ return null;
+ // check enum
+ if (value instanceof Enum<?>)
+ { // already an enum: Check type
+ if (value.getClass().equals(enumType))
+ return (T)value;
+ // try to match names
+ value = ((Enum<?>)value).name();
+ }
+ // check column data type
+ T[] items = enumType.getEnumConstants();
+ if (value instanceof Number)
+ { // by ordinal
+ int ordinal = ((Number)value).intValue();
+ // check range
+ if (ordinal<0 || ordinal>=items.length)
+ throw new ItemNotFoundException(String.valueOf(ordinal));
+ // return enum
+ return items[ordinal];
+ }
+ else
+ { // by name
+ String name = StringUtils.toString(value);
+ // find name
+ for (T e : items)
+ if (e.name().equals(name))
+ return e;
+ // error: not found
+ throw new ItemNotFoundException(name);
+ }
+ }
+
+ /**
* Converts an object value to a Date.
* <P>
* If the object value supplied is null or if conversion is not possible then null is returned.
diff --git a/empire-db/src/main/java/org/apache/empire/data/Column.java b/empire-db/src/main/java/org/apache/empire/data/Column.java
index 622ac01..58e6e0d 100644
--- a/empire-db/src/main/java/org/apache/empire/data/Column.java
+++ b/empire-db/src/main/java/org/apache/empire/data/Column.java
@@ -83,11 +83,18 @@ public interface Column extends ColumnExpr
/**
* Returns true if an enum type has been set for this column
* <P>
- * @return eturns true if an enum type has been set for this column
+ * @return true if an enum type has been set for this column
*/
boolean isEnum();
/**
+ * Returns the enum type for this column
+ * <P>
+ * @return the enum type
+ */
+ Class<Enum<?>> getEnumType();
+
+ /**
* Checks if the given value is a valid value for this column
* If not, an exception is thrown
* @return the value the validated and possibly converted value
diff --git a/empire-db/src/main/java/org/apache/empire/data/bean/BeanProperty.java b/empire-db/src/main/java/org/apache/empire/data/bean/BeanProperty.java
index 24c7609..ccbac58 100644
--- a/empire-db/src/main/java/org/apache/empire/data/bean/BeanProperty.java
+++ b/empire-db/src/main/java/org/apache/empire/data/bean/BeanProperty.java
@@ -173,7 +173,19 @@ public class BeanProperty implements Column
@Override
public boolean isEnum()
{
- return (attributes!=null && getAttribute(COLATTR_ENUMTYPE)!=null);
+ return (getEnumType()!=null);
+ }
+
+ /**
+ * Returns the enum type for this column
+ * <P>
+ * @return the enum type
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ public Class<Enum<?>> getEnumType()
+ {
+ return (attributes!=null ? (Class<Enum<?>>)getAttribute(COLATTR_ENUMTYPE) : null);
}
/**
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBColumn.java b/empire-db/src/main/java/org/apache/empire/db/DBColumn.java
index 85f5276..c05632a 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBColumn.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBColumn.java
@@ -392,7 +392,19 @@ public abstract class DBColumn extends DBColumnExpr
@Override
public boolean isEnum()
{
- return (attributes!=null && getAttribute(COLATTR_ENUMTYPE)!=null);
+ return (getEnumType()!=null);
+ }
+
+ /**
+ * Returns the enum type for this column
+ * <P>
+ * @return the enum type
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ public Class<Enum<?>> getEnumType()
+ {
+ return (attributes!=null ? (Class<Enum<?>>)getAttribute(COLATTR_ENUMTYPE) : null);
}
/**
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBRecord.java b/empire-db/src/main/java/org/apache/empire/db/DBRecord.java
index 407cf73..834cd3c 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBRecord.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBRecord.java
@@ -646,19 +646,30 @@ public class DBRecord extends DBRecordData implements Record, Cloneable
Object current = fields[index];
if (current==ObjectUtils.NO_VALUE)
throw new FieldValueNotFetchedException(getColumn(index));
+ // convert
+ DBColumn column = rowset.getColumn(index);
+ // must convert enums
+ if (value!=null && value.getClass().isEnum())
+ { // convert enum
+ Enum<?> enumVal = ((Enum<?>)value);
+ boolean numeric = column.getDataType().isNumeric();
+ value = (numeric ? enumVal.ordinal() : enumVal.name());
+ }
// Has Value changed?
if (ObjectUtils.compareEqual(current, value))
- return; // no change
- // Field has changed
- DBColumn column = rowset.getColumn(index);
+ { // value has not changed!
+ return;
+ }
// Check whether we can change this field
if (!allowFieldChange(column))
{ // Read Only column may be set
throw new FieldIsReadOnlyException(column);
}
- // Is Value valid
+ // Is Value valid?
if (this.validateFieldValues)
- value = validateValue(column, value);
+ { // validate
+ value = validateValue(column, value);
+ }
// Init original values
modifyValue(index, value, true);
}
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBRecordData.java b/empire-db/src/main/java/org/apache/empire/db/DBRecordData.java
index 53dd2e1..f9b8d38 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBRecordData.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBRecordData.java
@@ -31,7 +31,6 @@ import org.apache.empire.data.Column;
import org.apache.empire.data.ColumnExpr;
import org.apache.empire.data.RecordData;
import org.apache.empire.db.exceptions.FieldIllegalValueException;
-import org.apache.empire.db.exceptions.FieldValueOutOfRangeException;
import org.apache.empire.exceptions.BeanPropertySetException;
import org.apache.empire.exceptions.InvalidArgumentException;
import org.apache.empire.exceptions.ItemNotFoundException;
@@ -103,8 +102,8 @@ public abstract class DBRecordData extends DBObject
public int getInt(int index)
{
// Get Integer value
- Object o = getValue(index);
- return ObjectUtils.getInteger(o);
+ Object value = getValue(index);
+ return ObjectUtils.getInteger(value);
}
/**
@@ -129,8 +128,8 @@ public abstract class DBRecordData extends DBObject
public long getLong(int index)
{
// Get Integer value
- Object o = getValue(index);
- return ObjectUtils.getLong(o);
+ Object value = getValue(index);
+ return ObjectUtils.getLong(value);
}
/**
@@ -155,8 +154,8 @@ public abstract class DBRecordData extends DBObject
public double getDouble(int index)
{
// Get Double value
- Object v = getValue(index);
- return ObjectUtils.getDouble(v);
+ Object value = getValue(index);
+ return ObjectUtils.getDouble(value);
}
/**
@@ -181,8 +180,8 @@ public abstract class DBRecordData extends DBObject
public BigDecimal getDecimal(int index)
{
// Get Double value
- Object v = getValue(index);
- return ObjectUtils.getDecimal(v);
+ Object value = getValue(index);
+ return ObjectUtils.getDecimal(value);
}
/**
@@ -207,8 +206,8 @@ public abstract class DBRecordData extends DBObject
public boolean getBoolean(int index)
{
// Get Boolean value
- Object o = getValue(index);
- return ObjectUtils.getBoolean(o);
+ Object value = getValue(index);
+ return ObjectUtils.getBoolean(value);
}
/**
@@ -231,8 +230,8 @@ public abstract class DBRecordData extends DBObject
public String getString(int index)
{
// Get Integer value
- Object o = getValue(index);
- return StringUtils.toString(o);
+ Object value = getValue(index);
+ return StringUtils.toString(value);
}
/**
@@ -257,8 +256,8 @@ public abstract class DBRecordData extends DBObject
public Date getDateTime(int index)
{
// Get DateTime value
- Object o = getValue(index);
- return ObjectUtils.getDate(o);
+ Object value = getValue(index);
+ return ObjectUtils.getDate(value);
}
/**
@@ -283,33 +282,21 @@ public abstract class DBRecordData extends DBObject
* @return the enum value
*/
public <T extends Enum<?>> T getEnum(int index, Class<T> enumType)
- {
- // check column data type
+ { // check for null
+ if (isNull(index))
+ return null;
+ // convert
ColumnExpr col = getColumnExpr(index);
- boolean numeric = col.getDataType().isNumeric();
- T[] items = enumType.getEnumConstants();
- if (numeric)
- { // by ordinal
- if (isNull(index))
- return null;
- int ordinal = getInt(index);
- // check range
- if (ordinal<0 || ordinal>=items.length)
- throw new FieldValueOutOfRangeException(col.getSourceColumn(), 0, items.length);
- // return enum
- return items[ordinal];
- }
- else
- { // by name
- String name = getString(index);
- if (StringUtils.isEmpty(name))
- return null;
- // find name
- for (T e : items)
- if (e.name().equals(name))
- return e;
- // error: not found
- throw new FieldIllegalValueException(col.getSourceColumn(), name);
+ try {
+ // Convert to enum, depending on DataType
+ boolean numeric = col.getDataType().isNumeric();
+ return ObjectUtils.getEnum(enumType, (numeric ? getInt(index) : getValue(index)));
+
+ } catch (Exception e) {
+ // Illegal value
+ String value = StringUtils.valueOf(getValue(index));
+ log.error("Unable to resolve enum value of '{}' for type {}", value, enumType.getName());
+ throw new FieldIllegalValueException(col.getSourceColumn(), value, e);
}
}
@@ -336,8 +323,8 @@ public abstract class DBRecordData extends DBObject
@SuppressWarnings("unchecked")
public final <T extends Enum<?>> T getEnum(Column column)
{
- Object enumType = column.getAttribute(Column.COLATTR_ENUMTYPE);
- if (enumType==null || !(enumType instanceof Class<?>))
+ Class<Enum<?>> enumType = column.getEnumType();
+ if (enumType==null)
{ // Not an enum column (Attribute "enumType" has not been set)
throw new InvalidArgumentException("column", column);
}
@@ -371,7 +358,6 @@ public abstract class DBRecordData extends DBObject
/**
* Set a single property value of a java bean object used by readProperties.
*/
- @SuppressWarnings("rawtypes")
protected void setBeanProperty(ColumnExpr column, Object bean, String property, Object value)
{
if (StringUtils.isEmpty(property))
@@ -392,18 +378,11 @@ public abstract class DBRecordData extends DBObject
value = DateUtils.addDate((Date)value, 0, 0, 0);
}
*/
- Object type = column.getAttribute(Column.COLATTR_ENUMTYPE);
- if (type!=null && value!=null)
- {
- String name = value.toString();
- @SuppressWarnings("unchecked")
- Class<Enum> enumType = (Class<Enum>)type;
- for (Enum e : enumType.getEnumConstants())
- if (e.name().equals(name))
- {
- value = e;
- break;
- }
+ @SuppressWarnings("unchecked")
+ Class<Enum<?>> enumType = (Class<Enum<?>>)column.getAttribute(Column.COLATTR_ENUMTYPE);
+ if (enumType!=null && value!=null)
+ { // value to enum
+ value = ObjectUtils.getEnum(enumType, value);
}
// Set Property Value
if (value!=null)
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBTableColumn.java b/empire-db/src/main/java/org/apache/empire/db/DBTableColumn.java
index 53f3716..af494e0 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBTableColumn.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBTableColumn.java
@@ -430,7 +430,7 @@ public class DBTableColumn extends DBColumn
case DECIMAL:
// check enum
if (value.getClass().isEnum())
- {
+ { // convert enum
value = ((Enum<?>)value).ordinal();
}
// check number
@@ -468,7 +468,7 @@ public class DBTableColumn extends DBColumn
case INTEGER:
// check enum
if (value.getClass().isEnum())
- {
+ { // convert enum
value = ((Enum<?>)value).ordinal();
}
// check number
@@ -490,12 +490,16 @@ public class DBTableColumn extends DBColumn
case TEXT:
case VARCHAR:
case CHAR:
+ // check enum
if (value.getClass().isEnum())
- { // check enum
+ { // convert enum
value = ((Enum<?>)value).name();
}
+ // check length
if (value.toString().length() > size)
+ {
throw new FieldValueTooLongException(this);
+ }
break;
default: