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 cd4f6fc8 EMPIREDB-444 ValueUtils: some additinal optimizations
cd4f6fc8 is described below

commit cd4f6fc82bcbbbb72a670e47b59b492fdf2a2bff
Author: Rainer Döbele <[email protected]>
AuthorDate: Thu Oct 24 21:30:39 2024 +0200

    EMPIREDB-444
    ValueUtils: some additinal optimizations
---
 .../org/apache/empire/commons/ObjectUtils.java     |  59 ++++----
 .../java/org/apache/empire/commons/ValueUtils.java | 148 +++++++--------------
 .../main/java/org/apache/empire/db/DBCmdParam.java |   6 +
 .../main/java/org/apache/empire/db/DBDatabase.java |  20 +--
 .../java/org/apache/empire/db/DBSQLBuilder.java    |   3 +-
 .../main/java/org/apache/empire/db/DBTable.java    |   2 +-
 .../exceptions/ValueConversionException.java       |  40 ++++++
 7 files changed, 125 insertions(+), 153 deletions(-)

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 015e0339..3514e4cc 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
@@ -23,17 +23,18 @@ import java.math.BigDecimal;
 import java.text.ParseException;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.format.DateTimeParseException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Date;
 import java.util.List;
-import java.util.Locale;
 
 import org.apache.commons.beanutils.MethodUtils;
 import org.apache.empire.data.ColumnExpr;
 import org.apache.empire.data.DataType;
 import org.apache.empire.exceptions.InvalidArgumentException;
+import org.apache.empire.exceptions.ValueConversionException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -444,32 +445,6 @@ public final class ObjectUtils
         return valueUtils.getString(value);
     }
     
-    /**
-     * Converts an object value to a Date.
-     * <P>
-     * @param v the object to convert
-     * @return the Date value of o or null
-     * @throws ParseException
-     */
-    public static Date toDate(Object v)
-        throws ParseException
-    {
-        return valueUtils.toDate(v);
-    }
-    
-    /**
-     * 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.
-     * @param v the object to convert
-     * @param locale the locale used for conversion
-     * @return the Date value of o or null
-     */
-    public static Date getDate(Object v, Locale locale)
-    {
-        return valueUtils.getDate(v, locale);
-    }
-    
     /**
      * Converts an object value to a Date.
      * <P>
@@ -478,29 +453,43 @@ public final class ObjectUtils
      */
     public static Date getDate(Object v)
     {
-        return valueUtils.getDate(v);
+        try {
+            return valueUtils.toDate(v);
+        } catch (ParseException e) {
+            throw new ValueConversionException(Date.class, v, e);
+        }
     }
     
     /**
-     * Converts an object value to a Date.
+     * Converts an object value to a LocalDate.
      * <P>
      * @param v the object to convert
-     * @return the Date value of o or null
+     * @return the LocalDate value of o or null
      */
     public static LocalDate getLocalDate(Object v)
     {
-        return valueUtils.getLocalDate(v);
+        try {   
+            // DateTimeFormatter.ISO_LOCAL_DATE_TIME
+            return valueUtils.toLocalDate(v);
+        } catch (DateTimeParseException e) {
+            throw new ValueConversionException(LocalDate.class, v, e);
+        }
     }
     
     /**
-     * Converts an object value to a Date.
+     * Converts an object value to a LocalDateTime.
      * <P>
      * @param v the object to convert
-     * @return the Date value of o or null
+     * @return the LocalDateTime value of o or null
      */
     public static LocalDateTime getLocalDateTime(Object v)
     {
-        return valueUtils.getLocalDateTime(v);
+        try {
+            // DateTimeFormatter.ISO_LOCAL_DATE_TIME
+            return valueUtils.toLocalDateTime(v);
+        } catch (DateTimeParseException e) {
+            throw new ValueConversionException(LocalDateTime.class, v, e);
+        }
     }
     
     /**
@@ -523,7 +512,7 @@ public final class ObjectUtils
      * @param c the class type to convert to
      * @param v the object to convert
      * 
-     * @return the Date value of o or null
+     * @return the converted value of o or null
      * 
      * @throws ClassCastException if the object is not null and is not 
assignable to the type T.
      */
diff --git a/empire-db/src/main/java/org/apache/empire/commons/ValueUtils.java 
b/empire-db/src/main/java/org/apache/empire/commons/ValueUtils.java
index 9385365b..9ab51dfe 100644
--- a/empire-db/src/main/java/org/apache/empire/commons/ValueUtils.java
+++ b/empire-db/src/main/java/org/apache/empire/commons/ValueUtils.java
@@ -20,28 +20,26 @@ package org.apache.empire.commons;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.sql.Timestamp;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
-import java.time.format.DateTimeParseException;
 import java.time.temporal.Temporal;
 import java.util.Collection;
 import java.util.Date;
