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 3769626b EMPIREDB-459 DBRecordData and DataListEntry: sync functions 
and behaviour
3769626b is described below

commit 3769626b04c07848cd3ad05af758ff10f62283bb
Author: Rainer Döbele <[email protected]>
AuthorDate: Fri Mar 21 10:48:44 2025 +0100

    EMPIREDB-459
    DBRecordData and DataListEntry: sync functions and behaviour
---
 .../java/org/apache/empire/commons/ClassUtils.java |  58 +++
 .../java/org/apache/empire/data/RecordData.java    |   2 +-
 .../org/apache/empire/data/list/DataListEntry.java | 508 +++++++++++++++++----
 .../org/apache/empire/data/list/DataListHead.java  |   6 +-
 .../java/org/apache/empire/db/DBRecordData.java    | 329 +++++++------
 .../main/java/org/apache/empire/db/DBRowSet.java   |  16 +
 6 files changed, 666 insertions(+), 253 deletions(-)

diff --git a/empire-db/src/main/java/org/apache/empire/commons/ClassUtils.java 
b/empire-db/src/main/java/org/apache/empire/commons/ClassUtils.java
index f78f5be1..8a10f6cb 100644
--- a/empire-db/src/main/java/org/apache/empire/commons/ClassUtils.java
+++ b/empire-db/src/main/java/org/apache/empire/commons/ClassUtils.java
@@ -18,6 +18,7 @@
  */
 package org.apache.empire.commons;
 
+import java.beans.PropertyDescriptor;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -31,13 +32,17 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.net.URISyntaxException;
 
+import org.apache.commons.beanutils.BeanUtils;
 import org.apache.commons.beanutils.ConstructorUtils;
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.empire.exceptions.BeanPropertySetException;
 import org.apache.empire.exceptions.EmpireException;
 import org.apache.empire.exceptions.InternalException;
 import org.apache.empire.exceptions.InvalidArgumentException;
 import org.apache.empire.exceptions.InvalidOperationException;
 import org.apache.empire.exceptions.NotImplementedException;
 import org.apache.empire.exceptions.NotSupportedException;
+import org.apache.empire.exceptions.PropertyReadOnlyException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -803,4 +808,57 @@ public final class ClassUtils
         }
     }
     
+    /**
+     * Set a single property value of a java bean object used by 
readProperties.
+     *
+     * @param column the column expression
+     * @param bean the bean
+     * @param property the property
+     * @param value the value
+     */
+    public static void setBeanProperty(Object bean, String property, Object 
value)
+    {
+        try
+        {
+            if (bean==null)
+                throw new InvalidArgumentException("bean", bean);
+            if (StringUtils.isEmpty(property))
+                throw new InvalidArgumentException("property", property);
+            if (log.isTraceEnabled())
+                log.trace("{}: setting property '{}' to {}", 
bean.getClass().getName(), property, value);
+            // Set Property Value
+            if (value!=null)
+            {   // Bean utils will convert if necessary
+                BeanUtils.setProperty(bean, property, value);
+            }
+            else
+            {   // Don't convert, just set
+                PropertyDescriptor pd = 
PropertyUtils.getPropertyDescriptor(bean, property);
+                if (pd==null)
+                    return; // No such property
+                // get the write method
+                final Method method = PropertyUtils.getWriteMethod(pd);
+                if (method == null)
+                    throw new PropertyReadOnlyException(property);
+                // invoke
+                method.invoke(bean, value);
+            }
+          // IllegalAccessException
+        } catch (IllegalAccessException e)
+        {   log.error(bean.getClass().getName() + ": unable to set property '" 
+ property + "'");
+            throw new BeanPropertySetException(bean, property, e);
+          // InvocationTargetException  
+        } catch (InvocationTargetException e)
+        {   log.error(bean.getClass().getName() + ": unable to set property '" 
+ property + "'");
+            throw new BeanPropertySetException(bean, property, e);
+          // NoSuchMethodException   
+        } catch (NoSuchMethodException e)
+        {   log.error(bean.getClass().getName() + ": unable to set property '" 
+ property + "'");
+            throw new BeanPropertySetException(bean, property, e);
+        } catch (NullPointerException e)
+        {   log.error(bean.getClass().getName() + ": unable to set property '" 
+ property + "'");
+            throw new BeanPropertySetException(bean, property, e);
+        }
+    }
+    
 }
