/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.empire.db;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.apache.empire.commons.ClassUtils;
import org.apache.empire.commons.ObjectUtils;
import org.apache.empire.commons.Options;
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.Record;
import org.apache.empire.db.context.DBRollbackHandler;
import org.apache.empire.db.exceptions.FieldReadOnlyException;
import org.apache.empire.db.exceptions.FieldValueNotFetchedException;
import org.apache.empire.db.exceptions.NoPrimaryKeyException;
import org.apache.empire.db.exceptions.RecordReadOnlyException;
import org.apache.empire.exceptions.BeanPropertyGetException;
import org.apache.empire.exceptions.InvalidArgumentException;
import org.apache.empire.exceptions.NotSupportedException;
import org.apache.empire.exceptions.ObjectNotValidException;
import org.apache.empire.xml.XMLUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * This abstract class provides write access to the fields of a record
 * 
 * The class provides methods that are useful for frontend-form development like
 *   - providing information about the allowed values for a field (field options)
 *   - providing information about whether or not a field is visible to the user    
 *   - providing information about whether or not a field is required (mandantory)    
 *   - providing information about whether or not a field is read-only    
 *   - providing information about whether a particular field value is valid    
 *   - providing information about whether a field was modified since it was read from the database
 *   - providing information about whether the record was modified
 * 
 * Also, field value changes, can be handled using the onFieldChanged event.
 */
public abstract class DBRecordBase extends DBRecordData implements Record, Cloneable, Serializable
{
    private static final long serialVersionUID = 1L;
    
    private static final Logger log  = LoggerFactory.getLogger(DBRecordBase.class);
    
    /**
     * DBRecordRollbackHandler
     * @author doebele
     */
    public static class DBRecordRollbackHandler implements DBRollbackHandler
    {
        // Logger
        private static final Logger log = LoggerFactory.getLogger(DBRecordRollbackHandler.class);
        
        public final DBRecordBase   record;
        
        private final State     state;  /* the original state */
        private Object[]        fields;
        private boolean[]       modified;
        private Object          rowsetData;
    
        public DBRecordRollbackHandler(DBRecordBase record)
        {
            this.record = record;
            // check
            if (record.state==State.Invalid)
                throw new ObjectNotValidException(record);
            // save state
            this.state = record.state;            
            this.modified   = copy(record.modified);
            this.fields     = copy(record.fields);
            this.rowsetData = copy(record.rowsetData);
        }

        @Override
        public DBObject getObject()
        {
            return record;
        }

        @Override
        public String getObjectInfo()
        {
            return "Record "+record.getRowSet().getName()+":"+StringUtils.arrayToString(record.getKey(), "|");
        }

        @Override
        public void combine(DBRollbackHandler successor)
        {
            if (record!=successor.getObject())
                throw new InvalidArgumentException("successor", successor);
            // combine now
            DBRecordRollbackHandler s = (DBRecordRollbackHandler)successor;
            log.info("combining rollback state for record {}/{}", record.getRowSet().getName(), StringUtils.arrayToString(record.getKey(), "|"));
            if (s.modified==null)
            {
                return; // not modified!
            }
            // Make sure we have a modified array 
            if (modified==null)
                modified = new boolean[fields.length];
            // special case Timestamp
            DBRowSet rowset = record.getRowSet();
            DBColumn tsColumn = record.getRowSet().getTimestampColumn();
            // copy
            for (int i=0; i<fields.length; i++)
            {   // ignore timestamp and key columns
                DBColumn column = record.getColumn(i);
                if (column==tsColumn || rowset.isKeyColumn(column))
                    continue;
                // copy modified fields
                if (s.modified[i]==false)
                    continue;
                // field was modified
                fields[i] = s.fields[i];
                if (modified!=null)
                    modified[i] = true;
            }
        }

        @Override
        public void rollback(Connection conn)
        {
            // rollback
            record.state = this.state;
            record.fields = this.fields;
            record.modified = this.modified;
            record.rowsetData = rowsetData;
            // done
            if (log.isInfoEnabled())
                log.info("Rollback for {} performed.", getObjectInfo());
        }