-import java.util.Locale;
 
 import org.apache.commons.beanutils.MethodUtils;
 import org.apache.empire.data.DataType;
+import org.apache.empire.db.DBExpr;
 import org.apache.empire.db.expr.column.DBValueExpr;
 import org.apache.empire.exceptions.InvalidValueException;
 import org.apache.empire.exceptions.ItemNotFoundException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.empire.exceptions.ValueConversionException;
 
 /**
  * This class allows to customize value type conversion as well as other value 
related functions.
- * The functions and methods are called indirectly via the corresponding 
static functions in the ObjectUtils class.
- * 
+ * The functions and methods are called indirectly via the corresponding 
static functions in the ObjectUtils class. * 
  * You may create your own derived class and overwrite the methods.
  * In order to activate your ValueUtils implementation use the static function
  * 
@@ -52,7 +50,7 @@ import org.slf4j.LoggerFactory;
 public class ValueUtils
 {
     // Logger
-    private static final Logger log = 
LoggerFactory.getLogger(ValueUtils.class);
+    // private static final Logger log = 
LoggerFactory.getLogger(ValueUtils.class);
 
     protected static final String DATE_FORMAT = "yyyy-MM-dd";
     protected static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
@@ -159,6 +157,9 @@ public class ValueUtils
         // Use equal check first
         if (o1.equals(o2) || o2.equals(o1))
             return true;
+        // DBExpr 
+        if ((o1 instanceof DBExpr) || (o2 instanceof DBExpr))
+            return false;
         // Compare Numbers
         if (o1 instanceof Number && o2 instanceof Number)
         {   // boolean test = obj1.equals(obj2);
@@ -521,92 +522,28 @@ public class ValueUtils
             return DateUtils.toDate((LocalDate)v);
         if (v instanceof java.time.LocalDateTime)
             return DateUtils.toDate((LocalDateTime)v);
-        // Convert from String
-        String str = v.toString();
-        if (str.length() > 10)
-            return dateTimeFormatter.get().parse(str);
-        else
-            return dateOnlyFormatter.get().parse(str);
-    }
-    
-    /**
-     * 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.
-     * @param v the object to convert
-     * @param locale the locale used for conversion
-     * @return the Date value of o or null
-     */
-    public Date getDate(Object v, Locale locale)
-    {
-        // Get DateTime value
-        if (isEmpty(v))
-            return null;
-        if (v instanceof Date)
-            return ((Date)v);
-        if (v instanceof java.time.LocalDate)
-            return DateUtils.toDate((LocalDate)v);
-        if (v instanceof java.time.LocalDateTime)
-            return DateUtils.toDate((LocalDateTime)v);
-        // Get Calendar
         if (v instanceof Number)
         {   // Get Date from a number
             long l = ((Number)v).longValue();
-            if (l==0)
-                return DateUtils.getDateNow();
-            // Year or full date/time?
-            /*
-            if (l<10000)
-            {   // Year only
-                Calendar calendar = 
Calendar.getInstance(getSafeLocale(locale));
-                calendar.set((int)l, 1, 1);
-                return calendar.getTime();
-            }
-            */
-            // Date from long
-            return new Date(l);
+            return (l==0 ? null : new Date(l));
         }
-        // Try to parse
-        return DateUtils.parseDate(v.toString(), locale);
-    }
-    
-    /**
-     * Converts an object value to a Date.
-     * <P>
-     * @param v the object to convert
-     * @return the Date value of o or null
-     */
-    public Date getDate(Object v)
-    {
-        // Get DateTime value
-        if (isEmpty(v))
-            return null;
-        if (v instanceof java.util.Date)
-            return ((java.util.Date)v);
-        if (v instanceof java.time.LocalDate)
-            return DateUtils.toDate((LocalDate)v);
-        if (v instanceof java.time.LocalDateTime)
-            return DateUtils.toDate((LocalDateTime)v);
         // Convert from String
         String str = v.toString();
-        try
-        {   if (str.length() > 10)
-                return dateTimeFormatter.get().parse(str);
-            else
-                return dateOnlyFormatter.get().parse(str);
-        } catch (ParseException e) {
-            log.error(String.format("Cannot convert value [%s] to Date", str), 
e);
-            return null;
-        }
+        if (str.length() > 20)
+            return Timestamp.valueOf(str);
+        if (str.length() > 10)
+            return dateTimeFormatter.get().parse(str);
+        else
+            return dateOnlyFormatter.get().parse(str);
     }
     
     /**
      * Converts an object value to a Date.
      * <P>
      * @param v the object to convert
-     * @return the Date value of o or null
+     * @return the LocalDate value of o or null
      */