diff --git a/empire-db/src/main/java/org/apache/empire/data/RecordData.java 
b/empire-db/src/main/java/org/apache/empire/data/RecordData.java
index 4400344c..7655d464 100644
--- a/empire-db/src/main/java/org/apache/empire/data/RecordData.java
+++ b/empire-db/src/main/java/org/apache/empire/data/RecordData.java
@@ -91,7 +91,7 @@ public interface RecordData
 
     /**
      * copies all field values into a static Java Bean.
-     * <P>
+     * 
      * In order to map column names to property names 
      * the property name is detected by ColumnExpr.getBeanPropertyName()     
      * @param bean the Java Bean for which to set the properties
diff --git 
a/empire-db/src/main/java/org/apache/empire/data/list/DataListEntry.java 
b/empire-db/src/main/java/org/apache/empire/data/list/DataListEntry.java
index c6e01907..b28ba7be 100644
--- a/empire-db/src/main/java/org/apache/empire/data/list/DataListEntry.java
+++ b/empire-db/src/main/java/org/apache/empire/data/list/DataListEntry.java
@@ -20,18 +20,24 @@ package org.apache.empire.data.list;
 
 import java.io.Serializable;
 import java.math.BigDecimal;
+import java.sql.Timestamp;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
 import java.util.Collection;
 import java.util.Date;
 
+import org.apache.empire.commons.ClassUtils;
 import org.apache.empire.commons.ObjectUtils;
+import org.apache.empire.commons.StringUtils;
 import org.apache.empire.data.Column;
 import org.apache.empire.data.ColumnExpr;
 import org.apache.empire.data.EntityType;
 import org.apache.empire.data.RecordData;
+import org.apache.empire.db.DBRecordBase;
+import org.apache.empire.db.exceptions.FieldIllegalValueException;
 import org.apache.empire.db.exceptions.NoPrimaryKeyException;
 import org.apache.empire.exceptions.InvalidArgumentException;
 import org.apache.empire.exceptions.ItemNotFoundException;
-import org.apache.empire.exceptions.NotImplementedException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -127,6 +133,7 @@ public class DataListEntry implements RecordData, 
Serializable
     public void updateData(RecordData recData)
     {
         ColumnExpr[] cols = head.getColumns(); 
+        DBRecordBase dbrb =(recData instanceof DBRecordBase) ? 
(DBRecordBase)recData : null;
         for (int i=0; i<cols.length; i++)
         {
             ColumnExpr col = ObjectUtils.unwrap(cols[i]);
@@ -141,6 +148,10 @@ public class DataListEntry implements RecordData, 
Serializable
                 continue;
             // update
             try {
+                // check valid
+                if (dbrb!=null && !dbrb.isValueValid(ri))
+                    continue;
+                // set data
                 values[i] = recData.getValue(ri);
             } catch(Exception e) {
                 log.error("Failed to update value for column {}", 
cols[i].getName());
@@ -148,6 +159,11 @@ public class DataListEntry implements RecordData, 
Serializable
         }
     }
     
+    /**
+     * Modifies a particular value
+     * @param col the column to modify
+     * @param value the new value
+     */
     public void modifyValue(ColumnExpr col, Object value)
     {
         int i = getFieldIndex(col);
@@ -157,6 +173,11 @@ public class DataListEntry implements RecordData, 
Serializable
         values[i] = value;
     }
     
+    /**
+     * Returns the row-number
+     * This works only, if the row number has been set in the constructor
+     * @return the row number
+     */
     public int getRownum()
     {
         return rownum;
@@ -193,6 +214,11 @@ public class DataListEntry implements RecordData, 
Serializable
         return head.columns[index];
     }
     
+    /**
+     * Returns a value based on a field index.
+     * @param index the field index
+     * @return the field value
+     */
     @Override
     public Object getValue(int index)
     {
@@ -201,176 +227,486 @@ public class DataListEntry implements RecordData, 
Serializable
         return values[index];
     }
     
-    @Override
-    public final Object get(ColumnExpr column)
-    {
-        return getValue(indexOf(column));
-    }
-    
     /**
-     * Deprecated Renamed to get(...)
-     * @param column the column
-     * @return the field value   
+     * Deprecated Renamed to get(...)   
+     * @param column the column for which to obtain the value
+     * @return the record value
      */
     @Deprecated
     public Object getValue(ColumnExpr column)
     {
         return get(column);
     }
-
-    public final <T> T get(Column column, Class<T> returnType)
+    
+    /**
+     * Returns a data value for the desired column .
+     * 
+     * @param column the column for which to obtain the value
+     * @return the record value
+     */
+    @Override
+    public final Object get(ColumnExpr column)
     {
-        return ObjectUtils.convert(returnType, get(column));
+        return getValue(getFieldIndex(column));
     }
 
-    public final Object[] getArray(ColumnExpr... columns)
+    /**
+     * Returns the value of a field as an object of a given (wrapper)type
+     * @param <T> the value type
+     * @param column the column for which to retrieve the value
+     * @param returnType the type of the returned value
+     * @return the value
+     */
+    public final <T> T get(Column column, Class<T> returnType)
     {
-        Object[] values = new Object[columns.length];
-        for (int i=0; i<columns.length; i++)
-        {
-            int index = getFieldIndex(columns[i]);
-            if (index<0)
-                throw new ItemNotFoundException(columns[i].getName()); 
-            values[i] = getValue(index);
-        }
-        return values;
+        return ObjectUtils.convert(returnType, get(column));
     }
     
+    /**
+     * Checks whether or not the value for the given column is null.
+     * 
+     * @param index index of the column
+     * @return true if the value is null or false otherwise
+     */
     @Override
     public boolean isNull(int index)
     {
         return ObjectUtils.isEmpty(getValue(index));
     }
+
+    /**
+     * Checks whether or not the value for the given column is null.
+     * 
+     * @param column identifying the column
+     * @return true if the value is null or false otherwise
+     */
+    @Override
+    public final boolean isNull(ColumnExpr column)
+    {
+        return isNull(getFieldIndex(column));
+    }
+
+    /**
+     * Returns true if a numeric value is Zero
+     * For numeric columns only!
+     * @param column the column
+     * @return true if the value is zero or false otherwise 
+     */
+    public boolean isZero(ColumnExpr column)
+    {
+        if (column==null || column.getDataType().isNumeric())
+            throw new InvalidArgumentException("column", column);
+        // check for zero
+        Object v = get(column);
+        return (v instanceof Number) ? ObjectUtils.isZero((Number)v) : true;
+    }
     
     /*
      * Conversion functions
      */