        @Override
        public void discard(Connection conn)
        {
            /* nothing */
        }
        
        private boolean[] copy(boolean[] other)
        {
            if (other==null)
                return null;
            boolean[] copy = new boolean[other.length];
            for (int i=0; i<copy.length; i++)
            {
                copy[i] = other[i]; 
            }
            return copy;
        }
        
        private Object[] copy(Object[] other)
        {
            if (other==null)
                return null;
            Object[] copy = new Object[other.length];
            for (int i=0; i<copy.length; i++)
            {
                copy[i] = other[i]; 
            }
            return copy;
        }
        
        protected Object copy(Object other)
        {   
            if (other==null)
                return null;
            if (other instanceof Object[])
                return copy((Object[])other);
            return ClassUtils.copy(other);
        }
    }
  
    /* Record state enum */
    public enum State
    {
    	Invalid,
    /*	Empty,  not used! */
    	Valid,
    	Modified,
    	New;

    	/* Accessors */
    	boolean isLess(State other)
    	{
    		return this.ordinal()<other.ordinal();
    	}
    	boolean isEqualOrMore(State other)
    	{
    		return this.ordinal()>=other.ordinal();
    	}
    }
    
    // This is the record data
    private State           state;
    private Object[]        fields;
    private boolean[]       modified;
    Object                  rowsetData; // Special Rowset Data (usually null)
    protected boolean       validateFieldValues;
    
    // Parent-Record-Map for deferred identity setting 
    private Map<DBColumn, DBRecordBase> parentRecordMap;
    
    /**
     * Internal constructor for DBRecord
     * May be used by derived classes to provide special behaviour
     */
    protected DBRecordBase()
    {
        // init
        this.state = State.Invalid;
        this.fields = null;
        this.modified = null;
        this.rowsetData = null;
        this.validateFieldValues = true;
        this.parentRecordMap = null;
    }

    /**
     * helper to check if the object is valid
     * @throws an ObjectNotValidException if the object is not valid
     */
    protected void checkValid()
    {
        if (!isValid())
            throw new ObjectNotValidException(this);
    }

    /**
     * helper to check if the object is valid
     * @throws an ObjectNotValidException if the object is not valid
     */
    protected void checkValid(int fieldIndex)
    {
        if (!isValid())
            throw new ObjectNotValidException(this);
        // Check index
        if (fieldIndex < 0 || fieldIndex>= fields.length)
            throw new InvalidArgumentException("index", fieldIndex);
    }
    
    /**
     * Closes the record by releasing all resources and resetting the record's state to invalid.
     */
    @Override
    public void close()
    {
        // clear fields
        fields = null;
        modified = null;
        rowsetData = null;
        // change state
        if (state!=State.Invalid)
            changeState(State.Invalid);
        // done
        onRecordChanged();
    }
    
    /** {@inheritDoc} */
    @Override
    public DBRecordBase clone()
    {
        try 
        {
            DBRecordBase rec = (DBRecordBase)super.clone();
            rec.state = this.state;
            if (rec.fields == fields && fields!=null)
                rec.fields = fields.clone();
            if (rec.modified == modified && modified!=null)
                rec.modified = modified.clone();
            rec.rowsetData = ClassUtils.copy(this.rowsetData);
            return rec;
            
        } catch (CloneNotSupportedException e)
        {
            log.error("Unable to clone record.", e);
            return null;
        }
    }

    /**
     * Returns the DBRowSet object.
     * @return the DBRowSet object
     */
    public abstract DBRowSet getRowSet();
    
    /**
     * Returns whether or not RollbackHandling is enabled for this record
     */
    public abstract boolean isRollbackHandlingEnabled(); 

    /**
     * returns true if this record is a new record.
     * @return true if this record is a new record
     */
    @Override
    public EntityType getEntityType()
    {
        return getRowSet();
    }

