empire-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From doeb...@apache.org
Subject svn commit: r683173 [6/10] - in /incubator/empire-db/trunk/core/Empire-db: ./ .settings/ bin/ lib/ src/ src/META-INF/ src/org/ src/org/apache/ src/org/apache/empire/ src/org/apache/empire/commons/ src/org/apache/empire/data/ src/org/apache/empire/data/...
Date Wed, 06 Aug 2008 08:47:43 GMT
Added: incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBRecord.java
URL: http://svn.apache.org/viewvc/incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBRecord.java?rev=683173&view=auto
==============================================================================
--- incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBRecord.java (added)
+++ incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBRecord.java Wed Aug  6 01:47:37 2008
@@ -0,0 +1,921 @@
+/*
+ * ESTEAM Software GmbH
+ */
+package org.apache.empire.db;
+
+import java.lang.reflect.InvocationTargetException;
+import java.sql.Connection;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.commons.beanutils.BeanUtilsBean;
+import org.apache.commons.beanutils.PropertyUtilsBean;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.empire.commons.Errors;
+import org.apache.empire.commons.ObjectUtils;
+import org.apache.empire.commons.Options;
+import org.apache.empire.data.Column;
+import org.apache.empire.data.ColumnExpr;
+import org.apache.empire.data.DataType;
+import org.apache.empire.data.Record;
+import org.apache.empire.xml.XMLUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+
+/**
+ * This class handles one record from a database table.
+ * <P>
+ * 
+ * @author ESTEAM software <A TARGET="esteam" HREF="http://www.esteam.de">www.esteam.de</A>
+ */
+public class DBRecord extends DBRecordData implements Record, Cloneable
+{
+    public static final int REC_INVALID  = -1;
+    public static final int REC_EMTPY    = 0;
+    public static final int REC_VALID    = 1;
+    public static final int REC_MODIFIED = 2;
+    public static final int REC_NEW      = 3;
+
+    // Logger
+    @SuppressWarnings("hiding")
+    protected static Log    log          = LogFactory.getLog(DBRecord.class);
+
+    // This is the record data
+    private int             state;
+    private DBRowSet        rowset;
+    private Object[]        fields;
+    private boolean[]       modified;
+    // Special Rowset Data (usually null)
+    private Object          rowsetData;
+
+    /**
+     * Create a new DBRecord object.<BR>
+     * The record is not attachted to a RowSet and the record's state is intitially set to REC_INVALID.
+     * 
+     * Please derive your own Objects from this class.   
+     */
+    public DBRecord()
+    {
+        state = REC_INVALID;
+        rowset = null;
+        fields = null;
+        modified = null;
+        rowsetData = null;
+    }
+    
+    /**
+     * This method is used internally by the RowSet to initialize the record's properties
+     * @param rowset the rowset to which to attach this record
+     * @param state the state of the record 
+     * @param rowSetData any further RowSet specific data
+     */
+    protected void init(DBRowSet rowset, int state, Object rowSetData)
+    {
+        // Init
+        if (this.rowset != rowset)
+        {   // Set Rowset
+            this.rowset = rowset;
+            if (rowset!=null)
+                fields = new Object[rowset.getColumns().size()];
+            else
+                fields = null;
+            onRowSetChanged();
+        }
+        // Set State
+        changeState(state, rowSetData);
+    }
+    
+    /**
+     * This function provides direct access to the record fields.<BR>
+     * This method is used internally be the RowSet to fill the data.<BR>
+     * @return an array of field values
+     */
+    protected Object[] getFields()
+    {
+        return fields;
+    }
+    
+    /**
+     * This method is used internally be the RowSet to change the record's state<BR>
+     * @param state
+     * @param rowSetData
+     */
+    protected void changeState(int state, Object rowSetData)
+    {
+        this.state = state;
+        this.rowsetData = rowSetData;
+        this.modified = null;
+    }
+
+    /**
+     * Closes the record by releasing all resources and resetting the record's state to invalid.
+     */
+    @Override
+    public void close()
+    {
+        init(null, REC_INVALID, null);
+    }
+    
+    /**
+     * 
+     * @see java.lang.Object#clone()
+     */
+    @Override
+    public DBRecord clone()
+    {
+        try 
+        {
+            DBRecord rec = (DBRecord)super.clone();
+            rec.rowset = rowset;
+            rec.state = state;
+            if (rec.fields == fields && fields!=null)
+                rec.fields = fields.clone();
+            if (rec.modified == modified && modified!=null)
+                rec.modified = modified.clone();
+            rec.rowsetData = rowsetData;
+            return rec;
+            
+        } catch (CloneNotSupportedException e)
+        {
+            log.error("Unable to clone record.", e);
+            return null;
+        }
+    }
+
+    /**
+     * Returns the current DBDatabase object.
+     * 
+     * @return the current DBDatabase object
+     */
+    @Override
+    public DBDatabase getDatabase()
+    {
+        return (rowset != null) ? rowset.db : null;
+    }
+
+    /**
+     * Returns the DBRowSet object.
+     * 
+     * @return the DBRowSet object
+     */
+    public DBRowSet getRowSet()
+    {
+        return rowset;
+    }
+
+    /**
+     * Returns the DBRowSet object.
+     * 
+     * @return the DBRowSet object
+     */
+    public Object getRowSetData()
+    {
+        return rowsetData;
+    }
+
+    /**
+     * Returns the record state.
+     * 
+     * @return the record state
+     */
+    public int getState()
+    {
+        return state;
+    }
+
+    /**
+     * Returns true if the record is valid.
+     * 
+     * @return true if the record is valid
+     */
+    public boolean isValid()
+    {
+        return (state >= DBRecord.REC_VALID);
+    }
+
+    /**
+     * Returns true if the record is modified.
+     * 
+     * @return true if the record is modified
+     */
+    public boolean isModified()
+    {
+        return (state >= DBRecord.REC_MODIFIED);
+    }
+
+    /**
+     * Returns true if this record is a new record.
+     * 
+     * @return true if this record is a new record
+     */
+    public boolean isNew()
+    {
+        return (state == DBRecord.REC_NEW);
+    }
+
+    /**
+     * Returns the number of the columns.
+     * 
+     * @return the number of the columns
+     */
+    @Override
+    public int getFieldCount()
+    {
+        return (fields != null) ? fields.length : 0;
+    }
+
+    /**
+     * Returns the index value by a specified DBColumnExpr object.
+     * 
+     * @return the index value
+     */
+    @Override
+    public int getFieldIndex(ColumnExpr column)
+    {
+        DBColumnExpr expr = (DBColumnExpr)column;
+        return (rowset != null) ? rowset.getColumnIndex(expr.getUpdateColumn()) : -1;
+    }
+
+    /**
+     * Returns the index value by a specified column name.
+     * 
+     * @return the index value
+     */
+    @Override
+    public int getFieldIndex(String column)
+    {
+        if (rowset != null)
+        {
+            List<DBColumn> columns = rowset.getColumns();
+            for (int i = 0; i < columns.size(); i++)
+            {
+                DBColumn col = columns.get(i);
+                if (col.getName().equalsIgnoreCase(column))
+                    return i;
+            }
+        }
+        // not found
+        return -1;
+    }
+
+    /**
+     * Returns the DBColumn for the field at the given index.
+     * @return the index value
+     */
+    public DBColumn getDBColumn(int index)
+    {
+        return (rowset!=null ? rowset.getColumn(index) : null);
+    }
+
+    /**
+     * Implements the Record Interface getColumn method.<BR>
+     * Internally calls getDBColumn()
+     * @return the Column at the specified index 
+     */
+    public final Column getColumn(int index)
+    {
+        return getDBColumn(index);
+    }
+    
+    /**
+     * Returns a DBColumnExpr object by a specified index value.
+     * @return the index value
+     */
+    @Override
+    public final ColumnExpr getColumnExpr(int index)
+    {
+        return getDBColumn(index);
+    }
+    
+    /**
+     * Returns true if the field was modified.
+     * @return true if the field was modified
+     */
+    public boolean wasModified(int index)
+    {
+        if (rowset == null)
+            return error(Errors.ObjectNotValid, getClass().getName());
+        if (index < 0 || index >= fields.length)
+            return error(Errors.OutOfRange, index);
+        // Check modified
+        clearError();
+        if (modified == null)
+            return false;
+        return modified[index];
+    }
+
+    /**
+     * Returns true if the field was modified.
+     * 
+     * @return true if the field was modified
+     */
+    public final boolean wasModified(Column column)
+    {
+        return wasModified(getFieldIndex(column));
+    }
+
+    /**
+     * Sets the modified state of a column.<BR>
+	 * This will force the field to be updated in the database.
+     */
+    public void setModified(DBColumn column, boolean isModified)
+    {
+        if (modified == null)
+        { // Save all original values
+            modified = new boolean[fields.length];
+            for (int j = 0; j < fields.length; j++)
+                modified[j] = false;
+        }
+        int index = getFieldIndex(column);
+        if (index >= 0)
+            modified[index] = isModified;
+        // Set State
+        if (state < REC_MODIFIED && isModified)
+            state = REC_MODIFIED;
+    }
+    
+    /**
+     * returns an array of key columns which uniquely identify the record.
+     * @return the array of key columns if any
+     */
+    public Column[] getKeyColumns()
+    {
+        return rowset.getKeyColumns();
+    }
+
+    /**
+     * Returns the array of primary key columns.
+     * @return the array of primary key columns
+     */
+    public Object[] getKeyValues()
+    {
+        return ((rowset != null) ? rowset.getRecordKey(this) : null);
+    }
+
+    /**
+     * Returns the value for the given column or null if either the index is out of range or the value is not valid (see {@link DBRecord#isValueValid(int)})
+     * @return the index value
+     */
+    @Override
+    public Object getValue(int index)
+    {   // Check state
+        if (fields == null)
+        {   // Record not valid
+            error(Errors.ObjectNotValid, getClass().getName());
+            return null; 
+        }
+        // Check index
+        if (index < 0 || index>= fields.length)
+        {   // Index out of range
+            error(Errors.OutOfRange, index);
+            return null; 
+        }
+        clearError();
+        // Special check for NO_VALUE 
+        if (fields[index] == ObjectUtils.NO_VALUE)
+            return null;
+        // Return field value
+        return fields[index];
+    }
+    
+    /**
+     * Returns whether a field value is provided i.e. the value is not DBRowSet.NO_VALUE<BR>
+     * This function is only useful in cases where records are partically loaded.<BR>
+     * @return true if a valid value is supplied for the given field or false if value is {@link ObjectUtils#NO_VALUE}  
+     */
+    public boolean isValueValid(int index)
+    {   // Check state
+        if (fields == null)
+            return error(Errors.ObjectNotValid, getClass().getName());
+        // Check index
+        if (index < 0 || index>= fields.length)
+        {   // Index out of range
+            return error(Errors.OutOfRange, index);
+        }
+        clearError();
+        // Special check for NO_VALUE
+        return (fields[index] != ObjectUtils.NO_VALUE);
+    }
+
+    /**
+     * Gets the possbile Options for a field in the context of the current record.
+     */
+    public Options getFieldOptions(DBColumn column)
+    {
+        // DBColumn col = ((colexpr instanceof DBColumn) ? ((DBColumn) colexpr) : colexpr.getUpdateColumn());
+        return column.getOptions();
+    }
+
+    /**
+     * Gets the possbile Options for a field in the context of the current record.<BR>
+     * Same as getFieldOptions(DBColumn)
+     * @return the Option
+     */
+    public final Options getFieldOptions(Column column)
+    {
+        return getFieldOptions((DBColumn)column); 
+    }
+
+    /**
+     * Modifies a column value bypassing all checks made by setValue.
+     * Use this to explicitly set invalid values i.e. for temporary storage.
+     * 
+     * @param i index of the column
+     * @param value the column value
+     */
+    public void modifyValue(int i, Object value)
+    { // Init original values
+        if (modified == null)
+        { // Save all original values
+            modified = new boolean[fields.length];
+            for (int j = 0; j < fields.length; j++)
+                modified[j] = false;
+        }
+        // Set Modified
+        if (fields[i]!=ObjectUtils.NO_VALUE || value!=null)
+            modified[i] = true;
+        // Set Value
+        fields[i] = value;
+        // Set State
+        if (state < REC_MODIFIED)
+            state = REC_MODIFIED;
+        // field changed
+        onFieldChanged(i);
+    }
+
+    /**
+     * Sets the value of the column in the record.
+     * The functions checks if the column and the value are valid and whether the
+     * value has changed.
+     * 
+     * @param i the index of the column
+     * @param value the value
+     * @return true if successful
+     */
+    public boolean setValue(int i, Object value)
+    {
+        if (rowset == null)
+            return error(Errors.ObjectNotValid, getClass().getName());
+        if (i < 0 || i >= fields.length)
+            return error(Errors.OutOfRange, i);
+        // Strings special
+        if ((value instanceof String) && ((String)value).length()==0)
+            value = null;
+        // Has Value changed?
+        if (ObjectUtils.compareEqual(fields[i], value))
+            return success(); // no change
+        // Field has changed
+        DBColumn column = rowset.getColumn(i);
+        if (column.getDataType()==DataType.AUTOINC)
+        {   // Read Only column may be set
+            return error(DBErrors.FieldIsReadOnly, column.getName());
+        }
+        // Is Value valid
+        if (column.checkValue(value) == false)
+        { // Invalid Value for column
+            return error(column);
+        }
+        // Init original values
+        modifyValue(i, value);
+        return success();
+    }
+
+    /**
+     * Sets the value of the column in the record.
+     * The functions checks if the column and the value are valid and whether the
+     * value has changed.
+     * 
+     * @param column a DBColumn object
+     * @param value the value
+     * @return true if successful
+     */
+    public final boolean setValue(Column column, Object value)
+    {
+        if (rowset == null)
+            return error(Errors.ObjectNotValid, getClass().getName());
+        // Get Column Index
+        return setValue(rowset.getColumnIndex(column), value);
+    }
+    
+    /**
+     * returns whether a field is read only or not
+     */
+    public boolean isFieldReadOnly(DBColumn column)
+    {
+        if (rowset==null)
+        {   error(Errors.ObjectNotValid, getClass().getName());
+            return true;
+        }
+        // Ask RowSet
+        return (rowset.isColumnReadOnly(column));
+    }
+    
+    /**
+     * returns whether a field is read only or not
+     */
+    public final boolean isFieldReadOnly(Column column)
+    {
+        return isFieldReadOnly((DBColumn)column);
+    }
+    
+    /**
+     * returns whether a field is visible to the client or not
+     * <P>
+     * May be overridden to implement context specific logic.
+     * @param column the column which to check for visibility
+     * @return true if the column is visible or false if not 
+     */
+    public boolean isFieldVisible(DBColumn column)
+    {
+        if (rowset==null)
+            return error(Errors.ObjectNotValid, getClass().getName());
+        // Check if field is present and the value is valid 
+        int index = rowset.getColumnIndex(column);
+        return (index>=0 && isValueValid(index));
+    }
+    
+    /**
+     * returns whether a field is read only or not
+     */
+    public final boolean isFieldVisible(Column column)
+    {
+        return isFieldVisible((DBColumn)column);
+    }
+
+    /**
+     * Initializes this record object by attaching it to a rowset,
+     * setting its primary key values and setting the record state.<BR>
+     * This function is useful for updating a record without prior reading.
+     * <P>
+     * @param table the rowset
+     * @param keyValues a Object array, the primary key(s)
+     * @param insert if true change the state of this object to REC_NEW
+     * @return true if successful or false otherwise
+     */
+    public boolean init(DBRowSet table, Object[] keyValues, boolean insert)
+    { // Init with keys
+        if (table.initRecord(this, keyValues) == false)
+            return error(table);
+        if (insert)
+            state = DBRecord.REC_NEW;
+        return success();
+    }
+
+    /**
+     * @deprecated use {@link DBRecord#create(DBRowSet, Connection)}
+     */
+    @Deprecated
+	public final boolean initNew(DBRowSet table, Connection conn)
+    {
+        return (table.createRecord(this, conn) == false) ? error(table) : success();
+    }
+
+    /**
+     * @deprecated use {@link DBRecord#create(DBRowSet)}
+     */
+    @Deprecated
+	public final boolean initNew(DBRowSet table)
+    {
+        return initNew(table, null);
+    }
+    
+    /**
+     * Creates a new record for the given table.<BR>
+     * All record fields will be filled with their default values.
+     * The record's state is set to NEW
+     * <P>
+     * If a connection is supplied sequence generated values will be obtained<BR>
+     * Otherwise the sequence will be generated later. 
+     * <P>
+     * @param table the table for which to create a record
+     * @param conn a valid JDBC connection
+     * @return true if successful
+     */
+    public boolean create(DBRowSet table, Connection conn)
+    {
+        return (table.createRecord(this, conn) == false) ? error(table) : success();
+    }
+    
+    /**
+     * Creates a new record for the given table.<BR>
+     * All record fields will be filled with their default values.<BR>
+     * The record's state is set to NEW
+     * <P>
+     * @param table the table for which to create a record
+     * @return true if successful
+     */
+    public boolean create(DBRowSet table)
+    {
+        return create(table, null);
+    }
+
+    /**
+     * Loads a record from the database identified by it's primary key. 
+     * After sucessful reading the record will be valid and all values will be accessible.
+     * @see org.apache.empire.db.DBTable#readRecord(DBRecord, Object[], Connection)
+     * 
+     * @param table the rowset from which to read the record
+     * @param keys an array of the primary key values
+     * @param conn a valid connection to the database.
+     * @return true if the record was sucessfully loaded or false if the record was not found or an error occurred.
+     */
+    public boolean read(DBRowSet table, Object[] keys, Connection conn)
+    {
+        return (table.readRecord(this, keys, conn) == false) ? error(table) : success();
+    }
+
+    /**
+     * Loads a record from the database identified by it's primary key. 
+     * After sucessful reading the record will be valid and all values will be accessible.
+     * @see org.apache.empire.db.DBTable#readRecord(DBRecord, Object[], Connection)
+     * 
+     * @param table the rowset from which to read the record
+     * @param id the primary key of the record to load.
+     * @param conn a valid connection to the database.
+     * @return true if the record was sucessfully loaded or false if the record was not found or an error occurred.
+     */
+    public final boolean read(DBRowSet table, Object id, Connection conn)
+    {
+        if (id instanceof Collection)
+        {   // If it's a collectin then convert it to an array
+            return read(table, ((Collection)id).toArray(), conn);
+        }
+        // Simple One-Column key
+        return read(table, new Object[] { id }, conn);
+    }
+
+    /**
+     * Updates the record and saves all changes in the database.
+     * 
+     * @see org.apache.empire.db.DBTable#updateRecord(DBRecord, Connection)
+     * @param conn a valid connection to the database.
+     * @return true if successful
+     */
+    public boolean update(Connection conn)
+    {
+        if (rowset == null)
+            return error(Errors.ObjectNotValid, getClass().getName());
+        if (!rowset.updateRecord(this, conn))
+            return error(rowset);
+        return success();
+    }
+
+    /**
+     * This helper function calls the DBRowset.deleteRecord method 
+     * to delete the record.
+     * 
+     * WARING: There is no guarantee that it ist called
+     * Implement delete logic in the table's deleteRecord method if possible
+     * 
+     * @see org.apache.empire.db.DBTable#deleteRecord(Object[], Connection)
+     * @param conn a valid connection to the database.
+     * @return true if successful
+     */
+    public boolean delete(Connection conn)
+    {
+        if (isValid()==false)
+            return error(Errors.ObjectNotValid, getClass().getName());
+        // Delete only if record is not new
+        if (!isNew())
+        {
+            Object[] keys = rowset.getRecordKey(this);
+            if (rowset.deleteRecord(keys, conn)==false)
+                return error(rowset);
+        }
+        close();
+        return success();
+    }
+
+    /**
+     * This function set the field descriptions to the the XML tag.
+     * 
+     * @return true if successful
+     */
+    @Override
+    public boolean addColumnDesc(Element parent)
+    {
+        if (rowset == null)
+            return error(Errors.ObjectNotValid, getClass().getName());
+        // Add Field Description
+        List<DBColumn> columns = rowset.getColumns();
+        for (int i = 0; i < columns.size(); i++)
+        { // Add Field
+            DBColumn column = columns.get(i);
+            if (isFieldVisible(column)==false)
+                continue;
+            column.addXml(parent, 0);
+        }
+        return success();
+    }
+
+    /**
+     * Add the values of this record to the specified XML Element object.
+     * 
+     * @param parent the XML Element object
+     * @return true if successful
+     */
+    @Override
+    public boolean addRowValues(Element parent)
+    {
+        if (rowset == null)
+            return error(Errors.ObjectNotValid, getClass().getName());
+        // set row key
+        DBColumn[] keyColumns = rowset.getKeyColumns();
+        if (keyColumns != null && keyColumns.length > 0)
+        { // key exits
+            if (keyColumns.length > 1)
+            { // multi-Column-id
+                StringBuilder buf = new StringBuilder();
+                for (int i = 0; i < keyColumns.length; i++)
+                { // add
+                    if (i > 0)
+                        buf.append("/");
+                    buf.append(getString(keyColumns[i]));
+                }
+                parent.setAttribute("id", buf.toString());
+            } 
+            else
+                parent.setAttribute("id", getString(keyColumns[0]));
+        }
+        // row attributes
+        if (isNew())
+            parent.setAttribute("new", "1");
+        // Add all children
+        List<DBColumn> columns = rowset.getColumns();
+        for (int i = 0; i < fields.length; i++)
+        { // Read all
+            DBColumn column = columns.get(i);
+            if (isFieldVisible(column)==false)
+                continue;
+            // Add Field Value
+            String name = column.getName();
+            if (fields[i] != null)
+                XMLUtil.addElement(parent, name, getString(i));
+            else
+                XMLUtil.addElement(parent, name).setAttribute("null", "yes"); // Null-Value
+        }
+        return success();
+    }
+    
+    /**
+     * returns the DBXmlDictionary that should used to generate XMLDocuments<BR>
+     * @return the DBXmlDictionary
+     */
+    protected DBXmlDictionary getXmlDictionary()
+    {
+        return DBXmlDictionary.getInstance();
+    }
+
+    /**
+     * Returns a XML document with the field descriptiona an values of this record.
+     * 
+     * @return the new XML Document object
+     */
+    @Override
+    public Document getXmlDocument()
+    {
+        if (rowset == null)
+        {   error(Errors.ObjectNotValid, getClass().getName());
+            return null;
+        }
+        // Create Document
+        DBXmlDictionary xmlDic = getXmlDictionary();
+        Element root = XMLUtil.createDocument(xmlDic.getRowSetElementName());
+        if (rowset.getName() != null)
+            root.setAttribute("name", rowset.getName());
+        // Add Field Description
+        if (!addColumnDesc(root))
+            return null;
+        // Add row Values
+        if (!addRowValues(XMLUtil.addElement(root, xmlDic.getRowElementName())))
+            return null;
+        // return Document
+        clearError();
+        return root.getOwnerDocument();
+    }
+
+    /**
+     * Initialisieren the field with the values (NO_VALUE) of the vector 'field'.
+     */
+    public int fillMissingDefaults(Connection conn)
+    {
+        int count = 0;
+        for (int i = 0; i < fields.length; i++)
+        {
+            if (fields[i] == ObjectUtils.NO_VALUE)
+            {
+                DBTableColumn col = (DBTableColumn) rowset.getColumn(i);
+                Object value = col.getRecordDefaultValue(conn);
+                if (value==null)
+                    continue;
+                // Modify value
+                modifyValue(i, value);
+                count++;
+            }
+        }
+        return count;
+    }
+    
+
+    /**
+     * set a record value from a particular bean property.
+     * <P>
+     * For a property called FOO this is equivalent of calling<BR>
+     *     setValue(column, bean.getFOO())
+     * <P>
+     * @param bean the Java Bean from which to read the value from
+     * @param property the name of the property
+     * @param column the column for which to set the record value
+     * @return true if the value has been sucessfully set or false if not    
+     */
+    protected boolean setBeanValue(Object bean, String property, Column column)
+    {
+        try
+        {   /*
+            if (log.isTraceEnabled())
+                log.trace(bean.getClass().getName() + ": getting property '" + property + "' for column " + column.getName());
+            */
+            
+            // Get Property Value
+            PropertyUtilsBean pub = BeanUtilsBean.getInstance().getPropertyUtils();
+            Object value = pub.getSimpleProperty(bean, property);
+
+            // Now, set the record value
+            return setValue( column, value ); 
+
+        } catch (IllegalAccessException e)
+        {   log.error(bean.getClass().getName() + ": unable to get property '" + property + "'");
+            return error(e);
+        } catch (InvocationTargetException e)
+        {   log.error(bean.getClass().getName() + ": unable to get property '" + property + "'");
+            return error(e);
+        } catch (NoSuchMethodException e)
+        { 
+            log.warn(bean.getClass().getName() + ": no getter available for property '" + property + "'");
+            return error(e);
+        }
+    }
+    
+    /**
+     * Sets record values from the suppied java bean.
+     * 
+     * @return true if at least one value has been set sucessfully 
+     */
+    public boolean setBeanValues(Object bean, Collection<Column> ignoreList)
+    {
+        // Add all Columns
+        int count = 0;
+        for (int i = 0; i < getFieldCount(); i++)
+        { // Check Property
+            DBColumn column = getDBColumn(i);
+            if (column.isReadOnly())
+                continue;
+            if (ignoreList != null && ignoreList.contains(column))
+                continue; // ignore this property
+            // Get Property Name
+            String property = column.getBeanPropertyName();
+            if (setBeanValue(bean, property, column))
+                count++;
+        }
+        return (count > 0);
+    }
+
+    /**
+     * Sets record values from the suppied java bean.
+     * @return true if at least one value has been set sucessfully
+     */
+    public final boolean setBeanValues(Object bean)
+    {
+        return setBeanValues(bean, null);
+    }
+    
+    /**
+     * Override this to do extra handling when the rowset for this record changes
+     */
+    protected void onRowSetChanged()
+    {
+        if (log.isTraceEnabled() && rowset!=null)
+            log.trace("Record has been attached to rowset " + rowset.getName());
+    }
+    
+    /**
+     * Override this to do extra handling when the record changes
+     */
+    protected void onRecordChanged()
+    {
+        if (log.isTraceEnabled() && isValid())
+            log.trace("Record has been changed");
+    }
+    
+    /**
+     * Override this to get notified when a field value changes
+     */
+    protected void onFieldChanged(int i)
+    {
+        if (log.isDebugEnabled())
+            log.debug("Record field " + rowset.getColumn(i).getName() + " changed to " + String.valueOf(fields[i]));
+    }
+    
+}