-
-    public String getString(int index)
-    {   // Get String value
-        Object o = getValue(index);
-        return ObjectUtils.getString(o);
+    
+    /**
+     * Returns a data value identified by the column index.
+     * The data value is converted to a string if necessary.
+     * 
+     * @param index index of the column
+     * @return the value
+     */
+    public final String getString(int index)
+    {
+        return ObjectUtils.getString(getValue(index));
     }
 
+    /**
+     * Returns a data value for the desired column.
+     * The data value is converted to a string if necessary.
+     * 
+     * @param column identifying the column
+     * @return the value
+     */
     public final String getString(ColumnExpr column)
     {
-        return getString(indexOf(column));
+        return getString(getFieldIndex(column));
     }
 
-    public int getInt(int index)
-    {   // Get Integer value
-        Object o = getValue(index);
-        return ObjectUtils.getInteger(o);
+    /**
+     * Returns a data value identified by the column index.
+     * The value is converted to integer if necessary .
+     * 
+     * @param index index of the column
+     * @return the record value
+     */
+    public final int getInt(int index)
+    {
+        return ObjectUtils.getInteger(getValue(index));
     }
     
+    /**
+     * Returns a data value for the desired column.
+     * The data value is converted to integer if necessary.
+     * 
+     * @param column identifying the column
+     * @return the value
+     */
     public final int getInt(ColumnExpr column)
     {
-        return getInt(indexOf(column));
+        return getInt(getFieldIndex(column));
     }
 
-    public long getLong(int index)
-    {   // Get Long value
-        Object o = getValue(index);
-        return ObjectUtils.getLong(o);
+    /**
+     * Returns a data value identified by the column index.
+     * The data value is converted to a long if necessary.
+     * 
+     * @param index index of the column
+     * @return the value
+     */
+    public final long getLong(int index)
+    {
+        return ObjectUtils.getLong(getValue(index));
     }
     
+    /**
+     * Returns a data value for the desired column.
+     * The data value is converted to a long if necessary.
+     * 
+     * @param column identifying the column
+     * @return the value
+     */
     public final long getLong(ColumnExpr column)
     {
-        return getLong(indexOf(column));
+        return getLong(getFieldIndex(column));
     }
 
-    public BigDecimal getDecimal(int index)
-    {   // Get Integer value
-        Object o = getValue(index);
-        return ObjectUtils.getDecimal(o);
+    /**
+     * Returns a data value identified by the column index.
+     * The data value is converted to double if necessary.
+     * 
+     * @param index index of the column
+     * @return the value
+     */
+    public double getDouble(int index)
+    {
+        return ObjectUtils.getDouble(getValue(index));
     }
-    
+
+    /**
+     * Returns a data value for the desired column.
+     * The data value is converted to double if necessary.
+     * 
+     * @param column identifying the column
+     * @return the value
+     */
+    public final double getDouble(ColumnExpr column)
+    {
+        return getDouble(getFieldIndex(column));
+    }
+
+    /**
+     * Returns a data value identified by the column index.
+     * The data value is converted to double if necessary.
+     * 
+     * @param index index of the column
+     * @return the value
+     */
+    public final BigDecimal getDecimal(int index)
+    {
+        return ObjectUtils.getDecimal(getValue(index));
+    }
+
+    /**
+     * Returns a data value for the desired column.
+     * The data value is converted to BigDecimal if necessary.
+     * 
+     * @param column identifying the column
+     * @return the value
+     */
     public final BigDecimal getDecimal(ColumnExpr column)
     {
-        return getDecimal(indexOf(column));
+        return getDecimal(getFieldIndex(column));
     }
     
-    public boolean getBoolean(int index)
-    {   // Get Integer value
-        Object o = getValue(index);
-        return ObjectUtils.getBoolean(o);
+    /**
+     * Returns a data value identified by the column index.
+     * The data value is converted to boolean if necessary.
+     * 
+     * @param index index of the column
+     * @return the value
+     */
+    public final boolean getBoolean(int index)
+    {
+        return ObjectUtils.getBoolean(getValue(index));
     }
     
+    /**
+     * Returns a data value for the desired column.
+     * The data value is converted to boolean if necessary.
+     * 
+     * @param column identifying the column
+     * @return the value
+     */
     public final boolean getBoolean(ColumnExpr column)
+    { 
+        return getBoolean(getFieldIndex(column));
+    }
+    
+    /**
+     * Returns the value as as a java.util.Date object
+     * The data value is converted to a Date if necessary.
+     * 
+     * @param index index of the column
+     * @return the value
+     */
+    public final Date getDate(int index)
+    {
+        return ObjectUtils.getDate(getValue(index));
+    }
+    
+    /**
+     * Returns the value as as a java.util.Date object
+     * The data value is converted to a Date if necessary.
+     * 
+     * @param column identifying the column
+     * @return the value
+     */
+    public final Date getDate(ColumnExpr column)
+    {
+        return getDate(getFieldIndex(column));
+    }
+
+    /**
+     * Returns the value as as a java.sql.Timestamp object
+     * @return the Timestamp
+     */
+    public final Timestamp getTimestamp(int index)
+    {
+        return ObjectUtils.getTimestamp(getValue(index));
+    }
+
+    /**
+     * Returns the value as as a java.sql.Timestamp object
+     * @return the Timestamp
+     */
+    public final Timestamp getTimestamp(ColumnExpr column)
+    {
+        return getTimestamp(getFieldIndex(column));
+    }
+
+    /**
+     * Returns a data value identified by the column index.
+     * The data value is converted to a Date if necessary.
+     * 
+     * @param index index of the column
+     * @return the value
+     */
+    public final LocalDate getLocalDate(int index)
+    {
+        return ObjectUtils.getLocalDate(getValue(index));
+    }
+    
+    /**
+     * Returns a data value for the desired column.
+     * The data value is converted to a Date if necessary.
+     * 
+     * @param column identifying the column
+     * @return the value
+     */
+    public final LocalDate getLocalDate(ColumnExpr column)
+    {
+        return getLocalDate(getFieldIndex(column));
+    }
+
+    /**
+     * Returns a data value identified by the column index.
+     * The data value is converted to a Date if necessary.
+     * 
+     * @param index index of the column
+     * @return the value
+     */
+    public final LocalDateTime getLocalDateTime(int index)
+    {
+        return ObjectUtils.getLocalDateTime(getValue(index));
+    }
+    
+    /**
+     * Returns a data value for the desired column.
+     * The data value is converted to a Date if necessary.
+     * 
+     * @param column identifying the column
+     * @return the value
+     */
+    public final LocalDateTime getLocalDateTime(ColumnExpr column)
     {
-        return getBoolean(indexOf(column));
+        return getLocalDateTime(getFieldIndex(column));
     }
 
+    /**
+     * Returns the value of a field as an enum
+     * For numeric columns the value is assumed to be an ordinal of the 
enumeration item
+     * For non numeric columns the value is assumed to be the name of the 
enumeration item
+     * 
+     * @param <T> the enum type
+     * @param index index of the field
+     * @param enumType the enum type class
+     * @return the enum value
+     */
     public <T extends Enum<?>> T getEnum(int index, Class<T> enumType)
     {   // check for null
         if (isNull(index))
             return null;
-        // check column data type
+        // convert
         ColumnExpr col = getColumn(index);
-        boolean numeric = col.getDataType().isNumeric();
-        return ObjectUtils.getEnum(enumType, (numeric ? getInt(index) : 
getValue(index)));
+        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.getUpdateColumn(), value, 
e);
+        }
     }
 
+    /**
+     * Returns the value of a field as an enum
+     * For numeric columns the value is assumed to be an ordinal of the 
enumeration item
+     * For non numeric columns the value is assumed to be the name of the 
enumeration item
+     * 
+     * @param <T> the enum type
+     * @param column the column for which to retrieve the value
+     * @param enumType the enum type class
+     * @return the enum value
+     */
     public final <T extends Enum<?>> T getEnum(ColumnExpr column, Class<T> 
enumType)
     {
-        return getEnum(indexOf(column), enumType);
+        return getEnum(getFieldIndex(column), enumType);
     }
 
+    /**
+     * Returns the value of a field as an enum
+     * This assumes that the column attribute "enumType" has been set to an 
enum type
+     * For numeric columns the value is assumed to be an ordinal of the 
enumeration item
+     * 
+     * @param <T> the enum type
+     * @param column the column for which to retrieve the value
+     * @return the enum value
+     */
     @SuppressWarnings("unchecked")
     public final <T extends Enum<?>> T getEnum(Column column)
     {
-        Class<T> enumType = (Class<T>)column.getEnumType();
+        Class<Enum<?>> enumType = column.getEnumType();
         if (enumType==null)
         {   // Not an enum column (Attribute "enumType" has not been set)
             throw new InvalidArgumentException("column", column);
         }
-        return getEnum(indexOf(column), enumType);
+        return getEnum(getFieldIndex(column), (Class<T>)enumType);
     }
-    
-    public Date getDate(int index)
+
+    /**
+     * Returns an array of values for the given column expressions
+     * 
+     * @param columns the column expressions
+     * @return the corresponding record values
+     */
+    public final Object[] getArray(ColumnExpr... columns)
     {
-        Object o = getValue(index);
-        return ObjectUtils.getDate(o);
+        Object[] values = new Object[columns.length];
+        for (int i=0; i<columns.length; i++)
+        {
+            int index = getFieldIndex(columns[i]);
+            if (index<0)
+                throw new ItemNotFoundException(columns[i].getName()); 
+            values[i] = getValue(index);
+        }
+        return values;
     }
-        
-    public final Date getDate(ColumnExpr column)
+
+    /**
+     * Returns the value of a column as a formatted text
+     * This converts the value to a string if necessary and performs an 
options lookup
+     * To customize conversion please override convertToString()
+     * @param column the column for which to get the formatted value
+     * @return the formatted value
+     */
+    public String getText(ColumnExpr col)
     {
-        return getDate(indexOf(column));
+        int idx = getFieldIndex(col);
+        return head.getText(idx, values[idx]);
     }
-    
-    @Override
-    public final boolean isNull(ColumnExpr column)
+
+    /**
+     * Returns the value of a column as a formatted text
+     * This converts the value to a string if necessary and performs an 
options lookup
+     * To customize conversion please override convertToString()
+     * @param name the column for which to get the formatted value
+     * @return the formatted value
+     */
+    public final String getText(String name)
     {
-        return isNull(indexOf(column));
+        return getText(getColumn(getFieldIndex(name)));
     }
-    
+
+    /**
+     * Injects the current field values into a java bean.
+     * The property name is detected by ColumnExpr.getBeanPropertyName()
+     * @param bean the Java Bean for which to set the properties
+     * @param ignoreList list of columns to skip (optional)
+     * @return the number of bean properties set on the supplied bean
+     */
     @Override
     public int setBeanProperties(Object bean, Collection<? extends ColumnExpr> 
ignoreList)
     {
-        throw new NotImplementedException(this, "setBeanProperties");
+        // Add all Columns
+        int count = 0;
+        for (int i = 0; i < getFieldCount(); i++)
+        {   // Check Property
+            ColumnExpr column = getColumn(i);
+            if ((column instanceof Column) && ((Column)column).isReadOnly())
+                continue;
+            if (ignoreList != null && ignoreList.contains(column))
+                continue; // ignore this property
+            // Get Property Name
+            setBeanProperty(column, bean, this.getValue(i));
+            count++;
+        }
+        return count;
     }
-    
-    public int setBeanProperties(Object bean)
+
+    /**
+     * Injects the current field values into a java bean.
+     * The property name is detected by ColumnExpr.getBeanPropertyName()
+     * @param bean the Java Bean for which to set the properties
+     * @return the number of bean properties set on the supplied bean
+     */
+    public final int setBeanProperties(Object bean)
     {
         return setBeanProperties(bean, null);
     }
     
-    /*
-     * Miscellaneous functions
+    /**
+     * Set a single property value on a java bean object
+     *
+     * @param column the column expression
+     * @param bean the bean
+     * @param value the value
      */
-
-    public String getText(String name)
-    {
-        int idx = getFieldIndex(name);
-        return head.getText(idx, values[idx]);
-    }
-
-    public String getText(ColumnExpr col)
+    protected void setBeanProperty(ColumnExpr column, Object bean, Object 
value)
     {
-        int idx = getFieldIndex(col);
-        return head.getText(idx, values[idx]);
+        if (value!=null)
+        {   // Convert to enum
+            Class<Enum<?>> enumType = column.getEnumType();
+            if (enumType!=null)
+                value = ObjectUtils.getEnum(enumType, value);
+        }
+        String property = column.getBeanPropertyName();
+        ClassUtils.setBeanProperty(bean, property, value);
     }
     
+    /*
+     * Miscellaneous functions
+     */
+    
     @Override
     public String toString()
     {
@@ -383,6 +719,11 @@ public class DataListEntry implements RecordData, 
Serializable
         return b.toString();
     }
 
+    /**
+     * Returns the field index
+     * If the column cannot be found a ItemNotFoundException is thrown
+     * @param column the column for which to return the index
+     * @return the index
     protected int indexOf(ColumnExpr column)
     {
         int index = head.getColumnIndex(column);
@@ -390,5 +731,6 @@ public class DataListEntry implements RecordData, 
Serializable
             throw new ItemNotFoundException(column.getName());
         return index;
     }
+     */
     
 }
diff --git 
a/empire-db/src/main/java/org/apache/empire/data/list/DataListHead.java 
b/empire-db/src/main/java/org/apache/empire/data/list/DataListHead.java
index c48fa2e9..e4ca8bf4 100644
--- a/empire-db/src/main/java/org/apache/empire/data/list/DataListHead.java
+++ b/empire-db/src/main/java/org/apache/empire/data/list/DataListHead.java
@@ -96,14 +96,14 @@ public class DataListHead implements Serializable
      * Returns the value of a column as a formatted text
      * This converts the value to a string if necessary and performs an 
options lookup
      * To customize conversion please override convertToString()
-     * @param idx the field index for which to get the formatted value
+     * @param index the field index for which to get the formatted value
      * @param value the value to format
      * @return the formatted value
      */
-    public String getText(int idx, Object value)
+    public String getText(int index, Object value)
     {   // find text
         String text;
-        ColumnExpr column = columns[idx];
+        ColumnExpr column = columns[index];
         // check options first
         Options options = column.getOptions();
         if (options!=null && options.has(value))
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 b4b1c9fc..ad769810 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
@@ -17,18 +17,14 @@
  * under the License.
  */
 package org.apache.empire.db;
-import java.beans.PropertyDescriptor;
-// XML
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.math.BigDecimal;
+import java.sql.Timestamp;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.util.Collection;
 import java.util.Date;
 
-import org.apache.commons.beanutils.BeanUtils;
-import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.empire.commons.ClassUtils;
 import org.apache.empire.commons.ObjectUtils;
 import org.apache.empire.commons.Options;
 import org.apache.empire.commons.StringUtils;
@@ -37,10 +33,8 @@ import org.apache.empire.data.ColumnExpr;
 import org.apache.empire.data.RecordData;
 import org.apache.empire.db.context.DBContextAware;
 import org.apache.empire.db.exceptions.FieldIllegalValueException;
-import org.apache.empire.exceptions.BeanPropertySetException;
 import org.apache.empire.exceptions.InvalidArgumentException;
 import org.apache.empire.exceptions.ItemNotFoundException;
-import org.apache.empire.exceptions.PropertyReadOnlyException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
@@ -95,75 +89,96 @@ public abstract class DBRecordData extends DBObject
     {
         return get(column);
     }
+    
+    /**
+     * Returns a data value for the desired column .
+     * 
+     * @param column the column for which to obtain the value
+     * @return the record value
+     */
+    @Override
+    public final Object get(ColumnExpr column)
+    {
+        return getValue(getFieldIndex(column));
+    }
 
     /**
-     * Deprecated Renamed to get(...)   
+     * Returns the value of a field as an object of a given (wrapper)type
      * @param <T> the value type
      * @param column the column for which to retrieve the value
      * @param returnType the type of the returned value
      * @return the value
      */
-    @Deprecated
-    public final <T> T getValue(Column column, Class<T> returnType)
+    public final <T> T get(Column column, Class<T> returnType)
     {
-        return get(column, returnType);
+        return ObjectUtils.convert(returnType, get(column));
     }
-
+    
     /**
-     * Deprecated Renamed to get(...)   
-     * @param columns the columns for which to obtain the values
-     * @return the record values
+     * Checks whether or not the value for the given column is null.
+     * 
+     * @param index index of the column
+     * @return true if the value is null or false otherwise
      */
-    @Deprecated
-    public final Object[] getValues(ColumnExpr... columns)
+    @Override
+    public boolean isNull(int index)
     {
-        return getArray(columns);
+        return ObjectUtils.isEmpty(getValue(index));
     }
-    
+
     /**
-     * Returns a data value for the desired column .
+     * Checks whether or not the value for the given column is null.
      * 
-     * @param column the column for which to obtain the value
-     * @return the record value
+     * @param column identifying the column
+     * @return true if the value is null or false otherwise
      */
     @Override
-    public final Object get(ColumnExpr column)
+    public final boolean isNull(ColumnExpr column)
     {
-        int index = getFieldIndex(column);
-        if (index<0)
-            throw new ItemNotFoundException(column.getName()); 
-        return getValue(index);
+        return isNull(getFieldIndex(column));
     }
 
     /**
-     * Returns the value of a field as an object of a given (wrapper)type
-     * @param <T> the value type
-     * @param column the column for which to retrieve the value
-     * @param returnType the type of the returned value
+     * Returns true if a numeric value is Zero
+     * For numeric columns only!
+     * @param column the column
+     * @return true if the value is zero or false otherwise 
+     */
+    public boolean isZero(ColumnExpr column)
+    {
+        if (column==null || column.getDataType().isNumeric())
+            throw new InvalidArgumentException("column", column);
+        // check for zero
+        Object v = get(column);
+        return (v instanceof Number) ? ObjectUtils.isZero((Number)v) : true;
+    }
+    
+    /*
+     * Conversion functions
+     */
+    
+    /**
+     * Returns a data value identified by the column index.
+     * The data value is converted to a string if necessary.
+     * 
+     * @param index index of the column
      * @return the value
      */
-    public final <T> T get(Column column, Class<T> returnType)
+    public final String getString(int index)
     {
-        return ObjectUtils.convert(returnType, get(column));
+        return ObjectUtils.getString(getValue(index));
     }
 
     /**
-     * Returns an array of values for the given column expressions
+     * Returns a data value for the desired column.
+     * The data value is converted to a string if necessary.
      * 
-     * @param columns the column expressions
-     * @return the corresponding record values
+     * @param column identifying the column
+     * @return the value
      */
-    public final Object[] getArray(ColumnExpr... columns)
+    public final String getString(ColumnExpr column)
     {
-        Object[] values = new Object[columns.length];
-        for (int i=0; i<columns.length; i++)
-        {
-            int index = getFieldIndex(columns[i]);
-            if (index<0)
-                throw new ItemNotFoundException(columns[i].getName()); 
-            values[i] = getValue(index);
-        }
-        return values;
+        return getString(getFieldIndex(column));
     }
 
     /**
@@ -173,7 +188,7 @@ public abstract class DBRecordData extends DBObject
      * @param index index of the column
      * @return the record value
      */
-    public int getInt(int index)
+    public final int getInt(int index)
     {
         return ObjectUtils.getInteger(getValue(index));
     }
@@ -197,7 +212,7 @@ public abstract class DBRecordData extends DBObject
      * @param index index of the column
      * @return the value
      */
-    public long getLong(int index)
+    public final long getLong(int index)
     {
         return ObjectUtils.getLong(getValue(index));
     }
@@ -245,7 +260,7 @@ public abstract class DBRecordData extends DBObject
      * @param index index of the column
      * @return the value
      */
-    public BigDecimal getDecimal(int index)
+    public final BigDecimal getDecimal(int index)
     {
         return ObjectUtils.getDecimal(getValue(index));
     }
@@ -269,7 +284,7 @@ public abstract class DBRecordData extends DBObject
      * @param index index of the column
      * @return the value
      */
-    public boolean getBoolean(int index)
+    public final boolean getBoolean(int index)
     {
         return ObjectUtils.getBoolean(getValue(index));
     }
@@ -287,51 +302,63 @@ public abstract class DBRecordData extends DBObject
     }
     
     /**
-     * Returns a data value identified by the column index.
-     * The data value is converted to a string if necessary.
+     * Returns the value as as a java.util.Date object
+     * The data value is converted to a Date if necessary.
      * 
      * @param index index of the column
      * @return the value
      */
-    public String getString(int index)
+    public final Date getDate(int index)
     {
-        return ObjectUtils.getString(getValue(index));
+        return ObjectUtils.getDate(getValue(index));
     }
-
+    
     /**
-     * Returns a data value for the desired column.
-     * The data value is converted to a string if necessary.
+     * Returns the value as as a java.util.Date object
+     * The data value is converted to a Date if necessary.
      * 
      * @param column identifying the column
      * @return the value
      */
-    public final String getString(ColumnExpr column)
+    public final Date getDate(ColumnExpr column)
     {
-        return getString(getFieldIndex(column));
+        return getDate(getFieldIndex(column));
     }
 
     /**
-     * Returns a data value identified by the column index.
-     * The data value is converted to a Date if necessary.
-     * 
-     * @param index index of the column
-     * @return the value
+     * Deprecated: Use getDate(index) instead.
      */
+    @Deprecated
     public final Date getDateTime(int index)
     {
-        return ObjectUtils.getDate(getValue(index));
+        return getDate(index);
     }
     
     /**
-     * Returns a data value for the desired column.
-     * The data value is converted to a Date if necessary.
-     * 
-     * @param column identifying the column
-     * @return the value
+     * Deprecated: Use getDate(column) instead.
      */
+    @Deprecated
     public final Date getDateTime(ColumnExpr column)
     {
-        return getDateTime(getFieldIndex(column));
+        return getDate(column);
+    }
+
+    /**
+     * Returns the value as as a java.sql.Timestamp object
+     * @return the Timestamp
+     */
+    public final Timestamp getTimestamp(int index)
+    {
+        return ObjectUtils.getTimestamp(getValue(index));
+    }
+
+    /**
+     * Returns the value as as a java.sql.Timestamp object
+     * @return the Timestamp
+     */
+    public final Timestamp getTimestamp(ColumnExpr column)
+    {
+        return getTimestamp(getFieldIndex(column));
     }
 
     /**
@@ -429,7 +456,9 @@ public abstract class DBRecordData extends DBObject
     /**
      * Returns the value of a field as an enum
      * This assumes that the column attribute "enumType" has been set to an 
enum type
+     * For numeric columns the value is assumed to be an ordinal of the 
enumeration item
      * 
+     * @param <T> the enum type
      * @param column the column for which to retrieve the value
      * @return the enum value
      */
@@ -443,29 +472,24 @@ public abstract class DBRecordData extends DBObject
         }
         return getEnum(getFieldIndex(column), (Class<T>)enumType);
     }