    /**
     * Returns the current DBDatabase object.
     * 
     * @return the current DBDatabase object
     */
    @SuppressWarnings("unchecked")
    @Override
	public DBDatabase getDatabase()
    {
        return getRowSet().getDatabase();
    }

    /**
     * Returns the record state.
     * 
     * @return the record state
     */
    public State getState()
    {
        return state;
    }

    /**
     * Returns true if the record is valid.
     * 
     * @return true if the record is valid
     */
    @Override
    public boolean isValid()
    {
        return (state != State.Invalid);
    }

    /**
     * Returns true if the record is valid.
     * 
     * @return true if the record is valid
     */
    @Override
    public boolean isReadOnly()
    {
        if (!isValid())
            return true;
        DBRowSet rowset = getRowSet();
        return (rowset==null || !rowset.isUpdateable());
    }

    /**
     * Returns true if the record is modified.
     * 
     * @return true if the record is modified
     */
    @Override
    public boolean isModified()
    {
        return (state.isEqualOrMore(State.Modified));
    }

    /**
     * Returns true if this record is a new record.
     * 
     * @return true if this record is a new record
     */
    @Override
    public boolean isNew()
    {
        return (state == State.New);
    }

    /**
     * Returns true if this record is a existing record (valid but not new).
     * This may be used from expression language instead of the not allowed property "new" 
     * 
     * @return true if this record is a existing record (valid but not new).
     */
    public boolean isExists()
    {
        return (state == State.Valid || state == State.Modified);
    }

    /**
     * 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)
    {
        return getRowSet().getColumnIndex(column);
    }

    /**
     * Returns the index value by a specified column name.
     * 
     * @return the index value
     */
    @Override
    public int getFieldIndex(String column)
    {
        List<DBColumn> columns = getRowSet().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;
    }

    /**
     * Implements the Record Interface getColumn method.<BR>
     * Internally calls getDBColumn()
     * @return the Column at the specified index 
     */
    @Override
    public DBColumn getColumn(int index)
    {
        return getRowSet().getColumn(index);
    }
    
    /**
     * Returns true if the field was modified.
     * 
     * @param index the field index
     *  
     * @return true if the field was modified
     */
    public boolean wasModified(int index)
    {
        checkValid(index);
        // Check modified
        if (modified == null)
            return false;
        return modified[index];
    }
    
    /**
     * Returns true if the field was modified.
     * 
     * @return true if the field was modified
     */
    @Override
    public final boolean wasModified(Column column)
    {
        return wasModified(getFieldIndex(column));
    }

    /**
     * Returns true if any of the given fields was modified.
     * 
     * @return true if any of the given fields were modified or false otherwise
     */
    public final boolean wasAnyModified(Column... columns)
    {
        for (Column c : columns)
        {
            if (wasModified(getFieldIndex(c)))
                return true;
        }
        return false;
    }

    /**
     * Returns whether or not values are checked for validity when calling setValue().
     * If set to true validateValue() is called to check validity
     * @return true if the validity of values is checked or false otherwise
     */
    public boolean isValidateFieldValues() 
    {
        return validateFieldValues;
    }

    /**
     * Set whether or not values are checked for validity when calling setValue().
     * If set to true validateValue() is called to check validity, otherwise not.
     * @param validateFieldValues flag whether to check validity
     */
    public void setValidateFieldValues(boolean validateFieldValues) 
    {
        this.validateFieldValues = validateFieldValues;
    }

	/**
     * returns an array of key columns which uniquely identify the record.
     * @return the array of key columns if any
     */
    @Override
    public Column[] getKeyColumns()
    {
        return getRowSet().getKeyColumns();
    }

