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 2021/04/28 12:32:51 UTC

[empire-db] branch master updated: EMPIREDB-346 Improve Enum value conversion / allow custom conversion

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 db76b56  EMPIREDB-346 Improve Enum value conversion / allow custom conversion
db76b56 is described below

commit db76b5688743eb264fb7d4b395ab2fa5c9b8ac36
Author: Rainer Döbele <do...@apache.org>
AuthorDate: Wed Apr 28 14:32:47 2021 +0200

    EMPIREDB-346
    Improve Enum value conversion / allow custom conversion
---
 .../apache/empire/jsf2/components/SelectTag.java   |  8 +--
 .../apache/empire/jsf2/controls/InputControl.java  |  2 +-
 .../empire/jsf2/controls/RadioInputControl.java    |  6 +-
 .../empire/jsf2/controls/SelectInputControl.java   |  6 +-
 .../org/apache/empire/commons/ObjectUtils.java     | 82 ++++++++++++++++++++--
 .../org/apache/empire/commons/OptionEntry.java     |  4 +-
 .../main/java/org/apache/empire/db/DBCmdParam.java |  5 +-
 .../java/org/apache/empire/db/DBColumnExpr.java    |  6 +-
 .../src/main/java/org/apache/empire/db/DBExpr.java | 10 ++-
 .../main/java/org/apache/empire/db/DBRecord.java   |  4 +-
 .../main/java/org/apache/empire/db/DBTable.java    |  3 +-
 .../java/org/apache/empire/db/DBTableColumn.java   | 20 ++++--
 .../apache/empire/db/expr/column/DBValueExpr.java  |  8 +--
 13 files changed, 122 insertions(+), 42 deletions(-)

diff --git a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/SelectTag.java b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/SelectTag.java
index 3c91b95..575fb00 100644
--- a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/SelectTag.java
+++ b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/SelectTag.java
@@ -76,8 +76,8 @@ public class SelectTag extends UIInput implements NamingContainer
             Object value = SelectTag.this.getValue();
             if (value != null)
             {
-                if (value.getClass().isEnum())
-                    value = ((Enum<?>) value).name();
+                if (value instanceof Enum<?>)
+                    value = ((Enum<?>)value).name();
                 else
                     value = String.valueOf(value);
             }
@@ -391,8 +391,8 @@ public class SelectTag extends UIInput implements NamingContainer
         Object value = getValue();
         if (value != null)
         {
-            if (value.getClass().isEnum())
-                value = ((Enum<?>) value).name();
+            if (value instanceof Enum<?>)
+                value = ((Enum<?>)value).name();
             else
                 value = String.valueOf(value);
         }