-    public LocalDate getLocalDate(Object v)
+    public LocalDate toLocalDate(Object v)
     {
         // Get DateTime value
         if (isEmpty(v))
@@ -622,23 +559,18 @@ public class ValueUtils
         if (v instanceof java.util.Date)
             return DateUtils.toLocalDate((Date)v);
         // Convert from String
+        // DateTimeFormatter.ISO_LOCAL_DATE_TIME
         String str = v.toString();
-        try
-        {   // DateTimeFormatter ISO_LOCAL_DATE
-            return LocalDate.parse(str);
-        } catch (DateTimeParseException e) {
-            log.error(String.format("Cannot convert value [%s] to LocalDate", 
str), e);
-            return null;
-        }
+        return LocalDate.parse(str);
     }
     
     /**
      * Converts an object value to a Date.
      * <P>
      * @param v the object to convert
-     * @return the Date value of o or null
+     * @return the LocalDateTime value of o or null
      */
-    public LocalDateTime getLocalDateTime(Object v)
+    public LocalDateTime toLocalDateTime(Object v)
     {
         // Get DateTime value
         if (isEmpty(v))
@@ -654,14 +586,9 @@ public class ValueUtils
         if (v instanceof java.util.Date)
             return DateUtils.toLocalDateTime((Date)v);
         // Convert from String
+        // DateTimeFormatter.ISO_LOCAL_DATE_TIME
         String str = v.toString();
-        try
-        {   // DateTimeFormatter.ISO_LOCAL_DATE_TIME
-            return LocalDateTime.parse(str);
-        } catch (DateTimeParseException e) {
-            log.error(String.format("Cannot convert value [%s] to 
LocalDateTime", str), e);
-            return null;
-        }
+        return LocalDateTime.parse(str);
     }
     
     /**
@@ -741,19 +668,24 @@ public class ValueUtils
         // check null
         if (value == null)
             return null;
+        // Cannot convert DBEXpr, return as is
+        if (value instanceof DBExpr)
+            return value;
         // Strings special
         if ((value instanceof String) && ((String)value).length()==0)
             value = null;
-        // check for enum
-        if (value instanceof Enum<?>)
-        {   // convert enum
-            value = getEnumValue((Enum<?>)value, dataType.isNumeric());
-        }
         // check option entry
-        else if (value instanceof OptionEntry)
+        if (value instanceof OptionEntry)
         {   // option value
             value = ((OptionEntry)value).getValue();
         }
+        // check for enum
+        if (value instanceof Enum<?>)
+        {   // Convert Enum now (optional)
+            // value = getEnumValue((Enum<?>)value, dataType.isNumeric());
+            // Otherwise Enum will be converted later
+            return value; 
+        }
         // check type
         switch (dataType)
         {
@@ -761,6 +693,18 @@ public class ValueUtils
                 return value; // unchanged
             case BOOL:
                 return getBoolean(value, false);
+            case DATE:
+            case DATETIME:
+            case TIMESTAMP:
+                // check type
+                if ((value instanceof Date) || (value instanceof Temporal))
+                    return value; // already a date or temporal
+                // try to convert
+                try {
+                    return toDate(value);
+                } catch (ParseException e) {
+                    throw new ValueConversionException(Date.class, value, e);
+                }
             case INTEGER:
                 return (value instanceof Number) ? value : toLong(value);
             case FLOAT:
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 f532e203..3d2ebfea 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
@@ -22,6 +22,7 @@ import java.util.Set;
 
 import org.apache.empire.commons.ObjectUtils;
 import org.apache.empire.data.DataType;
+import org.apache.empire.exceptions.InvalidOperationException;
 
 /**
  * This class defines a parameter for a prepared statement query.
@@ -57,10 +58,15 @@ public class DBCmdParam extends DBExpr
      */
     protected Object getCmdParamValue(Object value)
     {
+        if (value instanceof DBExpr)
+            throw new InvalidOperationException("DBCmdParam does not accept 
DBExpr");
         if (value!=null)
             value = ObjectUtils.convertValue(type, value);
         if (value==null)
             return value;
+        // If still an Enum, convert now (Lazy conversion)
+        if (value instanceof Enum<?>)
+            value = ObjectUtils.getEnumValue((Enum<?>)value, type.isNumeric());
         // Check CLOB and BLOB
         switch (type)
         {
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBDatabase.java 
b/empire-db/src/main/java/org/apache/empire/db/DBDatabase.java
index 536b661e..4e615941 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBDatabase.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBDatabase.java
@@ -22,7 +22,6 @@ import java.lang.ref.WeakReference;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.sql.Timestamp;
-import java.text.ParseException;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
@@ -63,6 +62,7 @@ import org.apache.empire.exceptions.ItemExistsException;
 import org.apache.empire.exceptions.NotSupportedException;
 import org.apache.empire.exceptions.ObjectNotValidException;
 import org.apache.empire.exceptions.PropertyReadOnlyException;
+import org.apache.empire.exceptions.ValueConversionException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -1102,10 +1102,10 @@ public abstract class DBDatabase extends DBObject
                 if (!(value instanceof LocalDateTime) && !(value instanceof 
Date) && !DBDatabase.SYSDATE.equals(value))
                 {   try {
                         // Parse Date
-                        value = ObjectUtils.toDate(value);
-                    } catch(ParseException e) {
+                        value = ObjectUtils.getDate(value);
+                    } catch (ValueConversionException e) {
                         log.info("Parsing '{}' to Date failed for column {}. 
Message is "+e.toString(), value, column.getName());
-                        throw new FieldIllegalValueException(column, 
String.valueOf(value), e);
+                        throw new FieldIllegalValueException(column, 
String.valueOf(value), e.getCause());
                     }
                 }    
                 break;
@@ -1113,9 +1113,7 @@ public abstract class DBDatabase extends DBObject
             case DECIMAL:
                 // check enum
                 if (value instanceof Enum<?>)
-                {   // convert enum   
-                    value = ((Enum<?>)value).ordinal();
-                }
+                    break; // Convert later...
                 // check number
                 if (!(value instanceof java.lang.Number))
                 {   try
@@ -1149,9 +1147,7 @@ public abstract class DBDatabase extends DBObject
             case INTEGER:
                 // check enum
                 if (value instanceof Enum<?>)
-                {   // convert enum   
-                    value = ((Enum<?>)value).ordinal();
-                }
+                    break; // Convert later...
                 // check number
                 if (!(value instanceof java.lang.Number))
                 {   try
@@ -1170,9 +1166,7 @@ public abstract class DBDatabase extends DBObject
             case CHAR:
                 // check enum
                 if (value instanceof Enum<?>)
-                {   // convert enum   
-                    value = ObjectUtils.getString((Enum<?>)value);
-                }
+                    break; // Convert later...
                 // check length
                 if (value.toString().length() > (int)column.getSize())
                 {
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBSQLBuilder.java 
b/empire-db/src/main/java/org/apache/empire/db/DBSQLBuilder.java
index 8c83aefb..26bb1378 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBSQLBuilder.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBSQLBuilder.java
@@ -283,8 +283,7 @@ public abstract class DBSQLBuilder implements Appendable
     protected void appendSimpleValue(DataType type, Object value)
     { 
         if (value instanceof Enum<?>)
-        {   // convert enum
-            log.warn("Enum of type {} supplied for getValueString. Converting 
value...", value.getClass().getName());
+        {   // If still an Enum, convert now (Lazy conversion)
             value = ObjectUtils.getEnumValue((Enum<?>)value, type.isNumeric());
         }
         if (ObjectUtils.isEmpty(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 96e2ca16..1841767b 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
@@ -395,7 +395,7 @@ public class DBTable extends DBRowSet implements Cloneable
      */
     public final DBTableColumn addColumn(String columnName, DataType type, 
double size, boolean required, Enum<?> enumValue)
     { 
-        Object defValue = ObjectUtils.getEnumValue(enumValue, 
type.isNumeric());
+        Object defValue = ObjectUtils.convertValue(type, enumValue);
         DBTableColumn col = this.createAndAppendColumn(columnName, type, size, 
required, defValue);
         if (enumValue!=null)
             col.setEnumOptions(enumValue.getClass());
diff --git 
a/empire-db/src/main/java/org/apache/empire/exceptions/ValueConversionException.java
 
b/empire-db/src/main/java/org/apache/empire/exceptions/ValueConversionException.java
new file mode 100644
index 00000000..32f4e299
--- /dev/null
+++ 
b/empire-db/src/main/java/org/apache/empire/exceptions/ValueConversionException.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.empire.exceptions;
+
+import org.apache.empire.commons.ErrorType;
+import org.apache.empire.commons.StringUtils;
+
+public class ValueConversionException extends EmpireException
+{
+    private static final long serialVersionUID = 1L;
+    
+    public static final ErrorType errorType = new 
ErrorType("error.valueConversion", "Error converting from {1} to {0}. Invalid 
value: {2}");
+    
+    protected ValueConversionException(ErrorType errorType, String[] params)
+    {
+        super(errorType, params);
+    }
+    
+    public ValueConversionException(Class<?> targetType, Object value, 
Exception cause)
+    {
+        super(errorType, new String[] { targetType.getName(), 
value.getClass().getName(), StringUtils.valueOf(value) }, cause);
+    }
+
+}

Reply via email to