    /**
     * 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
     */
    @Override
    public Object[] getKey()
    {
        // Check Columns
        Column[] keyColumns = getKeyColumns();
        if (keyColumns == null || keyColumns.length==0)
            throw new NoPrimaryKeyException(getRowSet());
        // create the key
        Object[] key = new Object[keyColumns.length];
        for (int i = 0; i < keyColumns.length; i++)
        {
            key[i] = get(keyColumns[i]);
            if (key[i] == null)
            { // Primary Key not set
                log.warn("DBRecord.getKey() failed: " + getRowSet().getName() + " primary key value is null!");
            }
        }
        return key;
    }

    /**
     * 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 DBRecordBase#isValueValid(int)})
     * @return the index value
     */
    @Override
    public Object getValue(int index)
    {   // Check state
        checkValid(index);
        // Special check for NO_VALUE 
        if (fields[index] == ObjectUtils.NO_VALUE)
            throw new FieldValueNotFetchedException(getColumn(index));
        // 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 partially loaded.<BR>
     * 
     * @param index the filed index
     *  
     * @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
        checkValid(index);
        // 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.
     * 
     * @param column the database field column
     *  
     * @return the field options 
     */
    public Options getFieldOptions(DBColumn column)
    {
        // DBColumn col = ((colexpr instanceof DBColumn) ? ((DBColumn) colexpr) : colexpr.getSourceColumn());
        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
     */
    @Override
    public final Options getFieldOptions(Column column)
    {
        return getFieldOptions((DBColumn)column); 
    }
    
    /**
     * validates all modified values of a record
     */
    public void validateAllValues()
    {
        checkValid();
        // Modified
        if (modified == null)
            return; // nothing to do
        // check for field
        for (int index=0; index<fields.length; index++)
        {   // Modified or No value?
            if (modified[index]==false || fields[index]==ObjectUtils.NO_VALUE)
                continue;
            // Auto-generated ?
            DBColumn column = getColumn(index);
            if (column.isAutoGenerated())
                continue;
            // validate this one
            fields[index] = validateValue(column, fields[index]);
        }
    }

    /**
     * Sets the value of a column in the record.
     * The functions checks if the column and the value are valid and whether the
     * value has changed.
     * 
     * @param index the index of the column
     * @param value the value
     */
    @Override
    public void setValue(int index, Object value)
    {
        checkValid(index);
        // check updatable
        checkUpdateable();
        // Special case ParentRecord
        if (value instanceof DBRecordBase)
        {   // Special case: Value contains parent record
            setParentRecord(getColumn(index), (DBRecordBase)value);
            return;
        }
        // Strings special
        if ((value instanceof String) && ((String)value).length()==0)
            value = null;
        // Is value valid
        Object current = fields[index]; 
        if (current==ObjectUtils.NO_VALUE)
            throw new FieldValueNotFetchedException(getColumn(index));
        // convert
        DBColumn column = getColumn(index);
        // must convert enums
        if (value instanceof Enum<?>)
        {   // convert enum
            Enum<?> enumVal = ((Enum<?>)value);
            boolean numeric = column.getDataType().isNumeric();
            value = ObjectUtils.getEnumValue(enumVal, numeric);
        }
        // Has Value changed?
        if (ObjectUtils.compareEqual(current, value))
        {   // value has not changed!
            return; 
        }
        // Check whether we can change this field
        if (!allowFieldChange(column))
        {   // Read Only column may be set
            throw new FieldReadOnlyException(column);
        }
        // Is Value valid?
        if (isValidateFieldValues())
        {   // validate
            Object validated = validateValue(column, value);
            if (value != validated)
            {   // Value has been converted, check again
                if (ObjectUtils.compareEqual(current, validated))
                    return; 
                // user converted value
                value = validated;
            }
        }
        // Init original values
        modifyValue(index, value, true);
    }

    /**
     * @Deprecated Renamed to set(...)   
     */
    @Deprecated
    public DBRecordBase setValue(Column column, Object value)
    {
        return set(column, value);
    }

    /**
     * Sets the value of a 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
     */
    @Override
    public DBRecordBase set(Column column, Object value)
    {   
        setValue(getFieldIndex(column), value);
        return this;
    }

    /**
     * Validates a value before it is set in the record.
     * By default, this method simply calls column.validate()
     * @param column the column that needs to be changed
     * @param value the new value
     */
    @Override
    public Object validateValue(Column column, Object value)
    {
    	return column.validateValue(value);
    }
    
    /**
     * 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 
     */
    @Override
    public boolean isFieldVisible(Column column)
    {
    	// Check value
        int index = getRowSet().getColumnIndex(column);
        if (index<0)
        {   // Column not found
            log.warn("Column {} does not exist for record of {}", column.getName(), getRowSet().getName());
        }
        return (index>=0 && isValueValid(index));
    }
    
    /**
     * returns whether a field is read only or not
     * 
     * @param column the database column 
     * 
     * @return true if the field is read only
     */
    @Override
    public boolean isFieldReadOnly(Column column)
    {
        DBRowSet rowset = getRowSet();
    	if (getFieldIndex(column)<0)
            throw new InvalidArgumentException("column", column);
    	// Check key column 
        if (isValid() && !isNew() && rowset.isKeyColumn((DBColumn)column))
        	return true;
        // Ask RowSet
        return (rowset.isColumnReadOnly((DBColumn)column));
    }
    
    /**
     * returns whether a field is required or not
     * 
     * @param column the database column 
     * 
     * @return true if the field is required
     */
    @Override
    public boolean isFieldRequired(Column column)
    {
    	if (getRowSet().getColumnIndex(column)<0)
            throw new InvalidArgumentException("column", column);
        // from column definition
        return (column.isRequired());
    }
    
    /**
     * Sets record values from the supplied java bean.
     * 
     * @return true if at least one value has been set successfully 
     */
    @Override
    public int setRecordValues(Object bean, Collection<Column> ignoreList)
    {
        // Add all Columns
        int count = 0;
        for (int i = 0; i < getFieldCount(); i++)
        { // Check Property
            DBColumn column = getColumn(i);
            if (column.isReadOnly())
                continue;
            if (ignoreList != null && ignoreList.contains(column))
                continue; // ignore this property
            // Get Property Name
            String property = column.getBeanPropertyName();
            setRecordValue(column, bean, property);
            count++;
        }
        return count;
    }

    /**
     * Sets record values from the suppied java bean.
     * @return true if at least one value has been set sucessfully
     */
    @Override
    public final int setRecordValues(Object bean)
    {
        return setRecordValues(bean, null);
    }
    
    /**
     * For DBMS with IDENTITY-columns defer setting the parent-id until the record is inserted
     * The parent record must have a one-column primary key
     * @param parentIdColumn the column for which to set the parent
     * @param record the parent record to be set for the column
     */
    public void setParentRecord(DBColumn parentIdColumn, DBRecordBase record)
    {
        checkValid();
        // check column
        checkParamNull("parentIdColumn", parentIdColumn);
        // check updateable
        checkUpdateable();
        // remove
        if (record==null)
        {   // clear parent 
            if (parentRecordMap!=null)
                parentRecordMap.remove(parentIdColumn);
            set(parentIdColumn, null);
            return;
        }
        // set key or record
        Object[] key = record.getKey();
        if (key.length!=1)
            throw new NotSupportedException(this, "setParentRecord");
        if (key[0]==null)
        {   // preserve until later
            if (parentRecordMap==null)
                parentRecordMap = new HashMap<DBColumn, DBRecordBase>(1);
            // add record to map
            log.info("Deffering setting of {} until the record is saved!", parentIdColumn.getName());
            parentRecordMap.put(parentIdColumn, record);
        }
        else
        {   // set directly
            int index = getFieldIndex(parentIdColumn);
            Object id = getValue(index);
            if (!ObjectUtils.compareEqual(id, key[0]))
            {   // set parent-id
                modifyValue(index, key[0], true);
            }
        }
    }

    /**
     * Compares the record to another one
     * @param otherObject
     * @return true if it is the same record (but maybe a different instance)
     */
    public boolean isSame(DBRecordBase other)
    {   // check valid
        if (!isValid() || !other.isValid())
            return false;
        // compare table
        if (!getRowSet().isSame(other.getRowSet()))
            return false;
        // compare key
        Object[] key1 = getKey();
        Object[] key2 = other.getKey();
        return ObjectUtils.compareEqual(key1, key2);
    }

    /**
     * This function set the field descriptions to the the XML tag.
     * 
     * @return the number of column descriptions added to the element
     */
    @Override
    public int addXmlMeta(Element parent)
    {
        checkValid();
        // Add Field Description
        int count = 0;
        List<DBColumn> columns = getRowSet().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);
            count++;
        }
        return count;
    }