-    
-    /**
-     * Checks whether or not the value for the given column is null.
-     * 
-     * @param index index of the column
-     * @return true if the value is null or false otherwise
-     */
-    @Override
-    public boolean isNull(int index)
-    {
-        return ObjectUtils.isEmpty(getValue(index));
-    }
 
     /**
-     * Checks whether or not the value for the given column is null.
+     * Returns an array of values for the given column expressions
      * 
-     * @param column identifying the column
-     * @return true if the value is null or false otherwise
+     * @param columns the column expressions
+     * @return the corresponding record values
      */
-    @Override
-    public final boolean isNull(ColumnExpr column)
+    public final Object[] getArray(ColumnExpr... columns)
     {
-        return isNull(getFieldIndex(column));
+        Object[] values = new Object[columns.length];
+        for (int i=0; i<columns.length; i++)
+        {
+            int index = getFieldIndex(columns[i]);
+            if (index<0)
+                throw new ItemNotFoundException(columns[i].getName()); 
+            values[i] = getValue(index);
+        }
+        return values;
     }
     
     /**
@@ -505,84 +529,22 @@ public abstract class DBRecordData extends DBObject
     }
 
     /**
-     * Convert a non-string value to a string
-     * @param column the column expression 
-     * @param value the value to format
-     * @return the formatted string
-     */
-    protected String formatValue(ColumnExpr column, Object value)
-    {
-        return ObjectUtils.getString(value);
-    }
-    
-    /**
-     * Set a single property value of a java bean object used by 
readProperties.
-     *
-     * @param column the column expression
-     * @param bean the bean
-     * @param property the property
-     * @param value the value
+     * Returns the value of a column as a formatted text
+     * This converts the value to a string if necessary and performs an 
options lookup
+     * To customize conversion please override convertToString()
+     * @param name the column for which to get the formatted value
+     * @return the formatted value
      */