Added: incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBRecordData.java
URL: http://svn.apache.org/viewvc/incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBRecordData.java?rev=683173&view=auto
==============================================================================
--- incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBRecordData.java (added)
+++ incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBRecordData.java Wed Aug  6 01:47:37 2008
@@ -0,0 +1,316 @@
+/*
+ * ESTEAM Software GmbH
+ */
+package org.apache.empire.db;
+// XML
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collection;
+import java.util.Date;
+
+import org.apache.commons.beanutils.BeanUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.empire.commons.DateUtils;
+import org.apache.empire.commons.ObjectUtils;
+import org.apache.empire.commons.StringUtils;
+import org.apache.empire.data.ColumnExpr;
+import org.apache.empire.data.RecordData;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+
+/**
+ * This interface defines for the classes DDRecordSet and DBRecord.
+ * <P>
+ * 
+ * @author ESTEAM software <A TARGET="esteam" HREF="http://www.esteam.de">www.esteam.de</A>
+ */
+public abstract class DBRecordData extends DBObject
+	implements RecordData
+{
+    // Logger
+    protected static Log log = LogFactory.getLog(DBRecordData.class);
+    
+    // Field Info
+    public abstract int     getFieldCount();
+    public abstract int  	getFieldIndex(ColumnExpr column);
+    public abstract int  	getFieldIndex(String column);
+    // Column lookup
+    public abstract ColumnExpr getColumnExpr(int i);
+    // xml
+    public abstract boolean  addColumnDesc(Element parent);
+    public abstract boolean  addRowValues (Element parent);
+    public abstract Document getXmlDocument();
+    // others
+    public abstract void    close();
+
+    /**
+     * Returns a value based on an index.
+     */
+    public abstract Object  getValue(int index);
+    
+    /**
+     * Returns a data value for the desired column .
+     * 
+     * @param column the column for which to obtain the value
+     * @return the record value
+     */
+    public final Object getValue(ColumnExpr column)
+    {
+        return getValue(getFieldIndex(column));
+    }
+
+    /**
+     * 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 int getInt(int index)
+    {
+        // Get Integer value
+        Object o = getValue(index);
+        return ObjectUtils.getInteger(o);
+    }
+    
+    /**
+     * Returns a data value for the desired column.
+     * The data value is converted to integer if necessary.
+     * 
+     * @param column identifing the column
+     * @return the value
+     */
+    public final int getInt(ColumnExpr column)
+    {
+        return getInt(getFieldIndex(column));
+    }
+
+    /**
+     * 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 long getLong(int index)
+    {
+        // Get Integer value
+        Object o = getValue(index);
+        return ObjectUtils.getLong(o);
+    }
+    
+    /**
+     * Returns a data value for the desired column.
+     * The data value is converted to a long if necessary.
+     * 
+     * @param column identifing the column
+     * @return the value
+     */
+    public final long getLong(ColumnExpr column)
+    {
+        return getLong(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 double getDouble(int index)
+    {
+        // Get Double value
+        Object o = getValue(index);
+        return ObjectUtils.getDouble(o);
+    }
+
+    /**
+     * Returns a data value for the desired column.
+     * The data value is converted to double if necessary.
+     * 
+     * @param column identifing 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 boolean if necessary.
+     * 
+     * @param index index of the column
+     * @return the value
+     */
+    public boolean getBoolean(int index)
+    {
+        // Get Boolean value
+        Object o = getValue(index);
+        return ObjectUtils.getBoolean(o);
+    }
+    
+    /**
+     * Returns a data value for the desired column.
+     * The data value is converted to boolean if necessary.
+     * 
+     * @param column identifing the column
+     * @return the value
+     */
+    public final boolean getBoolean(ColumnExpr column)
+    { return getBoolean(getFieldIndex(column)); }
+    
+    /**
+     * 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 String getString(int index)
+    {
+        // Get Integer value
+        Object o = getValue(index);
+        return StringUtils.toString(o);
+    }
+
+    /**
+     * Returns a data value for the desired column.
+     * The data value is converted to a string if necessary.
+     * 
+     * @param column identifing the column
+     * @return the value
+     */
+    public final String getString(ColumnExpr column)
+    {
+        return getString(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 Date getDateTime(int index)
+    {
+        // Get DateTime value
+        Object o = getValue(index);
+        return ObjectUtils.getDate(o);
+    }
+    
+    /**
+     * Returns a data value for the desired column.
+     * The data value is converted to a Date if necessary.
+     * 
+     * @param column identifing the column
+     * @return the value
+     */
+    public final Date getDateTime(ColumnExpr column)
+    {
+        return getDateTime(getFieldIndex(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
+     */
+    public boolean isNull(int index)
+    {
+        return (getValue(index) == null);
+    }
+
+    /**
+     * Checks whether or not the value for the given column is null.
+     * 
+     * @param column identifing the column
+     * @return true if the value is null or false otherwise
+     */
+    public final boolean isNull(ColumnExpr column)
+    {
+        return isNull(getFieldIndex(column));
+    }
+
+    /**
+     * Set a single property value of a java bean object used by readProperties.
+     */
+    protected boolean getBeanProperty(Object bean, String property, Object value)
+    {
+        try
+        {   /*
+            if (log.isTraceEnabled())
+                log.trace(bean.getClass().getName() + ": setting property '" + property + "' to " + String.valueOf(value));
+            */    
+            if (value instanceof Date)
+            {   // Patch for Strage Date Bug in BeanUtils
+                value = DateUtils.addDate((Date)value, 0, 0, 0);
+            }
+            // Set Property Value
+            // Should check whether property exists
+            BeanUtils.setProperty(bean, property, value);
+            // Check result
+            /*
+             * String res = BeanUtils.getProperty(bean, property); if (res!=value && res.equals(String.valueOf(value))==false) { //
+             * Property value cannot be set // (missing setter?) String msg = bean.getClass().getName() + ": unable to set
+             * property '" + property + "' to " + String.valueOf(value); return error(ERR_INTERNAL, msg); } else if
+             * (log.isInfoEnabled()) { log.info(bean.getClass().getName() + ": property '" + property + "' has been set to " +
+             * res); }
+             */
+            // done
+            return success();
+
+        } catch (IllegalAccessException e)
+        {
+            log.error(bean.getClass().getName() + ": unable to set property '" + property + "'");
+            return error(e);
+        } catch (InvocationTargetException e)
+        {
+            log.error(bean.getClass().getName() + ": unable to set property '" + property + "'");
+            return error(e);
+            /*
+             * } catch(NoSuchMethodException e) { log.warn(bean.getClass().getName() + ": cannot check value of property '" +
+             * property + "'"); return true;
+             */
+        }
+    }
+
+    /**
+     * Injects the current field values into a java bean.
+     * 
+     * @return true if successful
+     */
+    public boolean getBeanProperties(Object bean, Collection<ColumnExpr> ignoreList)
+    {
+        // Add all Columns
+        for (int i = 0; i < getFieldCount(); i++)
+        { // Check Property
+            ColumnExpr column = getColumnExpr(i);
+            if (ignoreList != null && ignoreList.contains(column))
+                continue; // ignore this property
+            // Get Property Name
+            String property = column.getBeanPropertyName();
+            if (getBeanProperty(bean, property, this.getValue(i))==false)
+            {   // Error setting property.
+                return false;
+            }
+        }
+        // Success, All Properties have been set
+        return success();
+    }
+
+    /**
+     * Injects the current field values into a java bean.
+     * 
+     * @return true if successful
+     */
+    public final boolean getBeanProperties(Object bean)
+    {
+        return getBeanProperties(bean, null);
+    }
+    
+}

Added: incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBRelation.java
URL: http://svn.apache.org/viewvc/incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBRelation.java?rev=683173&view=auto
==============================================================================
--- incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBRelation.java (added)
+++ incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBRelation.java Wed Aug  6 01:47:37 2008
@@ -0,0 +1,87 @@
+/*
+ * ESTEAM Software GmbH, 15.12.2004
+ */
+package org.apache.empire.db;
+
+/**
+ * This class creates a DBReferene object for a foreing key relation.
+ * 
+ * @author ESTEAM software <A TARGET="esteam" HREF="http://www.esteam.de">www.esteam.de </A>
+ */
+public class DBRelation extends DBObject
+{
+	public static class DBReference
+	{
+	    private DBTableColumn sourceColumn;
+        private DBTableColumn targetColumn;
+	    
+	    public DBReference(DBTableColumn sourceColumn, DBTableColumn targetColumn)
+	    {
+	       this.sourceColumn = sourceColumn;
+	       this.targetColumn = targetColumn;
+	    }
+
+        public DBTableColumn getSourceColumn()
+        {
+            return sourceColumn;
+        }
+
+        public DBTableColumn getTargetColumn()
+        {
+            return targetColumn;
+        }
+	}
+
+	// Members
+    private DBDatabase    db;
+    private String        name;
+    private DBReference[] references;
+
+    /**
+     * Creates a DBReferene object for a foreing key relation.
+     */
+	public DBRelation(DBDatabase db, String name, DBReference[] references)
+	{
+	   this.db         = db;
+	   this.name       = name;
+	   this.references = references;
+	}
+	
+    /**
+     * Returns the name.
+     * 
+     * @return Returns the name
+     */
+    public String getName()
+    {
+        return name;
+    }
+
+    /**
+     * Returns the full qualified table name.
+     * 
+     * @return the full qualified table name
+     */
+    public String getFullName()
+    {
+        String  schema = db.getSchema();
+        return (schema!=null) ? schema+"."+name : name;
+    }
+    
+    /**
+     * Returns the references.
+     * 
+     * @return the references
+     */
+    public DBReference[] getReferences()
+    {
+        return references;
+    }
+
+    @Override
+    public DBDatabase getDatabase()
+    {
+        return db;
+    }
+
+}
\ No newline at end of file

Added: incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBRowSet.java
URL: http://svn.apache.org/viewvc/incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBRowSet.java?rev=683173&view=auto
==============================================================================
--- incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBRowSet.java (added)
+++ incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBRowSet.java Wed Aug  6 01:47:37 2008
@@ -0,0 +1,770 @@
+/*
+ * ESTEAM Software GmbH
+ */
+package org.apache.empire.db;
+
+import java.sql.Connection;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.empire.commons.Errors;
+import org.apache.empire.commons.ObjectUtils;
+import org.apache.empire.commons.StringUtils;
+import org.apache.empire.data.Column;
+import org.apache.empire.data.DataType;
+import org.apache.empire.db.DBRelation.DBReference;
+import org.apache.empire.db.expr.column.DBCountExpr;
+
+
+/**
+ * This class is the base class for all the DBTable,
+ * CBView and DBQuery classes this class contains all the columns of the
+ * tables, views or querys
+ * <P>
+ * 
+ * @author ESTEAM software <A TARGET="esteam" HREF="http://www.esteam.de">www.esteam.de </A>
+ */
+public abstract class DBRowSet extends DBExpr
+{
+    // Logger
+    @SuppressWarnings("hiding")
+    protected static Log log = LogFactory.getLog(DBRowSet.class);
+    // Members
+    protected final DBDatabase db;
+    protected String        comment           = null;
+    protected DBIndex       primaryKey        = null;
+    protected DBColumn      timestampColumn   = null; // Use SetUpdateTimestamp!
+    protected Map<DBColumn, DBColumn> columnReferences = null;
+    // The column List
+    protected List<DBColumn> columns          = new ArrayList<DBColumn>();
+
+    /**
+     * Constructs a DBRecord object set the current database object.
+     */
+    public DBRowSet(DBDatabase db)
+    {
+        this.db = db;
+    }
+
+    // ------- Abstract Methods -------
+    
+    public abstract String getName();
+    
+    public abstract String getAlias();
+
+    public abstract boolean createRecord(DBRecord rec, Connection conn);
+
+    public abstract boolean deleteRecord(Object[] keys, Connection conn);
+    
+    /**
+     * Returns the full qualified name of the rowset.
+     * <P>
+     * @return the full qualified name
+     */
+    public String getFullName()
+    {
+        String  name   = getName();
+        String  schema = db.getSchema();
+        return (schema!=null) ? schema+"."+name : name;
+    }
+
+    /**
+     * @see org.apache.empire.db.DBExpr#addReferencedColumns(Set)
+     */
+    @Override
+    public void addReferencedColumns(Set<DBColumn> list)
+    {
+        list.addAll(columns);
+    }
+
+    /**
+     * Returns the current DBDatabase object.
+     * <P>
+     * @return the current DBDatabase object
+     */
+    @Override
+    public final DBDatabase getDatabase()
+    {
+        return db;
+    }
+
+    /**
+     * Gets all columns of this rowset (e.g. for cmd.select()).
+     * <P>
+     * @return all columns of this rowset
+     */
+    public List<DBColumn> getColumns()
+    {
+        return columns;
+    }
+
+    /**
+     * Gets the index of a particular column expression.
+     * <P>
+     * @return the position of a column expression
+     */
+    public int getColumnIndex(DBColumn column)
+    {
+        return columns.indexOf(column);
+    }
+    
+    /**
+     * Gets the index of a particular column expression.
+     * <P>
+     * @return the position of a column expression
+     */
+    public final int getColumnIndex(Column column)
+    {
+        return getColumnIndex((DBColumn)column);
+    }
+
+    /**
+     * Returns a DBColumn object by a specified index value.
+     * 
+     * @return the index value
+     */
+    public DBColumn getColumn(int iColumn)
+    {
+        if (iColumn < 0 || iColumn >= columns.size())
+            return null;
+        return columns.get(iColumn);
+    }
+
+    /**
+     * Gets the column Expression with a particular name.
+     * 
+     * @return the column Expression at position
+     */
+    public DBColumn getColumn(String name)
+    {
+        for (int i = 0; i < columns.size(); i++)
+        {
+            DBColumn col = columns.get(i);
+            if (col.getName().equalsIgnoreCase(name))
+                return col;
+        }
+        return null;
+    }
+
+    /**
+     * Checks whether a column is read only or writable.
+     * Only the timestamp column is read only by default.
+     * The primary is read only if the column is of type.
+     * 
+     * @return a new DBCountExpr object
+     */
+    public boolean isColumnReadOnly(DBColumn col)
+    {
+        if (getColumnIndex(col)<0)
+            return true; // not found!
+        if (col==timestampColumn)
+            return true; // timestamp column
+        // Check Update Column
+        return (col.isReadOnly());
+    }
+
+    /**
+     * Returns an array of all primary key columns.
+     * 
+     * @return an array of all primary key columns
+     */
+    public DBColumn[] getKeyColumns()
+    {
+        return ((primaryKey != null) ? primaryKey.getColumns() : null);
+    }
+    
+    /**
+     * Checks whether a given column is part of the primary key for this RowSet 
+     * @param column the column to check
+     * @return true if the column is part of the primary key or false otherwise
+     */
+    public boolean isKeyColumn(DBColumn column)
+    {
+        DBColumn[] keyColumns = getKeyColumns();
+        for (int i=0; i<keyColumns.length; i++)
+        {
+            if (keyColumns[i]==column)
+                return true;
+        }
+        return false;
+    }
+
+    /**
+     * @return Returns the comment.
+     */
+    public String getComment()
+    {
+        return comment;
+    }
+
+    /**
+     * @param comment The comment to set.
+     */
+    public void setComment(String comment)
+    {
+        this.comment = comment;
+    }
+    /**
+     * @return Returns the timestampColumn.
+     */
+    public DBColumn getTimestampColumn()
+    {
+        return timestampColumn;
+    }
+    /**
+     * @param timestampColumn The timestampColumn to set.
+     */
+    public void setTimestampColumn(DBColumn timestampColumn)
+    {
+        this.timestampColumn = timestampColumn;
+    }
+    
+    /**
+     * Returns the a list of column references.
+     * 
+     * @return a list of references
+     */
+    public Map<DBColumn, DBColumn> getColumnReferences()
+    {
+        return columnReferences; 
+    }
+    
+    /**
+     * Adds a column reference to the ist of table references.
+     * This method ist internally called from DBDatabase.addReleation().
+     * 
+     * @param source a column reference for one of this table's column
+     * @param target the target column to which the source column references
+     */
+    protected boolean addColumnReference(DBColumn source, DBColumn target)
+    {
+        if (source.getRowSet()!=this)
+            return error(Errors.InvalidArg, source.getFullName(), "column");
+        if (columnReferences== null)
+            columnReferences = new HashMap<DBColumn, DBColumn>();
+        // Check if column is already there
+        columnReferences.put(source, target);
+        return success();
+    }
+    
+    /**
+     * Returns a new DBCountExpr object.
+     * 
+     * @return a new DBCountExpr object
+     */
+    public DBColumnExpr count()
+    {
+        return new DBCountExpr(this, null);
+    }
+    
+    /**
+     * Returns the sql phrase for renaming tables.
+     * usually just a space character ' '
+     * 
+     * @return the table rename phrase
+     */
+    protected String getRenameTablePhrase()
+    {
+        if (db==null || db.driver==null)
+            return " ";
+        return db.driver.getSQLPhrase(DBDatabaseDriver.SQL_RENAME_TABLE);
+    }
+
+    /**
+     * Returns a array of primary key columns by a specified DBRecord object.
+     * 
+     * @param rec the DBRecord object, contains all fields and the field properties
+     * @return a array of primary key columns
+     */
+    public Object[] getRecordKey(DBRecord rec)
+    {
+        if (rec.getRowSet() != this)
+            return null; // Invalid Argument
+        if (primaryKey == null)
+            return null; // No primary key
+        // Check Columns
+        DBColumn[] keyColumns = primaryKey.getColumns();
+        Object[] keys = new Object[keyColumns.length];
+        for (int i = 0; i < keyColumns.length; i++)
+        {
+            keys[i] = rec.getValue(keyColumns[i]);
+            if (keys[i] == null)
+            { // Primary Key not set
+                log.warn("getRecordKey: " + getName() + " primary key value is null!");
+            }
+        }
+        return keys;
+    }
+
+    /**
+     * Initialise this DBRowSet object and sets it's initial state.
+     * 
+     * @param rec the DBRecord object to initialise this DBRowSet object
+     * @param state the state of this DBRowSet object
+     * @return true if successful
+     */
+    protected boolean prepareInitRecord(DBRecord rec, int state, Object rowSetData)
+    {
+        if (columns.size() < 1)
+            return error(Errors.ObjectNotValid, getClass().getName());
+        // Init
+        rec.init(this, state, rowSetData);
+        return success();
+    }
+
+    /**
+     * Initializes a DBRecord for this RowSet and sets primary key values (the Object[] keyValues).
+     * The record may then be modified and updated.<BR>
+     * <P>
+     * @param rec the Record object
+     * @param keyValues an array of the primary key columns
+     * @return true if successful
+     */
+    public boolean initRecord(DBRecord rec, Object[] keyValues)
+    {
+        // Inititialisierung
+        if (!prepareInitRecord(rec, DBRecord.REC_EMTPY, null))
+            return false;
+        // Initialize all Fields
+        Object[] fields = rec.getFields();
+        for (int i = 0; i < fields.length; i++)
+            fields[i] = ObjectUtils.NO_VALUE;
+        // Init Key Values
+        if (keyValues != null && primaryKey != null)
+        {
+            // Check Columns
+            DBColumn[] keyColumns = primaryKey.getColumns();
+            for (int i = 0; i < keyColumns.length; i++)
+            { // Ignore Validity Checks
+                int field = getColumnIndex(keyColumns[i]);
+                fields[field] = keyValues[i];
+            }
+        }
+        // Init
+        return completeInitRecord(rec);
+    }
+
+    /**
+     * Initializes a DBRecord for this rowset using the record data provided (i.e. from a DBReader)<BR>
+     * The record may then be modified and updated.<BR>
+     * At least all primary key columns must be supplied.<BR>
+     * We strongly recommend to supply the value of the update timestamp column in order to detect concurrent changes.<BR>
+     * Fields for which no value is supplied with the recData paramter are set to NO_VALUE<BR>
+     * <P>
+     * @param rec the record object
+     * @param recData the record data from which to initialized the record
+     * @return true if successful
+     */
+    public boolean initRecord(DBRecord rec, DBRecordData recData)
+    {
+        // Initialize the record
+        prepareInitRecord(rec, DBRecord.REC_VALID, null);
+        // Get Record Field Values
+        Object[] fields = rec.getFields();
+        for (int i = 0; i < fields.length; i++)
+        {
+            try
+            {   // Read a value
+            	DBColumn column = columns.get(i);
+            	int rdi = recData.getFieldIndex(column);
+            	if (rdi<0)
+            	{	// Field not available in Record Data
+            		if (primaryKey!=null && primaryKey.contains(column))
+            		{	// Error: Primary Key not supplied
+            			return error(DBErrors.RecordInvalidKey, column.toString());
+            		}
+                    if (timestampColumn == column)
+                    { // Check the update Time Stamp
+                    	if (log.isInfoEnabled())
+                    		log.info(getName() + "No record timestamp value has been provided. Hence concurrent changes will not be detected.");
+                    } 
+            		// Set to NO_VALUE
+                    fields[i] = ObjectUtils.NO_VALUE;
+            	}
+            	else
+            	{
+                    fields[i] = recData.getValue(rdi);
+            	}
+                
+            } catch (Exception e)
+            {
+                log.error("initRecord exception: " + e.toString());
+                rec.close();
+                return error(e);
+            }
+        }
+        // Done
+        return completeInitRecord(rec);
+    }
+    
+    /**
+     * Reads a single record from the database using the given command object.<BR>
+     * If a reocord is found the DBRecord object will hold all record data. 
+     * <P>
+     * @param rec the DBRecord object which holds the record data
+     * @param cmd the SQL-Command used to query the record
+     * @param conn a valid JDBC connection.
+     * @return true if successful
+     */
+    protected boolean readRecord(DBRecord rec, DBCommand cmd, Connection conn)
+    {
+        DBReader reader = null;
+        try
+        {
+            clearError();
+            reader = new DBReader();
+            if (reader.getRecordData(cmd, conn)==false)
+                return error(reader);
+            if (initRecord(rec, reader)==false)
+            	return false;
+            // Done
+            return success();
+            
+        } finally
+        {
+        	reader.close();
+        }
+    }
+    
+    /**
+     * Completes the record initialisation.<BR>
+     * Override this function to do post initialisation processing.
+     * <P>
+     * @param rec the DBRecord object to initialise
+     * @return true if successful
+     */
+    protected boolean completeInitRecord(DBRecord rec)
+    {
+    	rec.onRecordChanged();
+        return success();
+    }
+    
+    /**
+     * Reads the record with the given primary key from the database.
+     * <P>
+     * @param rec the DBRecord object which will hold the record data
+     * @param key the primary key values
+     * @param conn a valid JDBC connection.
+     * @return true if successful
+     */
+    public boolean readRecord(DBRecord rec, Object[] key, Connection conn)
+    {
+        // Check Arguments
+        if (conn == null || rec == null)
+            return error(Errors.InvalidArg, null, "conn|rec");
+        // Check Primary key
+        if (primaryKey == null ) 
+            return error(DBErrors.NoPrimaryKey, getName()); // Invalid Argument
+        // Check Columns
+        DBColumn[] keyColumns = primaryKey.getColumns();
+        if (key == null || key.length != keyColumns.length)
+            return error(DBErrors.RecordInvalidKey, key); // Invalid Argument
+        // Select
+        DBCommand cmd = db.createCommand();
+        cmd.select(columns);
+        for (int i = 0; i < key.length; i++)
+            cmd.where(keyColumns[i].is(key[i]));
+        // Read Record
+        if (!readRecord(rec, cmd, conn))
+        {   // Record not found
+            if (getErrorType()==DBErrors.QueryNoResult)
+                return error(DBErrors.RecordNotFound, key);
+            // Return given error
+            return false;
+        }
+        // Done
+        return success();
+    }
+
+    /**
+     * Returns true if the record exists in the database or false otherwise.
+     * <P>
+     * @param key an array of the primary key columns
+     * @param conn a valid JDBC connection.
+     * @return true if successful or false otherwise
+     */
+    public boolean recordExists(Object[] key, Connection conn)
+    {
+        // Check Arguments
+        if (conn == null)
+            return error(Errors.InvalidArg, conn, "conn");
+        // Check Primary key
+        if (primaryKey == null ) 
+            return error(DBErrors.NoPrimaryKey, getName()); // Invalid Argument
+        // Check Columns
+        DBColumn[] keyColumns = primaryKey.getColumns();
+        if (key == null || key.length != keyColumns.length)
+            return error(DBErrors.RecordInvalidKey, key); // Invalid Argument
+        // Select
+        DBCommand cmd = db.createCommand();
+        cmd.select(count());
+        for (int i = 0; i < key.length; i++)
+            cmd.where(keyColumns[i].is(key[i]));
+        // check exits
+        return (db.querySingleInt(cmd.getSelect(), conn)==1);
+    }
+
+    /**
+     * Returns true if the record exists in the database or false otherwise.
+     * <P>
+     * @param id id of the record
+     * @param conn a valid JDBC connection.
+     * @return true if successful or false otherwise
+     */
+    public final boolean recordExists(Object id, Connection conn)
+    {
+        return recordExists(new Object[] { id }, conn); 
+    }
+    
+    /**
+     * Updates or Inserts a record in the database.<BR>
+     * Whether an update or insert is performed depends on the record state.<BR>
+     * Only modified fields will be inserted or updated in the database.<BR>
+     * <P>
+     * If a timestamp-column is set for this RowSet then a constraint will be added in the 
+     * update statement in order to detect concurrent changes.<BR> 
+     * If the record has been modified by another user, an error of type 
+     * DBErrors.RecordUpdateFailed will be set.  
+     * <P>
+     * @param rec the DBRecord object. contains all fields and the field properties
+     * @param conn a valid JDBC connection.
+     * @return true if the update was sucessful or false otherwise
+     */
+    public boolean updateRecord(DBRecord rec, Connection conn)
+    {
+        // Check Arguments
+        if (conn == null)
+            return error(Errors.InvalidArg, conn, "conn");
+        // Get the new Timestamp
+        String name = getName();
+        Timestamp timestamp = (timestampColumn!=null) ? db.getUpdateTimestamp(conn) : null;
+        // Get the fields and the flags
+        Object[] fields = rec.getFields();
+        // Build SQL-Statement
+        DBCommand cmd = db.createCommand();
+        String sql = null;
+        int setCount = 0;
+        int autoIncFieldIndex = -1; // for post insert auto increment processing
+        switch (rec.getState())
+        {
+            case DBRecord.REC_MODIFIED:
+                if (primaryKey == null)
+                { // Requires a primary key
+                    log.error("updateRecord: "  + name + " no primary key defined!");
+                    return error(DBErrors.NoPrimaryKey, name);
+                }
+                for (int i = 0; i < columns.size(); i++)
+                { // search for the column
+                	Object value = fields[i];
+                	boolean modified = rec.wasModified(i);
+                	boolean empty = ObjectUtils.isEmpty(value); 
+                    DBTableColumn col = (DBTableColumn) columns.get(i);
+                    if (primaryKey.contains(col))
+                    { // Check for Modification
+                        if (modified == true)
+                        { // Requires a primary key
+                            log.warn("updateRecord: " + name + " primary has been modified!");
+                        }
+                        cmd.where(col.is(value));
+                    } 
+                    else if (timestampColumn == col)
+                    { // Check the update Time Stamp
+                    	if (empty==false)
+	                        cmd.where(col.is(value));
+                    	else if (log.isDebugEnabled())
+                    		log.debug("updateRecord has no value for timestamp column. Concurrent changes will not be detected.");
+                        cmd.set(col.to(timestamp));
+                    } 
+                    else if (modified && value!=ObjectUtils.NO_VALUE)
+                    { // Update a field
+                        if (col.isReadOnly())
+                            log.warn("updateRecord: Read-only column '" + col.getName() + " has been modified!");
+                        // Check the value
+                        if (!col.checkValue(value))
+                            return error(col);
+                        // Set the column
+                        cmd.set(col.to(value));
+                        setCount++;
+                    }
+                }
+                // Get the SQL statement
+                sql = cmd.getUpdate();
+                break;
+
+            case DBRecord.REC_NEW:
+                for (int i = 0; i < columns.size(); i++)
+                { // search for the column
+                	Object value = fields[i];
+                	boolean empty = ObjectUtils.isEmpty(value); 
+                    DBTableColumn col = (DBTableColumn) columns.get(i);
+                    if (col.getDataType()==DataType.AUTOINC && empty) 
+                    { // Set Autoinc value if not already done
+                        if (db.getDriver().isSupported(DBDriverFeature.SEQUENCES)==false)
+                        {  // Post Dectect Autoinc Value
+                           autoIncFieldIndex = i;
+                           continue;
+                        }
+                        // Get Next Sequence value
+                        fields[i] = value = col.getRecordDefaultValue(conn);
+                        empty = ObjectUtils.isEmpty(value);
+                    }
+                    if (primaryKey!=null && primaryKey.contains(col) && empty)
+                    { // All primary key fields must be supplied
+                        return error(DBErrors.FieldNotNull, col.getTitle());
+                    }
+                    if (timestampColumn == col)
+                    { // Make sure the upate Timestamp Column is set
+                        cmd.set(col.to(timestamp));
+                    } 
+                    else if (empty==false)
+                    { // Check the value
+                        if (!col.checkValue(value))
+                            return error(col);
+                        // Insert a field
+                        cmd.set(col.to(value));
+                        setCount++;
+                    } 
+                    else if (col.required == true)
+                    { // Error Column is required!
+                        return error(DBErrors.FieldNotNull, col.getTitle());
+                    }
+                }
+                sql = cmd.getInsert();
+                break;
+
+            default:
+                log.warn("updateRecord: " + name + " record has not been modified! ");
+                return success();
+        }
+        if (setCount == 0)
+        { // Cannot update or insert fields
+            log.info("updateRecord: " + name + " nothing to update or insert!");
+            return success();
+        }
+        // Perform action
+        int affected = db.executeSQL(sql, cmd.getCmdParams(), conn);
+        if (affected < 0)
+        { // Update Failed
+            return error(db);
+        } 
+        else if (affected == 0)
+        { // Record not found
+            return error(DBErrors.RecordUpdateFailed, name);
+        } 
+        else if (affected > 1)
+        { // Multiple Records affected
+            return error(DBErrors.RecordUpdateInvalid, name);
+        }
+        // Post Insert Autoincrement processing
+        if (autoIncFieldIndex>=0 && fields[autoIncFieldIndex]==null)
+        {   // Driver must supply the value
+            fields[autoIncFieldIndex]=db.getDriver().getPostInsertAutoIncValue(db, conn);
+            if (fields[autoIncFieldIndex]==null)
+                return error(db.getDriver());
+        }
+        // Correct Timestamp
+        if (timestampColumn != null)
+        { // Set the correct Timestamp
+            int i = rec.getFieldIndex(timestampColumn);
+            if (i >= 0)
+                fields[i] = timestamp;
+        }
+        // Change State
+        rec.changeState(DBRecord.REC_VALID, null);
+        return success();
+    }
+    
+    /**
+     * Deletes a single record from the database.<BR>
+     * <P>
+     * @param id the record's primary key
+     * @param conn a valid JDBC connection
+     * @return true if the record has been successfully deleted or false otherwise
+     */
+    public final boolean deleteRecord(Object id, Connection conn)
+    {
+        return deleteRecord(new Object[] { id }, conn);
+    }
+
+    /**
+     * Deletes all records which reference this table.
+     * <P>
+     * @param key the key the record to be deleted
+     * @param conn a valid connection
+     * @return true if all reference records could be deleted
+     */
+    protected final boolean deleteAllReferences(Object[] key, Connection conn)
+    {
+        // Merge Sub-Records
+        List<DBRelation> relations = db.getRelations();
+        DBColumn[] keyColumns = getKeyColumns();
+        if (keyColumns==null)
+            return success(); // No primary key - no references!
+        // Find all relations
+        for (DBRelation rel : relations)
+        {   // References
+            DBReference[] refs = rel.getReferences();
+            for (int i=0; i<refs.length; i++)
+            {
+                if (refs[i].getTargetColumn().equals(keyColumns[0]))
+                {   // Found a reference on RowSet
+                    DBRowSet rs = refs[0].getSourceColumn().getRowSet(); 
+                    if (rs.deleteReferenceRecords(refs, key, conn)==false)
+                        return false;
+                }
+            }
+        }
+        // No delete this record
+        return success();
+    }
+    
+    /**
+     * Deletes all records which are referenced by a particular relation.
+     * <P>
+     * @param refs the reference columns belonging to the releation
+     * @param key the key of the parent element
+     * @param conn a valid connection
+     * @return true if all records could be deleted or false otherwise
+     */
+    protected boolean deleteReferenceRecords(DBReference[] refs, Object[] key, Connection conn)
+    {
+        // Key length and reference length must match
+        if (refs.length!=key.length)
+            return error(DBErrors.RecordInvalidKey);
+        // Rowset
+        DBColumn[] keyColumns = getKeyColumns();
+        if (keyColumns==null || keyColumns.length==0)
+        {   // No Primary Key
+            DBCommand cmd = db.createCommand();
+            for (int i=0; i<key.length; i++)
+                cmd.where(refs[i].getSourceColumn().is(key[i]));
+            if (db.executeSQL(cmd.getDelete((DBTable)this), conn)<0)
+                return error(db);
+        }
+        else
+        {   // Query all keys
+            DBCommand cmd = db.createCommand();
+            cmd.select(keyColumns);
+            for (int i=0; i<key.length; i++)
+                cmd.where(refs[i].getSourceColumn().is(key[i]));
+            // Query all keys
+            List<Object[]> recKeys = db.queryObjectList(cmd.getSelect(), conn);
+            for (Object[] recKey : recKeys)
+            {   // Delete Record
+                log.info("Deleting Record " + StringUtils.valueOf(recKey) + " from table " + getName());
+                if (deleteRecord(recKey, conn)==false)
+                    return false;
+            }
+        }
+        // Done
+        return success();
+    }
+    
+}
+

Added: incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBSQLScript.java
URL: http://svn.apache.org/viewvc/incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBSQLScript.java?rev=683173&view=auto
==============================================================================
--- incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBSQLScript.java (added)
+++ incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBSQLScript.java Wed Aug  6 01:47:37 2008
@@ -0,0 +1,134 @@
+/*
+ * ESTEAM Software GmbH, 05.04.2008
+ */
+package org.apache.empire.db;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.empire.commons.ErrorObject;
+
+
+/**
+ * DBSQLScript<br>
+ * This class is a collection of sql command strings.<br>
+ * The class is used for obtaining and executing DDL commands supplied
+ * by the database driver (@see {@link DBDatabaseDriver#getDDLScript(DBCmdType, DBObject, DBSQLScript)}) 
+ */
+public class DBSQLScript extends ErrorObject implements Iterable<String>
+{
+    // Logger
+    private static final Log log = LogFactory.getLog(DBSQLScript.class);
+    
+    private ArrayList<String> sqlCmdList = new ArrayList<String>();
+    private static final String COMMAND_SEPARATOR = ";\r\n\r\n";
+    
+    /**
+     * Adds a statement to the script.
+     * @param sql the statement
+     * @return true if successful
+     */
+    public boolean addStmt(String sql)
+    {
+        sqlCmdList.add(sql);
+        return success();
+    }
+    
+    /**
+     * Adds a statement to the script.<br>
+     * The supplied StringBuilder will be reset to a length of 0
+     * @param sql the statement
+     * @return true if successful
+     */
+    public final boolean addStmt(StringBuilder sql)
+    {
+        if (!addStmt(sql.toString()))
+            return false;
+        // Clear Builder
+        sql.setLength(0);
+        return true;
+    }
+    
+    /**
+     * Returns the number of statemetns in this script
+     * @return number of statements in this script
+     */
+    public int getCount()
+    {
+        return sqlCmdList.size();
+    }
+    
+    /**
+     * Returns the statement at the given index
+     * @param i index of the statement to retrieve
+     * @return the sql statement
+     */
+    public String getStmt(int i)
+    {
+        return sqlCmdList.get(i);
+    }
+    
+    /**
+     * Clears the script and delets all statements
+     */
+    public void clear()
+    {
+        sqlCmdList.clear();
+    }
+    
+    /**
+     * Runs all SQL Statements using the supplied driver and connection.
+     * @param driver the driver used for statement execution
+     * @param conn the connection
+     * @param ignoreErrors true if errors should be ignored
+     * @return true if the script has been run successful or false otherwise 
+     */
+    public boolean run(DBDatabaseDriver driver, Connection conn, boolean ignoreErrors)
+    {
+        log.debug("Running script containing " + String.valueOf(getCount()) + " statements.");
+        for(String stmt : sqlCmdList)
+        {
+            try {
+                // Execute Statement
+                log.debug("Executing: " + stmt);
+                driver.executeSQL(stmt, null, conn);
+            } catch(SQLException e) {
+                // SQLException
+                log.error(e.toString(), e);
+                if (ignoreErrors==false)
+                    return error(DBErrors.SQLException, e);
+                // continue
+                log.debug("Ignoring error. Continuing with script...");
+            }
+        }
+        log.debug("Script completed.");
+        return success();
+    }
+    
+    /**
+     * Returns an iterator
+     */
+    public Iterator<String> iterator()
+    {
+        return sqlCmdList.iterator();
+    }
+    
+    /**
+     * Returns the sql script as a string
+     */
+    @Override
+    public String toString()
+    {
+        StringBuilder script = new StringBuilder();
+        for(String stmt : sqlCmdList)
+        {
+            script.append(stmt);
+            script.append(COMMAND_SEPARATOR);
+        }
+        return script.toString();
+    }
+}

Added: incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBTable.java
URL: http://svn.apache.org/viewvc/incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBTable.java?rev=683173&view=auto
==============================================================================
--- incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBTable.java (added)
+++ incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBTable.java Wed Aug  6 01:47:37 2008
@@ -0,0 +1,374 @@
+/*
+ * ESTEAM Software GmbH
+ */
+package org.apache.empire.db;
+
+// java
+import java.lang.reflect.Field;
+import java.sql.Connection;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.empire.commons.Errors;
+import org.apache.empire.data.DataType;
+
+
+/**
+ * This class represent one table of the database.
+ * It consits methods to get, add, update and delete records from the database.
+ * <P>
+ * 
+ * @author ESTEAM software <A TARGET="esteam" HREF="http://www.esteam.de">www.esteam.de </A>
+ */
+public class DBTable extends DBRowSet implements Cloneable
+{
+    private static int     tableCount    = 1;
+    private final String   name;
+    private String         alias;
+    private List<DBIndex>  indexes       = new ArrayList<DBIndex>();
+    private boolean        cascadeDelete = false;
+
+    /**
+     * Construct a new DBTable object set the specified parameters
+     * to this object and add this object to the current database.
+     * 
+     * @param name the table name
+     * @param db the valid database object
+     */
+    public DBTable(String name, DBDatabase db)
+    { 
+        super(db);
+        // init
+        this.name = name;
+        this.alias = "t" + String.valueOf(tableCount);
+        tableCount++;
+        // Add Table to Database
+        if (db != null)
+            db.addTable(this);
+    }
+
+    /**
+     * Returns the table name of this object.
+     * 
+     * @return the table name of this object
+     */
+    @Override
+    public String getName()
+    {
+        return name;
+    }
+
+    /**
+     * Returns the table alias name of this object.
+     * 
+     * @return the table alias name of this object
+     */
+    @Override
+    public String getAlias()
+    {
+        return alias;
+    }
+
+    /**
+     * Clones this object.
+     * 
+     * @return this cloned Object
+     */
+    @SuppressWarnings("unchecked")
+    @Override
+    public Object clone()
+    {
+        try
+        {
+            DBTable clone = (DBTable) super.clone();
+            // clone all columns
+            Class colClass = columns.get(0).getClass();
+            Class colBase = colClass.getSuperclass();
+            clone.columns = new ArrayList<DBColumn>();
+            Field[] fields = getClass().getDeclaredFields();
+            for (int i = 0; i < columns.size(); i++)
+            {
+                DBTableColumn srcCol = (DBTableColumn) columns.get(i);
+                DBTableColumn newCol = new DBTableColumn(clone, srcCol);
+                // Replace all references for oldCol to newCol
+                for (int j = 0; j < fields.length; j++)
+                { // Find a class of Type DBColumn or DBTableColumn
+                    Class type = fields[j].getType();
+                    if (type == colClass || type == colBase)
+                    {
+                        try
+                        {
+                            // Check if the field points to the old Value
+                            if (fields[j].get(clone) == srcCol)
+                                fields[j].set(clone, newCol);
+                        } catch (Exception e)
+                        {
+                            // IllegalAccessException or IllegalArgumentException
+                            log.error("clone: Cannot clone table-member: " + fields[j].getName() + "-->" + e.getMessage());
+                        }
+                    }
+                }
+            }
+            // set new alias
+            clone.alias = "t" + String.valueOf(tableCount);
+            tableCount++;
+            // done
+            log.info("clone: Table " + name + " cloned! Alias old=" + alias + " new=" + clone.alias);
+            return clone;
+        } catch (CloneNotSupportedException e)
+        {
+            return null;
+        }
+    }
+
+    /**
+     * Adds a column to this table's column list.
+     * 
+     * @param column a column object
+     */
+    protected boolean addColumn(DBTableColumn column)
+    { // find column by name
+        if (column==null || column.getRowSet()!=this)
+            return error(Errors.InvalidArg, column, "column");
+        if (columns.contains(column) == true)
+            return error(Errors.ItemExists, column.getName());
+        // add now
+        columns.add(column);
+        return true;
+    }
+
+    /**
+     * Creates a new DBTableColumn object and add it to this object.
+     * 
+     * @param columnName the column name
+     * @param type the type of the column e.g. integer, text, date
+     * @param size the column width
+     * @param required true if not null column
+     * @param defValue a Object object
+     * @return the created DBTableColumn object
+     */
+    public final DBTableColumn addColumn(String columnName, DataType type, double size, boolean required, Object defValue)
+    { // find column by name
+        return new DBTableColumn(this, type, columnName, size, required, defValue);
+    }
+
+    /**
+     * Creates a new DBTableColumn object and add it to this object.
+     * 
+     * @param columnName the column name
+     * @param type the type of the column e.g. integer, text, date
+     * @param size the column width
+     * @param required true if not null column
+     * @return the created DBTableColumn object
+     */
+    public final DBTableColumn addColumn(String columnName, DataType type, double size, boolean required)
+    { // find column by name
+        return addColumn(columnName, type, size, required, null);
+    }
+
+    /**
+     * Returns the primary key.
+     * 
+     * @return the the DBIndex object ->primary key
+     */
+    public DBIndex getPrimaryKey()
+    {
+        return primaryKey;
+    }
+
+    /**
+     * Returns the list of indexes (except the primary key).
+     * 
+     * @return a list of DBIndex objects
+     */
+    public List<DBIndex> getIndexes()
+    {
+        return indexes;
+    }
+    
+    /**
+     * Sets the primary keys.
+     * 
+     * @param columns a array with one or more DBColumn objects
+     */
+    public boolean setPrimaryKey(DBColumn[] columns)
+    {
+        if (columns==null || columns.length==0)
+            return error(Errors.InvalidArg, columns, "columns");
+        // All columns must belong to this table
+        for (int i=0; i<columns.length; i++)
+            if (columns[i].getRowSet()!=this)
+                return error(Errors.InvalidArg, columns[i].getFullName(), "columns");
+        // Set primary Key now
+        primaryKey = new DBIndex(name + "_PK", DBIndex.PRIMARYKEY, columns);
+        return true;
+    }
+
+    /**
+     * Sets the primary key to a single column.
+     * 
+     * @param column the primary key column
+     */
+    public final void setPrimaryKey(DBColumn column)
+    {
+        setPrimaryKey(new DBColumn[] { column });
+    }
+
+    /**
+     * Adds two columns to the primary key list.
+     */
+    public final void setPrimaryKey(DBColumn col1, DBColumn col2)
+    {
+        setPrimaryKey(new DBColumn[] { col1, col2 });
+    }
+
+    /**
+     * Adds three columns to the primary key list.
+     */
+    public final void setPrimaryKey(DBColumn col1, DBColumn col2, DBColumn col3)
+    {
+        setPrimaryKey(new DBColumn[] { col1, col2, col3 });
+    }
+
+    /**
+     * Adds an index.
+     */
+    public boolean addIndex(String indexName, boolean unique, DBColumn[] indexColumns)
+    {
+        if (indexName==null || indexColumns==null || indexColumns.length==0)
+            return error(Errors.InvalidArg, null, "name|columns");
+        // add Index now
+        indexes.add(new DBIndex(indexName, (unique) ? DBIndex.UNIQUE : DBIndex.STANDARD, indexColumns));
+        return true;
+    }
+
+    /**
+     * Adds a timestamp column to the table used for optimistic locking.
+     * 
+     * @param columnName the column name
+     */
+    public DBTableColumn addTimestampColumn(String columnName)
+    {
+        DBTableColumn col = addColumn(columnName, DataType.DATETIME, 0, true, DBDatabase.SYSDATE);
+        setTimestampColumn(col);
+        return col;
+    }
+
+    /**
+     * Adds the table's name to the supplied sql command buffer.
+     * 
+     * @param buf the SQL-Command
+     * @param context the current SQL-Command context
+     */
+    @Override
+    public void addSQL(StringBuilder buf, long context)
+    {
+        if ((context & CTX_FULLNAME)!=0 && db!=null)
+        {   // Add Schema
+            db.appendQualifiedName(buf, name);
+        }
+        else
+        {   // Simple Name only
+            buf.append(name);
+        }
+        // Tables and Views?
+        if ((context & CTX_ALIAS)!=0 && alias!=null)
+        {    // append alias
+             buf.append(getRenameTablePhrase());
+             buf.append(alias);
+        }
+    }
+
+    /**
+     * Gets all table fields and the fields properties. 
+     * Set this to the specified DBRecord object.
+     * 
+     * @param rec the DBRecord object. contains all fields and the field properties
+     * @param conn a valid connection to the database.
+     * @return true if successful
+     */
+    @Override
+    public boolean createRecord(DBRecord rec, Connection conn)
+    {
+        // Inititialisierung
+        if (!prepareInitRecord(rec, DBRecord.REC_NEW, null))
+            return false;
+        // Set Defaults
+        int count = columns.size();
+        for (int i = 0; i < count; i++)
+        {
+            DBTableColumn column = (DBTableColumn)columns.get(i);
+            Object value = column.getRecordDefaultValue(conn);
+            if (value!=null)
+                rec.modifyValue(i, value); 
+        }
+        // Init
+        return completeInitRecord(rec);
+    }
+
+    /**
+     *  Returns true if cascaded deletes are enabled or false otherwise.
+     */
+    public boolean isCascadeDelete()
+    {
+        return cascadeDelete;
+    }
+
+    /**
+     *  Sets true if delete records will.
+     */
+    public void setCascadeDelete(boolean cascadeDelete)
+    {
+        this.cascadeDelete = cascadeDelete;
+    }
+
+    /**
+     * Creates a delete SQL-Command by using the DBCommand getDelete method
+     * execute the the SQL-Command with the DBDatabase
+     * executeSQL method.
+     * 
+     * @param key an array of the primary key columns
+     * @param conn a valid connection to the database.
+     * @return true if successful
+     */
+    @Override
+    public boolean deleteRecord(Object[] key, Connection conn)
+    {
+        // Check Primary key
+        if (primaryKey == null )
+            return error(DBErrors.NoPrimaryKey, getName());
+
+        // Check Columns
+        DBColumn[] keyColumns = primaryKey.getColumns();
+        if (key == null || key.length != keyColumns.length)
+            return error(Errors.InvalidArg, key); // Invalid Argument
+
+        // Delete References
+        if (isCascadeDelete() && deleteAllReferences(key, conn)==false)
+            return false; // Error deleting referenced records
+        
+        // Build SQL-Statement
+        DBCommand cmd = db.createCommand();
+        for (int i = 0; i < key.length; i++)
+            cmd.where(keyColumns[i].is(key[i]));
+
+        // Perform delete
+        String sqlCmd = cmd.getDelete(this);
+        int affected  = db.executeSQL(sqlCmd, null, conn);
+        if (affected < 0)
+        { // Delete Failed
+            return error(db);
+        } 
+        else if (affected == 0)
+        { // Record not found
+            return error(DBErrors.RecordDeleteFailed, name);
+        } 
+        else if (affected > 1)
+        { // Multiple Records affected
+            return error(DBErrors.RecordUpdateInvalid, name);
+        }
+        // success
+        return success();
+    }
+
+}
\ No newline at end of file



Mime
View raw message