    /**
     * Add the values of this record to the specified XML Element object.
     * 
     * @param parent the XML Element object
     * @return the number of row values added to the element
     */
    @Override
    public int addXmlData(Element parent)
    {
        checkValid();
        // set row key
        Column[] keyColumns = 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
        int count = 0;
        List<DBColumn> columns = getRowSet().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
            // increase count
            count++;
        }
        return count;
    }

    /**
     * Returns a XML document with the field description an values of this record.
     * 
     * @return the new XML Document object
     */
    @Override
    public Document getXmlDocument()
    {
        checkValid();
        // Create Document
        DBXmlDictionary xmlDic = getXmlDictionary();
        Element root = XMLUtil.createDocument(xmlDic.getRowSetElementName());
        DBRowSet rowset = getRowSet();
        if (rowset.getName() != null)
            root.setAttribute("name", rowset.getName());
        // Add Field Description
        if (addXmlMeta(root)>0)
        {   // Add row Values
            addXmlData(XMLUtil.addElement(root, xmlDic.getRowElementName()));
        }
        // return Document
        return root.getOwnerDocument();
    }
    
    /**
     * 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;
    }
    
    /**
     * changes the state of the record
     * @param newState
     */
    protected void changeState(State newState)
    {
        this.state = newState;
    }
    
    /**
     * Factory function to create  createRollbackHandler();
     * @return the DBRollbackHandler
     */
    protected DBRollbackHandler createRollbackHandler()
    {
        return new DBRecordRollbackHandler(this);
    }
    
    /**
     * 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 rowsetData any further RowSet specific data
     * @param newRecord
     */
    protected void initData(boolean newRecord)
    {
        // Init rowset
        DBRowSet rowset = getRowSet();
        int colCount = rowset.getColumns().size();
        if (fields==null || fields.length!=colCount)
            fields = new Object[colCount];
        else
        {   // clear fields
            for (int i=0; i<fields.length; i++)
                if (fields[i]!=ObjectUtils.NO_VALUE)
                    fields[i]=null;
        }
        // Set State
        this.modified = null;
        this.rowsetData = null;
        changeState((rowset==null ? State.Invalid : (newRecord ? State.New : State.Valid)));
    }
    
    /**
     * This method is used internally to indicate that the record update has completed<BR>
     * This will set change the record's state to Valid
     * @param rowsetData additional data held by the rowset for this record (optional)
     */
    protected void updateComplete()
    {
        // Change state
        this.modified = null;
        changeState(State.Valid);
    }
    
    /**
     * Checks whether the record is updateable  
     * If its read-only a RecordReadOnlyException is thrown 
     */
    protected void checkUpdateable()
    {
        if (this.isReadOnly())
            throw new RecordReadOnlyException(this);
    }
    
    /**
     * Checks whether or not this field can be changed at all.
     * Note: This is not equivalent to isFieldReadOnly() 
     * @param column the column that needs to be changed
     * @return true if it is possible to change this field for this record context
     */
    protected boolean allowFieldChange(DBColumn column)
    {
        // Check auto generated
        if (column.isAutoGenerated() && (!isNew() || !isNull(column)))
            return false;
        // Check key Column
        if (!isNew() && getRowSet().isKeyColumn(column))
            return false;
        // done
        return true;
    }

    /**
     * Modifies a column value bypassing all checks made by setValue.
     * Use this to explicitly set invalid values i.e. for temporary storage.
     * 
     * @param index index of the column
     * @param value the column value
     */
    protected void modifyValue(int index, Object value, boolean fireChangeEvent)
    {   // Check valid
        checkValid(index);
        // modified state array
        if (modified == null)
        {   modified = new boolean[fields.length];
            for (int j = 0; j < fields.length; j++)
                modified[j] = false;
        }
        // set value and modified
        fields[index] = value;
        modified[index] = true;
        // set record state
        if (state.isLess(State.Modified))
            changeState(State.Modified);
        // field changed event
        if (fireChangeEvent)
            onFieldChanged(index);
    }
    
    /**
     * Override this to do extra handling when the record changes
     */
    protected void onRecordChanged()
    {
        if (log.isTraceEnabled() && isValid())
            log.trace("Record has been changed");
        // Remove rollback (but not when close() is called!)
        if (fields!=null && isRollbackHandlingEnabled())
            getContext().removeRollbackHandler(this);
    }
    
    /**
     * Override this to get notified when a field value changes
     */
    protected void onFieldChanged(int i)
    {
        if (log.isDebugEnabled())
            log.debug("Record field " + getColumn(i).getName() + " changed to " + String.valueOf(fields[i]));
    }

    /**
     * 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
     */
    protected void setRecordValue(Column column, Object bean, String property)
    {
        if (StringUtils.isEmpty(property))
            property = column.getBeanPropertyName();
        try
        {   // Get Property Value
            PropertyUtilsBean pub = BeanUtilsBean.getInstance().getPropertyUtils();
            Object value = pub.getSimpleProperty(bean, property);
            // Now, set the record value
            set( column, value ); 
            // done
        } catch (IllegalAccessException e)
        {   log.error(bean.getClass().getName() + ": unable to get property '" + property + "'");
            throw new BeanPropertyGetException(bean, property, e);
        } catch (InvocationTargetException e)
        {   log.error(bean.getClass().getName() + ": unable to get property '" + property + "'");
            throw new BeanPropertyGetException(bean, property, e);
        } catch (NoSuchMethodException e)
        {   log.warn(bean.getClass().getName() + ": no getter available for property '" + property + "'");
            throw new BeanPropertyGetException(bean, property, e);
        }
    }
    
    /**
     * For DBMS with IDENTITY-columns the deferred parent-keys are set by this functions
     * The parent records must have been previously set using setParentRecord
     */
    protected void assignParentIdentities()
    {
        // Check map
        if (parentRecordMap==null)
            return;
        // Apply map
        for (Map.Entry<DBColumn, DBRecordBase> e : parentRecordMap.entrySet())
        {
            DBColumn parentIdColumn = e.getKey();
            Object keyValue = e.getValue().getKey()[0];
            if (keyValue==null)
                throw new ObjectNotValidException(e.getValue());
            // Set key
            log.info("Deffered setting of {} to {}!", parentIdColumn.getName(), keyValue);
            set(parentIdColumn, keyValue);
        }
        parentRecordMap.clear();
    }
    
    /**
     * helper function to check if a given field index corresponds to one of the given columns
     * @param index the field index
     * @param column one or more columns to check
     * @return true if the index is for one of the columns or false otherwise
     */
    protected boolean isColumn(int index, DBColumn... column)
    {
        if (index < 0 || index >= fields.length)
            throw new InvalidArgumentException("index", index);
        if (column==null)
            throw new InvalidArgumentException("column", column);
        Column col = getColumn(index);
        for (int i=0; i<column.length; i++)
        {   // compare
            if (col==column[i])
                return true;
        }
        // not found
        return false; 
    }
    
    /**
     * returns the DBXmlDictionary that should used to generate XMLDocuments<BR>
     * @return the DBXmlDictionary
     */
    protected DBXmlDictionary getXmlDictionary()
    {
        return DBXmlDictionary.getInstance();
    }
    
}