-    protected void setBeanProperty(ColumnExpr column, Object bean, String 
property, Object value)
+    public final String getText(String name)
     {
-        if (StringUtils.isEmpty(property))
-            property = column.getBeanPropertyName();
-        try
-        {
-            if (bean==null)
-                throw new InvalidArgumentException("bean", bean);
-            if (StringUtils.isEmpty(property))
-                throw new InvalidArgumentException("property", property);
-            if (log.isTraceEnabled())
-                log.trace("{}: setting property '{}' to {}", 
bean.getClass().getName(), property, value);
-            /*
-            if (value instanceof Date)
-            {   // Patch for date bug in BeanUtils
-                value = DateUtils.addDate((Date)value, 0, 0, 0);
-            }
-            */
-            // Set Property Value
-            if (value!=null)
-            {   // Convert to enum
-                Class<Enum<?>> enumType = column.getEnumType();
-                if (enumType!=null)
-                    value = ObjectUtils.getEnum(enumType, value);
-                // Bean utils will convert if necessary
-                BeanUtils.setProperty(bean, property, value);
-            }
-            else
-            {   // Don't convert, just set
-                PropertyDescriptor pd = 
PropertyUtils.getPropertyDescriptor(bean, property);
-                if (pd==null)
-                    return; // No such property
-                // get the write method
-                final Method method = PropertyUtils.getWriteMethod(pd);
-                if (method == null)
-                    throw new PropertyReadOnlyException(property);
-                // invoke
-                method.invoke(bean, value);
-            }
-          // IllegalAccessException
-        } catch (IllegalAccessException e)
-        {   log.error(bean.getClass().getName() + ": unable to set property '" 
+ property + "'");
-            throw new BeanPropertySetException(bean, property, e);
-          // InvocationTargetException  
-        } catch (InvocationTargetException e)
-        {   log.error(bean.getClass().getName() + ": unable to set property '" 
+ property + "'");
-            throw new BeanPropertySetException(bean, property, e);
-          // NoSuchMethodException   
-        } catch (NoSuchMethodException e)
-        {   log.error(bean.getClass().getName() + ": unable to set property '" 
+ property + "'");
-            throw new BeanPropertySetException(bean, property, e);
-        } catch (NullPointerException e)
-        {   log.error(bean.getClass().getName() + ": unable to set property '" 
+ property + "'");
-            throw new BeanPropertySetException(bean, property, e);
-        }
+        return getText(getColumn(getFieldIndex(name)));
     }
 
     /**
      * Injects the current field values into a java bean.
-     * 
+     * The property name is detected by ColumnExpr.getBeanPropertyName()
+     * @param bean the Java Bean for which to set the properties
+     * @param ignoreList list of columns to skip (optional)
      * @return the number of bean properties set on the supplied bean
      */
     @Override