diff --git a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/controls/InputControl.java b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/controls/InputControl.java
index fddd02b..f940c72 100644
--- a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/controls/InputControl.java
+++ b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/controls/InputControl.java
@@ -704,7 +704,7 @@ public abstract class InputControl
     protected String formatValue(Object value, ValueInfo vi)
     {
         // For Enums use toString() to retrieve Value
-        if (value != null && value.getClass().isEnum() && !hasFormatOption(vi, "nolookup"))
+        if ((value instanceof Enum<?>) && !hasFormatOption(vi, "nolookup"))
         { // Handle enum
             String text = ((Enum<?>) value).toString();
             if (text != null)
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 97e0af7..5231521 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
@@ -318,10 +318,8 @@ public class RadioInputControl extends InputControl
     protected Object formatInputValue(Object value, InputInfo ii)
     {
         // the enum Value
-        if (value != null && value.getClass().isEnum())
-        {
+        if (value instanceof Enum<?>)
             return ((Enum<?>) value).name();
-        }
         // the value
         return value;
     }
@@ -332,7 +330,7 @@ public class RadioInputControl extends InputControl
         Class<Enum<?>> enumType = ii.getColumn().getEnumType();
         if (enumType!=null)
         {   // convert to enum
-            return ObjectUtils.getEnum(enumType, value);
+            return ObjectUtils.getEnumByName(enumType, 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 99f96b6..cdfbecd 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
@@ -354,10 +354,8 @@ public class SelectInputControl extends InputControl
     protected Object formatInputValue(Object value)
     {
         // the enum Value
-        if (value != null && value.getClass().isEnum())
-        {
+        if (value instanceof Enum<?>)
             return ((Enum<?>) value).name();
-        }
         // the value
         return value;
     }
@@ -368,7 +366,7 @@ public class SelectInputControl extends InputControl
         Class<Enum<?>> enumType = ii.getColumn().getEnumType();
         if (enumType!=null)
         {   // convert to enum
-            return ObjectUtils.getEnum(enumType, value);
+            return ObjectUtils.getEnumByName(enumType, value);
         }
         return value;
     }
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 ff2f882..42df629 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
@@ -74,7 +74,7 @@ public final class ObjectUtils
 
     private static final String DATE_FORMAT = "yyyy-MM-dd";
 	private static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
-
+	
     private ObjectUtils()
     {
         // Static Function only
@@ -151,7 +151,7 @@ public final class ObjectUtils
             return (d1==d2);
         }
         // Enum
-        if (o1.getClass().isEnum())
+        if (o1 instanceof Enum<?>)
         {   // Special enum handling   
             if (o2 instanceof Number)
                 return ((Enum<?>)o1).ordinal()==((Number)o2).intValue();
@@ -160,7 +160,7 @@ public final class ObjectUtils
             else
                 return ((Enum<?>)o1).name().equals(o2);
         }
-        else if (o2.getClass().isEnum())
+        else if (o2 instanceof Enum<?>)
         {   // Special enum handling   
             if (o1 instanceof Number)
                 return ((Enum<?>)o2).ordinal()==((Number)o1).intValue();
@@ -469,8 +469,20 @@ public final class ObjectUtils
             value = ((Enum<?>)value).name();
         }
         // check column data type
+        boolean numeric = (value instanceof Number);
         T[] items = enumType.getEnumConstants();
-        if (value instanceof Number)
+        if (items.length>0 && (items[0] instanceof EnumValue))
+        {   // custom conversion
+            for (T e : items)
+            {
+                Object eVal = ((EnumValue)e).toValue(numeric);
+                if (ObjectUtils.compareEqual(eVal, value))
+                    return e;
+            }
+            // error: not found
+            throw new ItemNotFoundException(StringUtils.toString(value));
+        }
+        else if (numeric)
         {   // by ordinal
             int ordinal = ((Number)value).intValue();
             // check range
@@ -490,6 +502,68 @@ public final class ObjectUtils
             throw new ItemNotFoundException(name);
         }
     }
+
+    /**
+     * find by name
+     * @param enumType the enum type
+     * @param name the enum name
+     * @return the enum
+     */
+    public static <T extends Enum<?>> T getEnumByName(Class<T> enumType, String name)
+    {   // check for null
+        if (isEmpty(name))
+            return null;
+        // check column data type
+        T[] items = enumType.getEnumConstants();
+        for (T e : items)
+            if (e.name().equals(name))
+                return e;
+        // error: not found
+        throw new ItemNotFoundException(name);
+    }
+    
+    /**
+     * Convert Enum<?> to Object
+     */
+    public static Object getEnumValue(Enum<?> enumValue, boolean isNumeric)
+    {
+        // convert
+        if (enumValue instanceof EnumValue)
+            return ((EnumValue)enumValue).toValue(isNumeric);
+        // default
+        return (isNumeric ? enumValue.ordinal() : getString(enumValue));
+    }
+    
+    /**
+     * Convert Enum<?> to String
+     */
+    public static String getString(Enum<?> enumValue)
+    {
+        // convert
+        if (enumValue instanceof EnumValue)
+            return StringUtils.toString(((EnumValue)enumValue).toValue(false));
+        /* special case */
+        if (enumValue==null || enumValue.name().equals("NULL"))
+            return null;
+        /* use name */
+        return enumValue.name();
+    }
+    
+    /**
+     * Convert Object to String
+     */
+    public static String getString(Object value)
+    {
+        // convert
+        if (value instanceof Enum<?>)
+            return getString((Enum<?>)value);
+        if (value instanceof Date)
+            return formatDate((Date)value, true);
+        if (value==NO_VALUE)
+            return null;
+        // toString
+        return (value!=null ? value.toString() : null);
+    }
     
     /**
      * Converts an object value to a Date.
diff --git a/empire-db/src/main/java/org/apache/empire/commons/OptionEntry.java b/empire-db/src/main/java/org/apache/empire/commons/OptionEntry.java
index f5ef540..d4e8f3a 100644
--- a/empire-db/src/main/java/org/apache/empire/commons/OptionEntry.java
+++ b/empire-db/src/main/java/org/apache/empire/commons/OptionEntry.java
@@ -68,8 +68,8 @@ public class OptionEntry implements Serializable
         if (value==null)
             return "";
         // check enum
-        if (value.getClass().isEnum())
-            return ((Enum<?>)value).name();
+        if (value instanceof Enum<?>)
+            return ObjectUtils.getString((Enum<?>)value);
         // convert
         return String.valueOf(value);
     }
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBCmdParam.java b/empire-db/src/main/java/org/apache/empire/db/DBCmdParam.java
index 0d70f12..68323b0 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBCmdParam.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBCmdParam.java
@@ -79,10 +79,9 @@ public class DBCmdParam extends DBExpr
             	return ObjectUtils.getBoolean(value);
             default:
                 // check for enum
-                if (value.getClass().isEnum())
+                if (value instanceof Enum<?>)
                 {   // convert enum
-                    Enum<?> enumValue = ((Enum<?>)value);
-                    return (type.isNumeric() ? enumValue.ordinal() : enumValue.name());
+                    return ObjectUtils.getEnumValue((Enum<?>)value, type.isNumeric());
                 }
                 // use as is
                 return value;
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBColumnExpr.java b/empire-db/src/main/java/org/apache/empire/db/DBColumnExpr.java
index fd78c4c..99c146a 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBColumnExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBColumnExpr.java
@@ -24,6 +24,7 @@ import java.util.LinkedHashMap;
 import java.util.Map;
 
 import org.apache.empire.commons.Attributes;
+import org.apache.empire.commons.ObjectUtils;
 import org.apache.empire.commons.OptionEntry;
 import org.apache.empire.commons.Options;
 import org.apache.empire.commons.StringUtils;
@@ -1095,7 +1096,7 @@ public abstract class DBColumnExpr extends DBExpr
         Map<Object, String> enumMap = new LinkedHashMap<Object, String>(items.length);
         for (int i=0; i<items.length; i++)
         {   // key: ordinal (for numeric columns) or name (for CHAR columns)
-            Object key = (byOrdinal ? items[i].ordinal() : items[i].name());
+            Object key = ObjectUtils.getEnumValue(items[i], byOrdinal);            
             enumMap.put(key, items[i].toString());
         }
         // Create the decode function
@@ -1122,7 +1123,8 @@ public abstract class DBColumnExpr extends DBExpr
         for (int i=0; i<items.length; i++)
         {   
             int sortValue = items[i].ordinal();
-            enumMap.put(items[i].name(), sortValue + sortOffset);
+            String value = ObjectUtils.getString(items[i]);
+            enumMap.put(value, sortValue + sortOffset);
         }
         // Create the decode function
         int defaultValue = (defaultToEnd ? items.length : 0);
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBExpr.java b/empire-db/src/main/java/org/apache/empire/db/DBExpr.java
index 4ee04a6..23e34f1 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBExpr.java
@@ -22,6 +22,7 @@ import java.util.Collection;
 import java.util.Date;
 import java.util.Set;
 
+import org.apache.empire.commons.ObjectUtils;
 import org.apache.empire.commons.OptionEntry;
 // java
 import org.apache.empire.data.DataType;
@@ -85,16 +86,13 @@ public abstract class DBExpr extends DBObject
         } 
         // check option entry
         if (value instanceof OptionEntry)
-        {
+        {   // option value
             value = ((OptionEntry)value).getValue();
         }
         // check enum
-        if (value!=null && value.getClass().isEnum())
+        if (value instanceof Enum<?>)
         {   // check enum
-            if (dataType.isNumeric())
-                value = ((Enum<?>)value).ordinal();
-            else
-                value = ((Enum<?>)value).name();
+            value = ObjectUtils.getEnumValue((Enum<?>)value, dataType.isNumeric());
         }
         else if (value instanceof Collection<?>)
         {   // collection 2 array
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 f612f09..d3ac89b 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
@@ -650,11 +650,11 @@ public class DBRecord extends DBRecordData implements Record, Cloneable
         // convert
         DBColumn column = rowset.getColumn(index);
         // must convert enums
-        if (value!=null && value.getClass().isEnum())
+        if (value instanceof Enum<?>)
         {   // convert enum
             Enum<?> enumVal = ((Enum<?>)value);
             boolean numeric = column.getDataType().isNumeric();
-            value = (numeric ? enumVal.ordinal() : enumVal.name());
+            value = ObjectUtils.getEnumValue(enumVal, numeric);
         }
         // Has Value changed?
         if (ObjectUtils.compareEqual(current, value))
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBTable.java b/empire-db/src/main/java/org/apache/empire/db/DBTable.java
index 153d5b4..d31cc64 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBTable.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBTable.java
@@ -26,6 +26,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import org.apache.empire.commons.ObjectUtils;
 import org.apache.empire.commons.Options;
 import org.apache.empire.commons.StringUtils;
 import org.apache.empire.data.DataMode;
@@ -416,7 +417,7 @@ public class DBTable extends DBRowSet implements Cloneable
      */
     public final DBTableColumn addColumn(String columnName, DataType type, double size, boolean required, Enum<?> enumValue)
     { 
-        Object defValue = type.isNumeric() ? enumValue.ordinal() : enumValue.name();
+        Object defValue = ObjectUtils.getEnumValue(enumValue, type.isNumeric());
         DBTableColumn col = this.crateAndAppendColumn(columnName, type, size, required, defValue);
         col.setEnumOptions(enumValue.getClass());
         return col;
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 7400e49..4a3447a 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
@@ -26,6 +26,7 @@ import java.util.Date;
 
 import org.apache.empire.commons.Attributes;
 import org.apache.empire.commons.ObjectUtils;
+import org.apache.empire.commons.OptionEntry;
 import org.apache.empire.commons.Options;
 import org.apache.empire.commons.StringUtils;
 import org.apache.empire.data.Column;
@@ -36,6 +37,7 @@ import org.apache.empire.db.exceptions.FieldNotNullException;
 import org.apache.empire.db.exceptions.FieldValueOutOfRangeException;
 import org.apache.empire.db.exceptions.FieldValueTooLongException;
 import org.apache.empire.exceptions.InvalidArgumentException;
+import org.apache.empire.exceptions.InvalidPropertyException;
 import org.apache.empire.exceptions.NotSupportedException;
 import org.apache.empire.exceptions.PropertyReadOnlyException;
 import org.apache.empire.xml.XMLUtil;
@@ -339,6 +341,16 @@ public class DBTableColumn extends DBColumn
         this.options = new Options(enumType);
         // set enumType
         setAttribute(Column.COLATTR_ENUMTYPE, enumType);
+        // check length
+        if (getDataType().isNumeric())
+            return; // no check required
+        int maxLength = (int)size;
+        for (OptionEntry oe : options)
+        {   // check length
+            String val = oe.getValueString();
+            if (val!=null && val.length()>maxLength)
+                throw new InvalidPropertyException(enumType.getName(), val);
+        }
     }
 
     /**
@@ -420,7 +432,7 @@ public class DBTableColumn extends DBColumn
 
             case DECIMAL:
                 // check enum
-                if (value.getClass().isEnum())
+                if (value instanceof Enum<?>)
                 {   // convert enum   
                     value = ((Enum<?>)value).ordinal();
                 }
@@ -458,7 +470,7 @@ public class DBTableColumn extends DBColumn
 
             case INTEGER:
                 // check enum
-                if (value.getClass().isEnum())
+                if (value instanceof Enum<?>)
                 {   // convert enum   
                     value = ((Enum<?>)value).ordinal();
                 }
@@ -482,9 +494,9 @@ public class DBTableColumn extends DBColumn
             case VARCHAR:
             case CHAR:
                 // check enum
-                if (value.getClass().isEnum())
+                if (value instanceof Enum<?>)
                 {   // convert enum   
-                    value = ((Enum<?>)value).name();
+                    value = ObjectUtils.getString((Enum<?>)value);
                 }
                 // check length
                 if (value.toString().length() > size)
diff --git a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBValueExpr.java b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBValueExpr.java
index 1ae26c6..9a61d3b 100644
--- a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBValueExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBValueExpr.java
@@ -20,6 +20,7 @@ package org.apache.empire.db.expr.column;
 
 import java.util.Set;
 
+import org.apache.empire.commons.ObjectUtils;
 // Java
 import org.apache.empire.data.DataType;
 import org.apache.empire.db.DBColumn;
@@ -195,11 +196,8 @@ public class DBValueExpr extends DBColumnExpr
             Object val = value;
             // unwrap enum
             if (value instanceof Enum)
-            {   // its an enum
-                if (dataType.isNumeric())
-                    val = ((Enum<?>) value).ordinal();
-                else 
-                    val = ((Enum<?>) value).name();
+            {   // Convert value
+                value = ObjectUtils.getEnumValue((Enum<?>) value, dataType.isNumeric());
             }
             // convert value to sql literal
             DBDatabaseDriver driver = db.getDriver();