@@ -593,12 +555,12 @@ public abstract class DBRecordData extends DBObject
         for (int i = 0; i < getFieldCount(); i++)
         {   // Check Property
             ColumnExpr column = getColumn(i);
+            if ((column instanceof Column) && ((Column)column).isReadOnly())
+                continue;
             if (ignoreList != null && ignoreList.contains(column))
                 continue; // ignore this property
             // Get Property Name
-            String property = column.getBeanPropertyName();
-            if (property!=null)
-                setBeanProperty(column, bean, property, this.getValue(i));
+            setBeanProperty(column, bean, this.getValue(i));
             count++;
         }
         return count;
@@ -606,7 +568,8 @@ public abstract class DBRecordData extends DBObject
 
     /**
      * Injects the current field values into a java bean.
-     * @param bean the bean
+     * The property name is detected by ColumnExpr.getBeanPropertyName()
+     * @param bean the Java Bean for which to set the properties
      * @return the number of bean properties set on the supplied bean
      */
     public final int setBeanProperties(Object bean)
@@ -614,4 +577,38 @@ public abstract class DBRecordData extends DBObject
         return setBeanProperties(bean, null);
     }
     
+    /**
+     * Set a single property value on a java bean object
+     *
+     * @param column the column expression
+     * @param bean the bean
+     * @param value the value
+     */
+    protected void setBeanProperty(ColumnExpr column, Object bean, Object 
value)
+    {
+        if (value!=null)
+        {   // Convert to enum
+            Class<Enum<?>> enumType = column.getEnumType();
+            if (enumType!=null)
+                value = ObjectUtils.getEnum(enumType, value);
+        }
+        String property = column.getBeanPropertyName();
+        ClassUtils.setBeanProperty(bean, property, value);
+    }
+    
+    /*
+     * Miscellaneous functions
+     */
+
+    /**
+     * Convert a non-string value to a string
+     * @param column the column expression 
+     * @param value the value to format
+     * @return the formatted string
+     */
+    protected String formatValue(ColumnExpr column, Object value)
+    {
+        return ObjectUtils.getString(value);
+    }
+    
 }
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java 
b/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java
index 44f0dcc6..2765d473 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java
@@ -37,6 +37,7 @@ import org.apache.empire.data.ColumnExpr;
 import org.apache.empire.data.DataType;
 import org.apache.empire.data.EntityType;
 import org.apache.empire.data.Record;
+import org.apache.empire.data.RecordData;
 import org.apache.empire.db.DBRelation.DBCascadeAction;
 import org.apache.empire.db.DBRelation.DBReference;
 import org.apache.empire.db.context.DBContextBase;
@@ -1292,6 +1293,21 @@ public abstract class DBRowSet extends DBExpr implements 
EntityType
         // just use the context
         return context.createCommand();
     }
+    
+    /**
+     * Adds key constraints to a DBCommand object
+     * @param cmd the command to add the constraints to
+     * @param data the record from which to take the values
+     */
+    public void addKeyConstraints(DBCommand cmd, RecordData data)
+    {
+        DBColumn[] keyColumns = getKeyColumns();
+        if (keyColumns==null || keyColumns.length==0)
+            throw new NoPrimaryKeyException(this);
+        // Collect key
+        for (int i=0; i<keyColumns.length; i++)
+            cmd.where(keyColumns[i].is(data.get(keyColumns[i])));
+    }
 
     /**
      * Returns additional data stored on a record by the RowSet


Reply via email to