This is an automated email from the ASF dual-hosted git repository.
doebele pushed a commit to branch version3
in repository https://gitbox.apache.org/repos/asf/empire-db.git
The following commit(s) were added to refs/heads/version3 by this push:
new f32080b EMPIREDB-370 Split DBRecord with new class DBRecordBase,
DBRecordBean as alternative implementation
f32080b is described below
commit f32080bf478bf7349f92a1d575efdcd332f445bc
Author: Rainer Döbele <[email protected]>
AuthorDate: Tue Feb 8 13:15:33 2022 +0100
EMPIREDB-370 Split DBRecord with new class DBRecordBase, DBRecordBean as
alternative implementation
---
.../org/apache/empire/samples/db/SampleApp.java | 16 +-
.../apache/empire/jsf2/components/InputTag.java | 8 +-
.../empire/jsf2/utils/TagEncodingHelper.java | 20 +-
.../main/java/org/apache/empire/data/Record.java | 2 +-
.../java/org/apache/empire/data/RecordData.java | 2 +-
.../java/org/apache/empire/db/DBCommandExpr.java | 6 +-
.../main/java/org/apache/empire/db/DBQuery.java | 12 +-
.../main/java/org/apache/empire/db/DBReader.java | 6 +-
.../main/java/org/apache/empire/db/DBRecord.java | 1137 +-------------------
.../empire/db/{DBRecord.java => DBRecordBase.java} | 520 ++-------
.../java/org/apache/empire/db/DBRecordBean.java | 299 +++++
.../main/java/org/apache/empire/db/DBRowSet.java | 51 +-
.../main/java/org/apache/empire/db/DBTable.java | 6 +-
.../main/java/org/apache/empire/db/DBUtils.java | 14 +-
.../src/main/java/org/apache/empire/db/DBView.java | 4 +-
.../db/exceptions/RecordReadOnlyException.java | 4 +-
.../apache/empire/db/list/DBRecordListFactory.java | 4 +-
.../empire/db/list/DBRecordListFactoryImpl.java | 26 +-
18 files changed, 523 insertions(+), 1614 deletions(-)
diff --git
a/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/SampleApp.java
b/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/SampleApp.java
index 778a0fc..52bc2ae 100644
---
a/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/SampleApp.java
+++
b/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/SampleApp.java
@@ -33,6 +33,7 @@ import org.apache.empire.db.DBContext;
import org.apache.empire.db.DBQuery;
import org.apache.empire.db.DBReader;
import org.apache.empire.db.DBRecord;
+import org.apache.empire.db.DBRecordBean;
import org.apache.empire.db.DBRowSet.PartialMode;
import org.apache.empire.db.DBSQLScript;
import org.apache.empire.db.context.DBContextStatic;
@@ -413,12 +414,21 @@ public class SampleApp
*/
private static void updateEmployee(long idEmp, String phoneNumber)
{
+ /*
// Update an Employee
DBRecord rec = new DBRecord(context, db.EMPLOYEES);
rec.read(idEmp);
// Set
rec.setValue(db.EMPLOYEES.PHONE_NUMBER, phoneNumber);
rec.update();
+ */
+
+ DBRecordBean rec = new DBRecordBean();
+ rec.read(context, db.EMPLOYEES, idEmp);
+ // Set
+ rec.setValue(db.EMPLOYEES.PHONE_NUMBER, phoneNumber);
+ rec.update(context);
+
}
/**
@@ -831,9 +841,9 @@ public class SampleApp
cmd.join(EMP.DEPARTMENT_ID, DEP.ID);
cmd.where(DEP.NAME.is("Development"));
// query now
- List<DBRecord> list = context.getUtils().queryRecordList(cmd, EMP);
+ List<DBRecordBean> list = context.getUtils().queryRecordList(cmd, EMP,
DBRecordBean.class);
log.info("RecordList query found {} employees in Development
department", list.size());
- for (DBRecord record : list)
+ for (DBRecordBean record : list)
{
Object[] key = record.getKey();
// print info
@@ -850,7 +860,7 @@ public class SampleApp
log.info("Salary was modified for {}. New salary is {}",
empName, record.getDecimal(EMP.SALARY));
}
// udpate the record
- record.update();
+ record.update(context);
// convert to bean
Employee employee = new Employee();
diff --git
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/InputTag.java
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/InputTag.java
index c457cab..6a8309f 100644
---
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/InputTag.java
+++
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/InputTag.java
@@ -31,7 +31,7 @@ import javax.faces.convert.ConverterException;
import javax.faces.view.AttachedObjectHandler;
import org.apache.empire.data.Column;
-import org.apache.empire.db.DBRecord;
+import org.apache.empire.db.DBRecordBase;
import org.apache.empire.db.exceptions.FieldIllegalValueException;
import org.apache.empire.exceptions.EmpireException;
import org.apache.empire.exceptions.InvalidArgumentException;
@@ -152,12 +152,12 @@ public class InputTag extends UIInput implements
NamingContainer
throw new InvalidArgumentException("column", null);
// Check record
Object record = helper.getRecord();
- if (record!=null && (record instanceof DBRecord) &&
((DBRecord)record).isValid())
+ if (record!=null && (record instanceof DBRecordBase) &&
((DBRecordBase)record).isValid())
{ // Check if column exists
- if (((DBRecord)record).getFieldIndex(column)<0)
+ if (((DBRecordBase)record).getFieldIndex(column)<0)
throw new InvalidArgumentException("column",
column.getName());
// not visible
- log.info("Column {} is not visible for record of {} and will
not be rendered!", column.getName(), ((DBRecord)record).getRowSet().getName());
+ log.info("Column {} is not visible for record of {} and will
not be rendered!", column.getName(),
((DBRecordBase)record).getRowSet().getName());
}
else
{ // Record not valid
diff --git
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java
index ede9cc8..808b26a 100644
---
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java
+++
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java
@@ -51,7 +51,7 @@ import org.apache.empire.data.Record;
import org.apache.empire.data.RecordData;
import org.apache.empire.db.DBColumn;
import org.apache.empire.db.DBDatabase;
-import org.apache.empire.db.DBRecord;
+import org.apache.empire.db.DBRecordBase;
import org.apache.empire.db.DBRowSet;
import org.apache.empire.db.exceptions.FieldNotNullException;
import org.apache.empire.exceptions.BeanPropertyGetException;
@@ -554,11 +554,11 @@ public class TagEncodingHelper implements NamingContainer
{ // Record has changed
if (log.isTraceEnabled())
{ // Debug output
- if ((rec instanceof DBRecord) && (this.record instanceof
DBRecord))
+ if ((rec instanceof DBRecordBase) && (this.record
instanceof DBRecordBase))
{ // a database record change
- String keyOld =
StringUtils.toString(((DBRecord)this.record).getKey());
- String keyNew =
StringUtils.toString(((DBRecord)rec).getKey());
- String rowSet =
StringUtils.valueOf(((DBRecord)rec).getRowSet().getName());
+ String keyOld =
StringUtils.toString(((DBRecordBase)this.record).getKey());
+ String keyNew =
StringUtils.toString(((DBRecordBase)rec).getKey());
+ String rowSet =
StringUtils.valueOf(((DBRecordBase)rec).getRowSet().getName());
log.trace("Changing
"+component.getClass().getSimpleName()+" record of rowset "+rowSet+" from {} to
{}", keyOld, keyNew);
}
else
@@ -760,7 +760,7 @@ public class TagEncodingHelper implements NamingContainer
}
// check whether to skip validation
boolean reenableValidation = false;
- if (skipValidation && (record instanceof DBRecord))
+ if (skipValidation && (record instanceof DBRecordBase))
{ // Ignore read only values
if (this.isReadOnly())
return;
@@ -768,9 +768,9 @@ public class TagEncodingHelper implements NamingContainer
if (ObjectUtils.isEmpty(value) && ((Record)
this.record).isFieldRequired(column))
return; // Cannot set required value to null
// Disable Validation
- reenableValidation =
((DBRecord)record).isValidateFieldValues();
+ reenableValidation =
((DBRecordBase)record).isValidateFieldValues();
if (reenableValidation)
- ((DBRecord)record).setValidateFieldValues(false);
+ ((DBRecordBase)record).setValidateFieldValues(false);
// Validation skipped for
if (log.isDebugEnabled())
log.debug("Input Validation skipped for {}.",
column.getName());
@@ -782,7 +782,7 @@ public class TagEncodingHelper implements NamingContainer
} finally {
// re-enable validation
if (reenableValidation)
- ((DBRecord)record).setValidateFieldValues(true);
+ ((DBRecordBase)record).setValidateFieldValues(true);
}
}
else if (record instanceof RecordData)
@@ -851,7 +851,7 @@ public class TagEncodingHelper implements NamingContainer
if (this.record!=null)
{ // Check attribute
Object recordTagValue = getTagAttributeValue("record");
- if ((recordTagValue instanceof DBRecord) &&
this.record!=recordTagValue)
+ if ((recordTagValue instanceof DBRecordBase) &&
this.record!=recordTagValue)
{ // shoud not come here
log.warn("Record in call to IsVisible has unexpectedly
changed!");
this.record=null;
diff --git a/empire-db/src/main/java/org/apache/empire/data/Record.java
b/empire-db/src/main/java/org/apache/empire/data/Record.java
index afbd9a2..0c9b3d0 100644
--- a/empire-db/src/main/java/org/apache/empire/data/Record.java
+++ b/empire-db/src/main/java/org/apache/empire/data/Record.java
@@ -31,7 +31,7 @@ import org.apache.empire.exceptions.InvalidArgumentException;
* <P>
* This interface inherits from RecordData which provides further data access
methods.
* <P>
- * The Record interface is implemented by the class {@link
org.apache.empire.db.DBRecord}
+ * The Record interface is implemented by the class {@link
org.apache.empire.db.DBRecordBase}
*/
public interface Record extends RecordData
{
diff --git a/empire-db/src/main/java/org/apache/empire/data/RecordData.java
b/empire-db/src/main/java/org/apache/empire/data/RecordData.java
index 0fd9acf..6e37c3e 100644
--- a/empire-db/src/main/java/org/apache/empire/data/RecordData.java
+++ b/empire-db/src/main/java/org/apache/empire/data/RecordData.java
@@ -24,7 +24,7 @@ import java.util.Collection;
* The RecordData interface provides methods for accessing data and context
specific metadata.
* <P>
* The Record interface is implemented by the classes {@link
org.apache.empire.db.DBReader}
- * and {@link org.apache.empire.db.DBRecord}.
+ * and {@link org.apache.empire.db.DBRecordData}.
* <P>
*/
public interface RecordData
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBCommandExpr.java
b/empire-db/src/main/java/org/apache/empire/db/DBCommandExpr.java
index fb48502..f78ea46 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBCommandExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBCommandExpr.java
@@ -120,21 +120,21 @@ public abstract class DBCommandExpr extends DBExpr
/** throws ERR_NOTSUPPORTED */
@Override
- public void createRecord(DBRecord record, Object[] initalKey, boolean
deferredInit)
+ public void createRecord(DBRecordBase record, Object[] initalKey,
boolean deferredInit)
{
throw new NotSupportedException(this, "addRecord");
}
/** throws ERR_NOTSUPPORTED */
@Override
- public void readRecord(DBRecord record, Object[] key)
+ public void readRecord(DBRecordBase record, Object[] key)
{
throw new NotSupportedException(this, "getRecord");
}
/** throws ERR_NOTSUPPORTED */
@Override
- public void updateRecord(DBRecord rec)
+ public void updateRecord(DBRecordBase rec)
{
throw new NotSupportedException(this, "updateRecord");
}
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBQuery.java
b/empire-db/src/main/java/org/apache/empire/db/DBQuery.java
index adcb882..166634b 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBQuery.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBQuery.java
@@ -305,7 +305,7 @@ public class DBQuery extends DBRowSet
* @param record the DBRecord object, contains all fields and the field
properties
* @return a array of primary key columns
*/
- protected Object[] getRecordKey(DBRecord record)
+ protected Object[] getRecordKey(DBRecordBase record)
{
if (record == null || record.getRowSet() != this)
throw new InvalidArgumentException("record", record);
@@ -341,7 +341,7 @@ public class DBQuery extends DBRowSet
* Add rowset data
*/
@Override
- public void initRecord(DBRecord record, DBRecordData recData)
+ public void initRecord(DBRecordBase record, DBRecordData recData)
{
// init
super.initRecord(record, recData);
@@ -371,7 +371,7 @@ public class DBQuery extends DBRowSet
* @throws NotImplementedException because this is not implemented
*/
@Override
- public void createRecord(DBRecord record, Object[] initalKey, boolean
deferredInit)
+ public void createRecord(DBRecordBase record, Object[] initalKey, boolean
deferredInit)
{
throw new NotImplementedException(this, "createRecord");
}
@@ -384,7 +384,7 @@ public class DBQuery extends DBRowSet
* @param conn a valid connection to the database.
*/
@Override
- public void readRecord(DBRecord record, Object[] key)
+ public void readRecord(DBRecordBase record, Object[] key)
{
if (record == null)
throw new InvalidArgumentException("conn|rec", null);
@@ -411,7 +411,7 @@ public class DBQuery extends DBRowSet
* @param conn a valid connection to the database.
*/
@Override
- public void updateRecord(DBRecord record)
+ public void updateRecord(DBRecordBase record)
{
// check updateable
if (isUpdateable()==false)
@@ -599,7 +599,7 @@ public class DBQuery extends DBRowSet
/**
* Adds join restrictions to the supplied command object.
*/
- protected boolean addJoinRestriction(DBCommand cmd, DBColumn updCol,
DBColumn joinCol, DBColumn[] keyColumns, Object[] key, DBRecord record)
+ protected boolean addJoinRestriction(DBCommand cmd, DBColumn updCol,
DBColumn joinCol, DBColumn[] keyColumns, Object[] key, DBRecordBase record)
{ // Find key for foreign field
for (int i = 0; key!=null && i < keyColumns.length; i++)
if (keyColumns[i]==joinCol)
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBReader.java
b/empire-db/src/main/java/org/apache/empire/db/DBReader.java
index 7c8d098..15e506c 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBReader.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBReader.java
@@ -65,7 +65,7 @@ import org.w3c.dom.Element;
* <li>access field values directly by using one of the get... functions (see
{@link DBRecordData})</li>
* <li>get the rows as a list of Java Beans using by using {@link
DBReader#getBeanList(Class, int)}</li>
* <li>get the rows as an XML-Document using {@link
DBReader#getXmlDocument()} </li>
- * <li>initialize a DBRecord with the current row data using {@link
DBReader#initRecord(DBRowSet, DBRecord)}<br>
+ * <li>initialize a DBRecord with the current row data using {@link
DBReader#initRecord(DBRowSet, DBRecordBase)}<br>
* This will allow you to modify and update the data.
* </li>
* </ul>
@@ -647,12 +647,12 @@ public class DBReader extends DBRecordData implements
Closeable
* initializes a DBRecord object with the values of the current row.
* At least all primary key columns of the target rowset must be provided
by this reader.
* This function is equivalent to calling rowset.initRecord(rec, reader)
- * set also {@link DBRowSet#initRecord(DBRecord, DBRecordData)});
+ * set also {@link DBRowSet#initRecord(DBRecordBase, DBRecordData)});
* </PRE>
* @param rowset the rowset to which to attach
* @param rec the record which to initialize
*/
- public void initRecord(DBRecord rec)
+ public void initRecord(DBRecordBase rec)
{
// init Record
DBRowSet rowset = rec.getRowSet();
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBRecord.java
b/empire-db/src/main/java/org/apache/empire/db/DBRecord.java
index 20696de..7f2ba0a 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBRecord.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBRecord.java
@@ -21,205 +21,41 @@ package org.apache.empire.db;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
-import java.io.Serializable;
-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.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.Entity;
-import org.apache.empire.data.Record;
import org.apache.empire.db.DBRowSet.PartialMode;
-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.db.expr.compare.DBCompareExpr;
-import org.apache.empire.exceptions.BeanPropertyGetException;
import org.apache.empire.exceptions.InvalidArgumentException;
import org.apache.empire.exceptions.ItemNotFoundException;
import org.apache.empire.exceptions.NotSupportedException;
import org.apache.empire.exceptions.ObjectNotValidException;
import org.apache.empire.exceptions.UnspecifiedErrorException;
-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 class represents a record from a database table, view or query
*
* The class provides methods to create, read, update and delete records
- * The class provides methods to obtain as well as to modify its fields
*
* If an Idendity-column (AUTOINC) is defined, the value will be set upon
creation by the dbms to the next value
* If a Timestamp-column is defined the value will be automatically set and
concurrent changes of the record will be detected
*
* If changes to the record are made, but a rollback on the connection is
performed, the changes will be reverted (Rollback-Handling)
*
- * 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.
- *
* The record is Serializable either if the provided DBContext is
serializable, or if the Context is provided on deserialization in a derived
class.
*/
-public class DBRecord extends DBRecordData implements Record, Cloneable,
Serializable
+public class DBRecord extends DBRecordBase
{
private static final long serialVersionUID = 1L;
private static final Logger log = LoggerFactory.getLogger(DBRecord.class);
/**
- * DBRecordRollbackHandler
- * @author doebele
- */
- public static class DBRecordRollbackHandler implements DBRollbackHandler
- {
- // Logger
- private static final Logger log =
LoggerFactory.getLogger(DBRecordRollbackHandler.class);
-
- public final DBRecord record;
-
- private final State state; /* the original state */
- private Object[] fields;
- private boolean[] modified;
- private Object rowsetData;
-
- public DBRecordRollbackHandler(DBRecord 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 = 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!
- }
- // copy
- for (int i=0; i<fields.length; i++)
- {
- if (fields[i]!= s.fields[i])
- fields[i] = s.fields[i];
- // not modified
- if (modified==null)
- continue;
- if (modified[i]==false && s.modified[i])
- modified[i] = s.modified[i];
- }
- // check modified
- if (modified==null && s.modified!=null)
- modified = copy(s.modified);
- }
-
- @Override
- public void rollback()
- {
- // 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()
- {
- /* 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;
- }
- }
-
- /* 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();
- }
- }
-
- /**
* varArgs to Array
* @param values
* @return
@@ -234,17 +70,9 @@ public class DBRecord extends DBRecordData implements
Record, Cloneable, Seriali
// Context and RowSet
protected final transient DBContext context; /* transient for
serialization */
protected final transient DBRowSet rowset; /* transient for
serialization */
-
- // This is the record data
- private State state;
- private Object[] fields;
- private boolean[] modified;
- Object rowsetData; // Special Rowset Data (usually null)
// options
protected boolean enableRollbackHandling;
- protected boolean validateFieldValues;
-
/**
* Custom serialization for transient rowset.
@@ -312,14 +140,9 @@ public class DBRecord extends DBRecordData implements
Record, Cloneable, Seriali
* May be used by derived classes to provide special behaviour
*/
protected DBRecord(DBContext context, DBRowSet rowset, boolean
enableRollbackHandling)
- {
- // init
+ { // init
this.context = context;
this.rowset = rowset;
- this.state = State.Invalid;
- this.fields = null;
- this.modified = null;
- this.rowsetData = null;
// options
this.enableRollbackHandling = enableRollbackHandling;
this.validateFieldValues = true;
@@ -336,46 +159,6 @@ public class DBRecord extends DBRecordData implements
Record, Cloneable, Seriali
checkParamNull("rowset", rowset),
context.isRollbackHandlingEnabled());
}
-
- /**
- * 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 DBRecord clone()
- {
- try
- {
- DBRecord rec = (DBRecord)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 = this.rowsetData;
- rec.validateFieldValues = this.validateFieldValues;
- return rec;
-
- } catch (CloneNotSupportedException e)
- {
- log.error("Unable to clone record.", e);
- return null;
- }
- }
/**
* Returns the current Context
@@ -395,6 +178,7 @@ public class DBRecord extends DBRecordData implements
Record, Cloneable, Seriali
*
* @return the DBRowSet object
*/
+ @Override
@SuppressWarnings("unchecked")
public <T extends DBRowSet> T getRowSet()
{
@@ -404,235 +188,27 @@ public class DBRecord extends DBRecordData implements
Record, Cloneable, Seriali
}
/**
- * returns true if this record is a new record.
- * @return true if this record is a new record
- */
- @Override
- public Entity getEntity()
- {
- return getRowSet();
- }
-
- /**
- * Returns the current DBDatabase object.
- *
- * @return the current DBDatabase object
- */
- @Override
- public <T extends DBDatabase> T 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 a DBColumnExpr object by a specified index value.
- * @return the index value
- */
- @Override
- public final ColumnExpr getColumnExpr(int index)
- {
- return 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)
- {
- if (!isValid())
- throw new ObjectNotValidException(this);
- if (index < 0 || index >= fields.length)
- throw new InvalidArgumentException("index", 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 an array of key columns which uniquely identify the record.
- * @return the array of key columns if any
+ * Returns whether or not RollbackHandling is enabled for this record
*/
@Override
- public Column[] getKeyColumns()
+ public boolean isRollbackHandlingEnabled()
{
- return getRowSet().getKeyColumns();
+ return this.enableRollbackHandling;
}
/**
- * 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
+ * Set whether or not RollbackHandling will be performed for this record
+ * Since Rollback handling requires additional resources it should only be
used if necessary
+ * Especially for bulk operations it should be disabled
+ * @param enabled flag whether to enable or disable RollbackHandling
*/
- @Override
- public Object[] getKey()
+ public void setRollbackHandlingEnabled(boolean enabled)
{
- // 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] = getValue(keyColumns[i]);
- if (key[i] == null)
- { // Primary Key not set
- log.warn("DBRecord.getKey() failed: " + getRowSet().getName()
+ " primary key value is null!");
- }
- }
- return key;
+ // check
+ if (enabled && !getContext().isRollbackHandlingEnabled())
+ throw new UnspecifiedErrorException("Rollback handling cannot be
enabled for this record since it is not supported for this context!");
+ // enable or disable
+ this.enableRollbackHandling = enabled;
}
/**
@@ -656,277 +232,6 @@ public class DBRecord extends DBRecordData implements
Record, Cloneable, Seriali
}
/**
- * 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)
- throw new ObjectNotValidException(this);
- // Check index
- if (index < 0 || index>= fields.length)
- throw new InvalidArgumentException("index", 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
- if (fields == null)
- throw new ObjectNotValidException(this);
- // Check index
- if (index < 0 || index>= fields.length)
- { // Index out of range
- throw new InvalidArgumentException("index", 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()
- {
- if (!this.isValid())
- throw new ObjectNotValidException(this);
- // 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 the 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)
- {
- if (!isValid())
- throw new ObjectNotValidException(this);
- if (index < 0 || index >= fields.length)
- throw new InvalidArgumentException("index", index);
- // check updatable
- checkUpdateable();
- // 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 (this.validateFieldValues)
- { // 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);
- }
-
- /**
- * 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
- */
- @Override
- public final void setValue(Column column, Object value)
- {
- setValue(getFieldIndex(column), value);
- }
-
- /**
- * 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 or not RollbackHandling is enabled for this record
- */
- public boolean isRollbackHandlingEnabled()
- {
- return this.enableRollbackHandling;
- }
-
- /**
- * Set whether or not RollbackHandling will be performed for this record
- * Since Rollback handling requires additional resources it should only be
used if necessary
- * Especially for bulk operations it should be disabled
- * @param enabled flag whether to enable or disable RollbackHandling
- */
- public void setRollbackHandlingEnabled(boolean enabled)
- {
- // check
- if (enabled && !getContext().isRollbackHandlingEnabled())
- throw new UnspecifiedErrorException("Rollback handling cannot
be enabled for this record since it is not supported for this context!");
- // enable now
- this.enableRollbackHandling = enabled;
- }
-
- /**
- * 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 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());
- }
-
- /**
* Creates a new record
*/
public void create(Object[] initalKey)
@@ -997,7 +302,7 @@ public class DBRecord extends DBRecordData implements
Record, Cloneable, Seriali
// check updatable
checkUpdateable();
// allow rollback
- if (enableRollbackHandling)
+ if (isRollbackHandlingEnabled())
getContext().appendRollbackHandler(createRollbackHandler());
// update
getRowSet().updateRecord(this);
@@ -1020,420 +325,16 @@ public class DBRecord extends DBRecordData implements
Record, Cloneable, Seriali
// check updatable
checkUpdateable();
// allow rollback
- if (enableRollbackHandling)
+ if (isRollbackHandlingEnabled())
getContext().appendRollbackHandler(createRollbackHandler());
// Delete only if record is not new
if (!isNew())
{
Object[] key = getKey();
+ log.info("Deleting record {}", StringUtils.arrayToString(key,
"|"));
getRowSet().deleteRecord(key, getContext());
}
close();
}
-
- /**
- * 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)
- {
- if (!isValid())
- throw new ObjectNotValidException(this);
- // 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)
- {
- if (!isValid())
- throw new ObjectNotValidException(this);
- // 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()
- {
- if (!isValid())
- throw new ObjectNotValidException(this);
- // 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();
- }
-
- /**
- * 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);
- }
-
- /**
- * Compares the record to another one
- * @param otherObject
- * @return true if it is the same record (but maybe a different instance)
- */
- public boolean isSame(DBRecord 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 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;
- }
-
- /**
- * returns the DBXmlDictionary that should used to generate
XMLDocuments<BR>
- * @return the DBXmlDictionary
- */
- protected DBXmlDictionary getXmlDictionary()
- {
- return DBXmlDictionary.getInstance();
- }
-
- /**
- * 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
- if (state == State.Invalid)
- throw new ObjectNotValidException(this);
- if (index < 0 || index >= fields.length)
- throw new InvalidArgumentException("index", 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);
- }
-
- /*
- * Sets the modified state of a column.<BR>
- * This will force the field to be updated in the database, if set to TRUE.
- *
- * @param column the column
- * @param isModified modified or not
- *
- protected void setModified(DBColumn column, boolean isModified)
- { // Check valid
- if (state == State.Invalid)
- throw new ObjectNotValidException(this);
- // Check modified
- if (modified == null)
- { // Init array
- 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 to modified, if not already at least modified and
isModified is set to true
- if (state.isLess(State.Modified) && isModified)
- changeState(State.Modified);
- // Reset state to unmodified, if currently modified and not modified
anymore after the change
- if (state == State.Modified && !isModified)
- {
- boolean recordNotModified = true;
- for (int j = 0; j < fields.length; j++)
- {
- if (modified[j] == true)
- {
- recordNotModified = false;
- }
- }
- if (recordNotModified)
- {
- changeState(State.Valid);
- }
- }
- }
- */
-
- /**
- * 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
- setValue( 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);
- }
- }
-
- /**
- * 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;
- }
-
- /**
- * 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 (enableRollbackHandling && fields!=null)
- 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]));
- }
}
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBRecord.java
b/empire-db/src/main/java/org/apache/empire/db/DBRecordBase.java
similarity index 74%
copy from empire-db/src/main/java/org/apache/empire/db/DBRecord.java
copy to empire-db/src/main/java/org/apache/empire/db/DBRecordBase.java
index 20696de..17828ea 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBRecord.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBRecordBase.java
@@ -18,18 +18,13 @@
*/
package org.apache.empire.db;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
import java.io.Serializable;
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.empire.commons.ClassUtils;
import org.apache.empire.commons.ObjectUtils;
import org.apache.empire.commons.Options;
import org.apache.empire.commons.StringUtils;
@@ -37,19 +32,14 @@ import org.apache.empire.data.Column;
import org.apache.empire.data.ColumnExpr;
import org.apache.empire.data.Entity;
import org.apache.empire.data.Record;
-import org.apache.empire.db.DBRowSet.PartialMode;
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.db.expr.compare.DBCompareExpr;
import org.apache.empire.exceptions.BeanPropertyGetException;
import org.apache.empire.exceptions.InvalidArgumentException;
-import org.apache.empire.exceptions.ItemNotFoundException;
-import org.apache.empire.exceptions.NotSupportedException;
import org.apache.empire.exceptions.ObjectNotValidException;
-import org.apache.empire.exceptions.UnspecifiedErrorException;
import org.apache.empire.xml.XMLUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -57,15 +47,7 @@ import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
- * This class represents a record from a database table, view or query
- *
- * The class provides methods to create, read, update and delete records
- * The class provides methods to obtain as well as to modify its fields
- *
- * If an Idendity-column (AUTOINC) is defined, the value will be set upon
creation by the dbms to the next value
- * If a Timestamp-column is defined the value will be automatically set and
concurrent changes of the record will be detected
- *
- * If changes to the record are made, but a rollback on the connection is
performed, the changes will be reverted (Rollback-Handling)
+ * 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)
@@ -77,14 +59,12 @@ import org.w3c.dom.Element;
* - providing information about whether the record was modified
*
* Also, field value changes, can be handled using the onFieldChanged event.
- *
- * The record is Serializable either if the provided DBContext is
serializable, or if the Context is provided on deserialization in a derived
class.
*/
-public class DBRecord extends DBRecordData implements Record, Cloneable,
Serializable
+public abstract class DBRecordBase extends DBRecordData implements Record,
Cloneable, Serializable
{
private static final long serialVersionUID = 1L;
- private static final Logger log = LoggerFactory.getLogger(DBRecord.class);
+ private static final Logger log =
LoggerFactory.getLogger(DBRecordBase.class);
/**
* DBRecordRollbackHandler
@@ -95,14 +75,14 @@ public class DBRecord extends DBRecordData implements
Record, Cloneable, Seriali
// Logger
private static final Logger log =
LoggerFactory.getLogger(DBRecordRollbackHandler.class);
- public final DBRecord record;
+ public final DBRecordBase record;
private final State state; /* the original state */
private Object[] fields;
private boolean[] modified;
private Object rowsetData;
-
- public DBRecordRollbackHandler(DBRecord record)
+
+ public DBRecordRollbackHandler(DBRecordBase record)
{
this.record = record;
// check
@@ -218,123 +198,25 @@ public class DBRecord extends DBRecordData implements
Record, Cloneable, Seriali
return this.ordinal()>=other.ordinal();
}
}
-
- /**
- * varArgs to Array
- * @param values
- * @return
- */
- public static Object[] key(Object... values)
- {
- if (values.length==0)
- throw new InvalidArgumentException("values", values);
- return values;
- }
-
- // Context and RowSet
- protected final transient DBContext context; /* transient for
serialization */
- protected final transient DBRowSet rowset; /* transient for
serialization */
// This is the record data
private State state;
private Object[] fields;
private boolean[] modified;
Object rowsetData; // Special Rowset Data (usually null)
-
- // options
- protected boolean enableRollbackHandling;
protected boolean validateFieldValues;
-
- /**
- * Custom serialization for transient rowset.
- *
- */
- private void writeObject(ObjectOutputStream strm) throws IOException
- { // Context
- writeContext(strm);
- // RowSet
- writeRowSet(strm);
- // write object
- strm.defaultWriteObject();
- }
-
- protected void writeContext(ObjectOutputStream strm) throws IOException
- {
- strm.writeObject(context);
- }
-
- protected void writeRowSet(ObjectOutputStream strm) throws IOException
- {
- String dbid = rowset.getDatabase().getIdentifier();
- String rsid = rowset.getName();
- strm.writeObject(dbid);
- strm.writeObject(rsid);
- }
-
- /**
- * Custom deserialization for transient rowset.
- */
- private void readObject(ObjectInputStream strm) throws IOException,
ClassNotFoundException
- { // Context
- DBContext ctx = readContext(strm);
- ClassUtils.setPrivateFieldValue(DBRecord.class, this, "context", ctx);
- // set final field
- DBRowSet rowset = readRowSet(strm);
- ClassUtils.setPrivateFieldValue(DBRecord.class, this, "rowset",
rowset);
- // read the rest
- strm.defaultReadObject();
- }
-
- protected DBContext readContext(ObjectInputStream strm) throws
IOException, ClassNotFoundException
- {
- return (DBContext)strm.readObject();
- }
-
- protected DBRowSet readRowSet(ObjectInputStream strm) throws IOException,
ClassNotFoundException
- { // Rowset
- String dbid = String.valueOf(strm.readObject());
- String rsid = String.valueOf(strm.readObject());
- // find database
- DBDatabase dbo = DBDatabase.findByIdentifier(dbid);
- if (dbo==null)
- throw new ItemNotFoundException(dbid);
- // find rowset
- DBRowSet rso = dbo.getRowSet(rsid);
- if (rso==null)
- throw new ItemNotFoundException(dbid);
- // done
- return rso;
- }
-
/**
* Internal constructor for DBRecord
* May be used by derived classes to provide special behaviour
*/
- protected DBRecord(DBContext context, DBRowSet rowset, boolean
enableRollbackHandling)
+ protected DBRecordBase()
{
// init
- this.context = context;
- this.rowset = rowset;
this.state = State.Invalid;
this.fields = null;
this.modified = null;
this.rowsetData = null;
- // options
- this.enableRollbackHandling = enableRollbackHandling;
- this.validateFieldValues = true;
- }
-
- /**
- * Constructs a new DBRecord.<BR>
- * @param context the DBContext for this record
- * @param rowset the corresponding RowSet(Table, View, Query, etc.)
- */
- public DBRecord(DBContext context, DBRowSet rowset)
- {
- this(checkParamNull("context", context),
- checkParamNull("rowset", rowset),
- context.isRollbackHandlingEnabled());
}
/**
@@ -356,18 +238,17 @@ public class DBRecord extends DBRecordData implements
Record, Cloneable, Seriali
/** {@inheritDoc} */
@Override
- public DBRecord clone()
+ public DBRecordBase clone()
{
try
{
- DBRecord rec = (DBRecord)super.clone();
+ 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 = this.rowsetData;
- rec.validateFieldValues = this.validateFieldValues;
return rec;
} catch (CloneNotSupportedException e)
@@ -382,26 +263,18 @@ public class DBRecord extends DBRecordData implements
Record, Cloneable, Seriali
* @return
*/
@Override
- @SuppressWarnings("unchecked")
- public <T extends DBContext> T getContext()
- {
- if (this.context==null)
- throw new ObjectNotValidException(this);
- return ((T)context);
- }
+ public abstract <T extends DBContext> T getContext();
/**
* Returns the DBRowSet object.
- *
* @return the DBRowSet object
*/
- @SuppressWarnings("unchecked")
- public <T extends DBRowSet> T getRowSet()
- {
- if (this.rowset==null)
- throw new ObjectNotValidException(this);
- return (T)this.rowset;
- }
+ public abstract <T extends DBRowSet> T getRowSet();
+
+ /**
+ * Returns whether or not RollbackHandling is enabled for this record
+ */
+ public abstract boolean isRollbackHandlingEnabled();
/**
* returns true if this record is a new record.
@@ -599,6 +472,26 @@ public class DBRecord extends DBRecordData implements
Record, Cloneable, Seriali
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
@@ -634,29 +527,9 @@ public class DBRecord extends DBRecordData implements
Record, Cloneable, Seriali
}
return key;
}
-
- /**
- * Returns the record id for tables which have a single numeric primary key
- * This method is provided for convenience in additon to the the getKey()
method
- * @return the record id
- * @throws NoPrimaryKeyException if the table has no primary key
- * @throws NotSupportedException if the primary key is not a single column
of if the column is not numeric
- */
- public long getId()
- {
- // Check Columns
- Column[] keyColumns = getKeyColumns();
- if (keyColumns == null || keyColumns.length==0)
- throw new NoPrimaryKeyException(getRowSet());
- // Check Columns
- if (keyColumns.length!=1 || !keyColumns[0].getDataType().isNumeric())
- throw new NotSupportedException(this, "getId");
- // the numeric id
- return getLong(keyColumns[0]);
- }
/**
- * 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)})
+ * 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
@@ -787,7 +660,7 @@ public class DBRecord extends DBRecordData implements
Record, Cloneable, Seriali
throw new FieldReadOnlyException(column);
}
// Is Value valid?
- if (this.validateFieldValues)
+ if (isValidateFieldValues())
{ // validate
Object validated = validateValue(column, value);
if (value != validated)
@@ -827,49 +700,6 @@ public class DBRecord extends DBRecordData implements
Record, Cloneable, Seriali
{
return column.validateValue(value);
}
-
- /**
- * Returns whether or not RollbackHandling is enabled for this record
- */
- public boolean isRollbackHandlingEnabled()
- {
- return this.enableRollbackHandling;
- }
-
- /**
- * Set whether or not RollbackHandling will be performed for this record
- * Since Rollback handling requires additional resources it should only be
used if necessary
- * Especially for bulk operations it should be disabled
- * @param enabled flag whether to enable or disable RollbackHandling
- */
- public void setRollbackHandlingEnabled(boolean enabled)
- {
- // check
- if (enabled && !getContext().isRollbackHandlingEnabled())
- throw new UnspecifiedErrorException("Rollback handling cannot
be enabled for this record since it is not supported for this context!");
- // enable now
- this.enableRollbackHandling = enabled;
- }
-
- /**
- * 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 whether a field is visible to the client or not
@@ -925,110 +755,58 @@ public class DBRecord extends DBRecordData implements
Record, Cloneable, Seriali
// from column definition
return (column.isRequired());
}
-
- /**
- * Creates a new record
- */
- public void create(Object[] initalKey)
- {
- getRowSet().createRecord(this, initalKey, true);
- }
-
- /**
- * Creates a new record
- */
- public void create()
- {
- getRowSet().createRecord(this, null, false);
- }
-
- /**
- * Reads a record from the database
- * Hint: variable args param (Object...) caused problems with migration
- * @param key an array of the primary key values
- */
- public void read(Object[] key)
- { // read
- getRowSet().readRecord(this, key);
- }
-
- /**
- * Reads a record from the database
- * @param id the record id value
- */
- public final void read(long id)
- {
- read(new Object[] {id});
- }
-
- /**
- * Reads a record from the database
- * @param key an array of the primary key values
- */
- public void read(DBCompareExpr whereConstraints)
- {
- getRowSet().readRecord(this, whereConstraints);
- }
/**
- * Reads a record partially i.e. not with all but just some selected fields
- * There are two modes:
- * 1. PartialMode.INCLUDE reads only the fields provided with the column
list
- * 2. PartialMode.EXCLUDE reads all but the fields provided with the
column list
- * The primary key is always fetched implicitly
- * @param key the primary key values
- * @param mode flag whether to include only the given columns or whether
to add all but the given columns
- * @param columns the columns to include or exclude (depending on mode)
+ * Sets record values from the supplied java bean.
+ *
+ * @return true if at least one value has been set successfully
*/
- public void read(Object[] key, PartialMode mode, DBColumn... columns)
+ @Override
+ public int setRecordValues(Object bean, Collection<Column> ignoreList)
{
- getRowSet().readRecord(this, key, mode, columns);
+ // 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;
}
/**
- * Updates the record and saves all changes in the database.
+ * Sets record values from the suppied java bean.
+ * @return true if at least one value has been set sucessfully
*/
- public void update()
+ @Override
+ public final int setRecordValues(Object bean)
{
- if (!isValid())
- throw new ObjectNotValidException(this);
- if (!isModified())
- return; /* Not modified. Nothing to do! */
- // check updatable
- checkUpdateable();
- // allow rollback
- if (enableRollbackHandling)
- getContext().appendRollbackHandler(createRollbackHandler());
- // update
- getRowSet().updateRecord(this);
+ return setRecordValues(bean, null);
}
/**
- * 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.
+ * Compares the record to another one
+ * @param otherObject
+ * @return true if it is the same record (but maybe a different instance)
*/
- public void delete()
- {
- if (isValid()==false)
- throw new ObjectNotValidException(this);
- // check updatable
- checkUpdateable();
- // allow rollback
- if (enableRollbackHandling)
- getContext().appendRollbackHandler(createRollbackHandler());
- // Delete only if record is not new
- if (!isNew())
- {
- Object[] key = getKey();
- getRowSet().deleteRecord(key, getContext());
- }
- close();
+ 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);
}
/**
@@ -1133,59 +911,6 @@ public class DBRecord extends DBRecordData implements
Record, Cloneable, Seriali
}
/**
- * 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);
- }
-
- /**
- * Compares the record to another one
- * @param otherObject
- * @return true if it is the same record (but maybe a different instance)
- */
- public boolean isSame(DBRecord 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 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
@@ -1196,15 +921,6 @@ public class DBRecord extends DBRecordData implements
Record, Cloneable, Seriali
}
/**
- * returns the DBXmlDictionary that should used to generate
XMLDocuments<BR>
- * @return the DBXmlDictionary
- */
- protected DBXmlDictionary getXmlDictionary()
- {
- return DBXmlDictionary.getInstance();
- }
-
- /**
* changes the state of the record
* @param newState
*/
@@ -1316,49 +1032,27 @@ public class DBRecord extends DBRecordData implements
Record, Cloneable, Seriali
if (fireChangeEvent)
onFieldChanged(index);
}
-
- /*
- * Sets the modified state of a column.<BR>
- * This will force the field to be updated in the database, if set to TRUE.
- *
- * @param column the column
- * @param isModified modified or not
- *
- protected void setModified(DBColumn column, boolean isModified)
- { // Check valid
- if (state == State.Invalid)
- throw new ObjectNotValidException(this);
- // Check modified
- if (modified == null)
- { // Init array
- 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 to modified, if not already at least modified and
isModified is set to true
- if (state.isLess(State.Modified) && isModified)
- changeState(State.Modified);
- // Reset state to unmodified, if currently modified and not modified
anymore after the change
- if (state == State.Modified && !isModified)
- {
- boolean recordNotModified = true;
- for (int j = 0; j < fields.length; j++)
- {
- if (modified[j] == true)
- {
- recordNotModified = false;
- }
- }
- if (recordNotModified)
- {
- changeState(State.Valid);
- }
- }
+
+ /**
+ * 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.
@@ -1416,24 +1110,12 @@ public class DBRecord extends DBRecordData implements
Record, Cloneable, Seriali
}
/**
- * 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 (enableRollbackHandling && fields!=null)
- getContext().removeRollbackHandler(this);
- }
-
- /**
- * Override this to get notified when a field value changes
+ * returns the DBXmlDictionary that should used to generate
XMLDocuments<BR>
+ * @return the DBXmlDictionary
*/
- protected void onFieldChanged(int i)
+ protected DBXmlDictionary getXmlDictionary()
{
- if (log.isDebugEnabled())
- log.debug("Record field " + getColumn(i).getName() + " changed to
" + String.valueOf(fields[i]));
+ return DBXmlDictionary.getInstance();
}
}
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBRecordBean.java
b/empire-db/src/main/java/org/apache/empire/db/DBRecordBean.java
new file mode 100644
index 0000000..89a4c6e
--- /dev/null
+++ b/empire-db/src/main/java/org/apache/empire/db/DBRecordBean.java
@@ -0,0 +1,299 @@
+/*
+ * 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.sql.Connection;
+
+import org.apache.empire.commons.StringUtils;
+import org.apache.empire.data.Column;
+import org.apache.empire.db.DBRowSet.PartialMode;
+import org.apache.empire.db.exceptions.NoPrimaryKeyException;
+import org.apache.empire.db.expr.compare.DBCompareExpr;
+import org.apache.empire.exceptions.InvalidArgumentException;
+import org.apache.empire.exceptions.NotSupportedException;
+import org.apache.empire.exceptions.ObjectNotValidException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class represents a record from a database table, view or query
+ *
+ * Other than DBRecord it is not permanently attached to a context or rowset
+ *
+ * Thus it has a Default constructor and is essentially a dynamic bean
+ *
+ */
+public class DBRecordBean extends DBRecordBase
+{
+ private static final long serialVersionUID = 1L;
+
+ private static final Logger log =
LoggerFactory.getLogger(DBRecordBean.class);
+
+ /**
+ * varArgs to Array
+ * @param values
+ * @return
+ */
+ public static Object[] key(Object... values)
+ {
+ if (values.length==0)
+ throw new InvalidArgumentException("values", values);
+ return values;
+ }
+
+ // Context and RowSet
+ protected transient DBContext tempContext;
+ protected transient DBRowSet rowset; /* will be injected by DBRowset */
+
+ // options
+ protected boolean enableRollbackHandling;
+
+ /**
+ * Constructs a new DBRecordBean.<BR>
+ * @param enableRollbackHandling flag whether to enable rollback handing
+ */
+ public DBRecordBean(boolean enableRollbackHandling)
+ {
+ this.enableRollbackHandling = enableRollbackHandling;
+ }
+
+ /**
+ * Constructs a new DBRecordBean.<BR>
+ * @param context the DBContext for this record
+ * @param rowset the corresponding RowSet(Table, View, Query, etc.)
+ */
+ public DBRecordBean()
+ {
+ this(false);
+ }
+
+ /**
+ * Returns the current Context
+ * @return
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T extends DBContext> T getContext()
+ {
+ if (this.tempContext==null)
+ throw new ObjectNotValidException(this);
+ return ((T)tempContext);
+ }
+
+ /**
+ * Returns the DBRowSet object.
+ *
+ * @return the DBRowSet object
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T extends DBRowSet> T getRowSet()
+ {
+ if (this.rowset==null)
+ throw new ObjectNotValidException(this);
+ return (T)this.rowset;
+ }
+
+ /**
+ * Returns whether or not RollbackHandling is enabled for this record
+ */
+ @Override
+ public boolean isRollbackHandlingEnabled()
+ {
+ return this.enableRollbackHandling;
+ }
+
+ /**
+ * Set whether or not RollbackHandling will be performed for this record
+ * Since Rollback handling requires additional resources it should only be
used if necessary
+ * Especially for bulk operations it should be disabled
+ * @param enabled flag whether to enable or disable RollbackHandling
+ */
+ public void setRollbackHandlingEnabled(boolean enabled)
+ {
+ // enable or disable
+ this.enableRollbackHandling = enabled;
+ }
+
+ /**
+ * Returns the record id for tables which have a single numeric primary key
+ * This method is provided for convenience in additon to the the getKey()
method
+ * @return the record id
+ * @throws NoPrimaryKeyException if the table has no primary key
+ * @throws NotSupportedException if the primary key is not a single column
of if the column is not numeric
+ */
+ public long getId()
+ {
+ // Check Columns
+ Column[] keyColumns = getKeyColumns();
+ if (keyColumns == null || keyColumns.length==0)
+ throw new NoPrimaryKeyException(getRowSet());
+ // Check Columns
+ if (keyColumns.length!=1 || !keyColumns[0].getDataType().isNumeric())
+ throw new NotSupportedException(this, "getId");
+ // the numeric id
+ return getLong(keyColumns[0]);
+ }
+
+ @Override
+ public void close()
+ {
+ super.close();
+ // clear
+ this.rowset = null;
+ }
+
+ /**
+ * Creates a new record
+ */
+ public void create(DBContext context, DBRowSet rowset, Object[] initalKey)
+ {
+ try {
+ this.tempContext = context;
+ rowset.createRecord(this, initalKey, true);
+ } finally {
+ this.tempContext = null;
+ }
+ }
+
+ /**
+ * Creates a new record
+ */
+ public void create(DBContext context, DBRowSet rowset)
+ {
+ try {
+ this.tempContext = context;
+ rowset.createRecord(this, null, false);
+ } finally {
+ this.tempContext = null;
+ }
+ }
+
+ /**
+ * Reads a record from the database
+ * Hint: variable args param (Object...) caused problems with migration
+ * @param key an array of the primary key values
+ */
+ public void read(DBContext context, DBRowSet rowset, Object[] key)
+ { // read
+ try {
+ this.tempContext = context;
+ rowset.readRecord(this, key);
+ } finally {
+ this.tempContext = null;
+ }
+ }
+
+ /**
+ * Reads a record from the database
+ * @param id the record id value
+ */
+ public final void read(DBContext context, DBRowSet rowset, long id)
+ {
+ read(context, rowset, new Object[] {id});
+ }
+
+ /**
+ * Reads a record from the database
+ * @param key an array of the primary key values
+ */
+ public void read(DBContext context, DBRowSet rowset, DBCompareExpr
whereConstraints)
+ { // read
+ try {
+ this.tempContext = context;
+ rowset.readRecord(this, whereConstraints);
+ } finally {
+ this.tempContext = null;
+ }
+ }
+
+ /**
+ * Reads a record partially i.e. not with all but just some selected fields
+ * There are two modes:
+ * 1. PartialMode.INCLUDE reads only the fields provided with the column
list
+ * 2. PartialMode.EXCLUDE reads all but the fields provided with the
column list
+ * The primary key is always fetched implicitly
+ * @param key the primary key values
+ * @param mode flag whether to include only the given columns or whether
to add all but the given columns
+ * @param columns the columns to include or exclude (depending on mode)
+ */
+ public void read(DBContext context, DBRowSet rowset, Object[] key,
PartialMode mode, DBColumn... columns)
+ { // read
+ try {
+ this.tempContext = context;
+ rowset.readRecord(this, key, mode, columns);
+ } finally {
+ this.tempContext = null;
+ }
+ }
+
+ /**
+ * Updates the record in the database
+ * @param context the current context
+ */
+ public void update(DBContext context)
+ { // update
+ if (isValid()==false)
+ throw new ObjectNotValidException(this);
+ if (!isModified())
+ return; /* Not modified. Nothing to do! */
+ try {
+ this.tempContext = context;
+ // check updatable
+ checkUpdateable();
+ // allow rollback
+ if (isRollbackHandlingEnabled())
+ context.appendRollbackHandler(createRollbackHandler());
+ // update
+ getRowSet().updateRecord(this);
+ } finally {
+ this.tempContext = null;
+ }
+ }
+
+ /**
+ * 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 context the current context
+ */
+ public void delete(DBContext context)
+ {
+ if (isValid()==false)
+ throw new ObjectNotValidException(this);
+ // check updatable
+ checkUpdateable();
+ // allow rollback
+ if (isRollbackHandlingEnabled())
+ context.appendRollbackHandler(createRollbackHandler());
+ // Delete only if record is not new
+ if (!isNew())
+ {
+ Object[] key = getKey();
+ log.info("Deleting record {}", StringUtils.arrayToString(key,
"|"));
+ getRowSet().deleteRecord(key, context);
+ }
+ close();
+ }
+
+}
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java
b/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java
index 201123c..3d7af28 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java
@@ -154,10 +154,17 @@ public abstract class DBRowSet extends DBExpr implements
Entity
* @param record the record
* @return the record
*/
- protected void checkParamRecord(String name, DBRecord record, boolean
checkValid)
+ protected void checkParamRecord(DBRecordBase record, boolean checkValid)
{
+ // special
+ if ((record instanceof DBRecordBean) && !checkValid)
+ { // set rowset of DBRecordBean
+ ((DBRecordBean)record).rowset = this;
+ }
+ // check param
if (record==null || record.getRowSet()!=this)
- throw new InvalidArgumentException(name, record);
+ throw new InvalidArgumentException("record", record);
+ // check valid
if (checkValid && !record.isValid())
throw new ObjectNotValidException(record);
}
@@ -289,7 +296,7 @@ public abstract class DBRowSet extends DBExpr implements
Entity
public abstract boolean isUpdateable();
- public abstract void createRecord(DBRecord record, Object[] initalKey,
boolean deferredInit);
+ public abstract void createRecord(DBRecordBase record, Object[] initalKey,
boolean deferredInit);
public abstract void deleteRecord(Object[] key, DBContext context);
@@ -573,10 +580,10 @@ public abstract class DBRowSet extends DBExpr implements
Entity
* @param fieldInitMode indicates how to initializes the record fields
* @param newRecord true if the record is new or false if it is an
existing record
*/
- protected void initRecord(DBRecord record, Object[] key, FieldInitMode
fieldInitMode, boolean newRecord)
+ protected void initRecord(DBRecordBase record, Object[] key, FieldInitMode
fieldInitMode, boolean newRecord)
{
// check param
- checkParamRecord("record", record, false);
+ checkParamRecord(record, false);
// Prepare
prepareInitRecord(record, newRecord);
// Initialize all Fields
@@ -621,10 +628,10 @@ public abstract class DBRowSet extends DBExpr implements
Entity
* @param record the record object
* @param recData the record data from which to initialized the record
*/
- public void initRecord(DBRecord record, DBRecordData recData)
+ public void initRecord(DBRecordBase record, DBRecordData recData)
{
// check param
- checkParamRecord("record", record, false);
+ checkParamRecord(record, false);
// Initialize the record
prepareInitRecord(record, false);
// Get Record Field Values
@@ -662,7 +669,7 @@ public abstract class DBRowSet extends DBExpr implements
Entity
* @param record the record
* @param conn (optional) to allow the dbms handle autogenerated fields
*/
- protected void initRecordDefaultValues(DBRecord record, FieldInitMode
fieldInitMode)
+ protected void initRecordDefaultValues(DBRecordBase record, FieldInitMode
fieldInitMode)
{
// check field init mode
if (fieldInitMode==FieldInitMode.NONE)
@@ -690,7 +697,7 @@ public abstract class DBRowSet extends DBExpr implements
Entity
* @param rowSetData any further RowSet specific data
* @param insert
*/
- protected void prepareInitRecord(DBRecord record, boolean newRecord)
+ protected void prepareInitRecord(DBRecordBase record, boolean newRecord)
{
if (record==null || record.getRowSet()!=this)
throw new InvalidArgumentException("rec", record);
@@ -706,7 +713,7 @@ public abstract class DBRowSet extends DBExpr implements
Entity
* <P>
* @param record the DBRecord object to initialize
*/
- protected void completeInitRecord(DBRecord record)
+ protected void completeInitRecord(DBRecordBase record)
{
record.onRecordChanged();
}
@@ -745,10 +752,10 @@ public abstract class DBRowSet extends DBExpr implements
Entity
* @param cmd the SQL-Command used to query the record
* @param rowSetData optional rowset specific data to be held on the record
*/
- protected void readRecord(DBRecord record, DBCommand cmd)
+ protected <R extends DBRecordBase> void readRecord(R record, DBCommand cmd)
{
// check param
- checkParamRecord("record", record, false);
+ checkParamRecord(record, false);
// read now
DBReader reader = null;
try
@@ -788,7 +795,7 @@ public abstract class DBRowSet extends DBExpr implements
Entity
* @param record the DBRecord object which will hold the record data
* @param key the primary key values
*/
- public void readRecord(DBRecord record, Object[] key)
+ public <R extends DBRecordBase> void readRecord(R record, Object[] key)
{
// Check Arguments
checkParamNull("key", key);
@@ -805,7 +812,7 @@ public abstract class DBRowSet extends DBExpr implements
Entity
* Reads a record from the database
* @param key an array of the primary key values
*/
- public void readRecord(DBRecord record, DBCompareExpr whereConstraints)
+ public void readRecord(DBRecordBase record, DBCompareExpr whereConstraints)
{
// Check Arguments
checkParamNull("whereConstraints", whereConstraints);
@@ -829,7 +836,7 @@ public abstract class DBRowSet extends DBExpr implements
Entity
* @param mode flag whether to include only the given columns or whether
to add all but the given columns
* @param columns the columns to include or exclude (depending on mode)
*/
- public void readRecord(DBRecord record, Object[] key, PartialMode mode,
DBColumn... columns)
+ public void readRecord(DBRecordBase record, Object[] key, PartialMode
mode, DBColumn... columns)
{
// Check Arguments
checkParamNull("key", key);
@@ -907,13 +914,13 @@ public abstract class DBRowSet extends DBExpr implements
Entity
* <P>
* @param record the DBRecord object. contains all fields and the field
properties
*/
- public void updateRecord(DBRecord record)
+ public <R extends DBRecordBase> void updateRecord(R record)
{
// check updateable
if (isUpdateable()==false)
throw new NotSupportedException(this, "updateRecord");
// Check Arguments
- checkParamRecord("record", record, true);
+ checkParamRecord(record, true);
// the connection
DBContext context = record.getContext();
Connection conn = context.getConnection();
@@ -929,8 +936,8 @@ public abstract class DBRowSet extends DBExpr implements
Entity
int setCount = 0;
// Perform action
DBColumn[] keyColumns =(DBColumn[])getKeyColumns();
- DBRecord.State recordState = record.getState();
- if (recordState==DBRecord.State.New)
+ DBRecordBase.State recordState = record.getState();
+ if (recordState==DBRecordBase.State.New)
{ // Insert Record
for (int i = 0; i < columns.size(); i++)
{ // search for the column
@@ -975,7 +982,7 @@ public abstract class DBRowSet extends DBExpr implements
Entity
}
sql = cmd.getInsert();
}
- else if (recordState==DBRecord.State.Modified)
+ else if (recordState==DBRecordBase.State.Modified)
{ // Update Record
if (keyColumns == null)
{ // Requires a primary key
@@ -1163,7 +1170,7 @@ public abstract class DBRowSet extends DBExpr implements
Entity
* @param record the record
* @return the rowset data
*/
- protected final Object getRowsetData(DBRecord record)
+ protected final Object getRowsetData(DBRecordBase record)
{
return record.rowsetData;
}
@@ -1173,7 +1180,7 @@ public abstract class DBRowSet extends DBExpr implements
Entity
* @param rec the record
* @return the rowset data
*/
- protected final void setRowsetData(DBRecord record, Object rowsetData)
+ protected final void setRowsetData(DBRecordBase record, Object rowsetData)
{
record.rowsetData = rowsetData;
}
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBTable.java
b/empire-db/src/main/java/org/apache/empire/db/DBTable.java
index 7c67770..1dc70f2 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBTable.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBTable.java
@@ -578,7 +578,7 @@ public class DBTable extends DBRowSet implements Cloneable
* @param conn a valid connection to the database.
*/
@Override
- public void createRecord(DBRecord record, Object[] initalKey, boolean
deferredInit)
+ public void createRecord(DBRecordBase record, Object[] initalKey, boolean
deferredInit)
{
FieldInitMode fieldInitMode = (deferredInit ?
FieldInitMode.SET_DEFAULTS_DEFERRED : FieldInitMode.SET_DEFAULTS);
super.initRecord(record, initalKey, fieldInitMode, true);
@@ -590,7 +590,7 @@ public class DBTable extends DBRowSet implements Cloneable
* @param id the record's primary key
* @param conn a valid JDBC connection
*/
- public DBIndex checkUniqueConstraints(DBRecord rec)
+ public DBIndex checkUniqueConstraints(DBRecordBase rec)
{
for (DBIndex idx : getIndexes())
{
@@ -720,7 +720,7 @@ public class DBTable extends DBRowSet implements Cloneable
* @param conn (optional) to allow the dbms handle autogenerated fields
*/
@Override
- protected void initRecordDefaultValues(DBRecord record, FieldInitMode
fieldInitMode)
+ protected void initRecordDefaultValues(DBRecordBase record, FieldInitMode
fieldInitMode)
{
// check field init mode
if (fieldInitMode==FieldInitMode.NONE)
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBUtils.java
b/empire-db/src/main/java/org/apache/empire/db/DBUtils.java
index 6220893..cd61d7a 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBUtils.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBUtils.java
@@ -816,9 +816,9 @@ public class DBUtils implements DBContextAware
* @param recordClass the recordClass for which to create the list head
* @return
*/
- protected <T extends DBRecord> DBRecordListFactory<T>
createDefaultRecordListFactory(Class<T> recordClass, DBRowSet rowset)
+ protected <R extends DBRecordBase> DBRecordListFactory<R>
createDefaultRecordListFactory(Class<R> recordClass, DBRowSet rowset)
{
- return new DBRecordListFactoryImpl<T>(recordClass, context.getClass(),
rowset);
+ return new DBRecordListFactoryImpl<R>(recordClass, context.getClass(),
rowset);
}
/**
@@ -829,9 +829,9 @@ public class DBUtils implements DBContextAware
* @param pageSize the maximum number of items to add to the list or -1
(default) for all
* @return the list
*/
- public <T extends DBRecord> List<T> queryRecordList(DBCommand cmd,
DBRecordListFactory<T> factory, int first, int pageSize)
+ public <R extends DBRecordBase> List<R> queryRecordList(DBCommand cmd,
DBRecordListFactory<R> factory, int first, int pageSize)
{
- List<T> list = null;
+ List<R> list = null;
DBReader r = new DBReader(context);
try
{ // prepare
@@ -866,7 +866,7 @@ public class DBUtils implements DBContextAware
int rownum = 0;
while (r.moveNext() && maxCount != 0)
{ // Create bean an init
- T entry = factory.newRecord(rownum, r);
+ R entry = factory.newRecord(rownum, r);
if (entry==null)
continue;
// check
@@ -902,10 +902,10 @@ public class DBUtils implements DBContextAware
* @param rowset the rowset for which to query the records
* @return the list of DBRecord items
*/
- public final <T extends DBRecord> List<T> queryRecordList(DBCommand cmd,
DBRowSet rowset, Class<T> recordType)
+ public final <R extends DBRecordBase> List<R> queryRecordList(DBCommand
cmd, DBRowSet rowset, Class<R> recordType)
{
@SuppressWarnings("cast")
- DBRecordListFactory<T> factory =
(DBRecordListFactory<T>)createDefaultRecordListFactory(recordType, rowset);
+ DBRecordListFactory<R> factory =
(DBRecordListFactory<R>)createDefaultRecordListFactory(recordType, rowset);
return queryRecordList(cmd, factory, 0, -1);
}
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBView.java
b/empire-db/src/main/java/org/apache/empire/db/DBView.java
index 4e94986..9d5acd3 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBView.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBView.java
@@ -405,7 +405,7 @@ public abstract class DBView extends DBRowSet
}
@Override
- public void updateRecord(DBRecord rec)
+ public void updateRecord(DBRecordBase rec)
{
if (updateable==false)
throw new NotSupportedException(this, "updateRecord");
@@ -419,7 +419,7 @@ public abstract class DBView extends DBRowSet
* @see
org.apache.empire.db.DBRowSet#addRecord(org.apache.empire.db.DBRecord,
java.sql.Connection)
*/
@Override
- public void createRecord(DBRecord record, Object[] initalKey, boolean
deferredInit)
+ public void createRecord(DBRecordBase record, Object[] initalKey, boolean
deferredInit)
{
throw new NotSupportedException(this, "createRecord");
}
diff --git
a/empire-db/src/main/java/org/apache/empire/db/exceptions/RecordReadOnlyException.java
b/empire-db/src/main/java/org/apache/empire/db/exceptions/RecordReadOnlyException.java
index 49046a6..6c27652 100644
---
a/empire-db/src/main/java/org/apache/empire/db/exceptions/RecordReadOnlyException.java
+++
b/empire-db/src/main/java/org/apache/empire/db/exceptions/RecordReadOnlyException.java
@@ -19,7 +19,7 @@
package org.apache.empire.db.exceptions;
import org.apache.empire.commons.ErrorType;
-import org.apache.empire.db.DBRecord;
+import org.apache.empire.db.DBRecordBase;
public class RecordReadOnlyException extends RecordException
{
@@ -27,7 +27,7 @@ public class RecordReadOnlyException extends RecordException
public static final ErrorType errorType = new
ErrorType("error.db.recordIsReadOnly", "The record {0} of {1} is read
only.");
- public RecordReadOnlyException(DBRecord record)
+ public RecordReadOnlyException(DBRecordBase record)
{
super(record, errorType, new String[] { keyToString(getKey(record)),
entityName(getEntity(record)) });
}
diff --git
a/empire-db/src/main/java/org/apache/empire/db/list/DBRecordListFactory.java
b/empire-db/src/main/java/org/apache/empire/db/list/DBRecordListFactory.java
index a74838a..a92d6a4 100644
--- a/empire-db/src/main/java/org/apache/empire/db/list/DBRecordListFactory.java
+++ b/empire-db/src/main/java/org/apache/empire/db/list/DBRecordListFactory.java
@@ -22,10 +22,10 @@ import java.util.List;
import org.apache.empire.db.DBCommand;
import org.apache.empire.db.DBContext;
-import org.apache.empire.db.DBRecord;
+import org.apache.empire.db.DBRecordBase;
import org.apache.empire.db.DBRecordData;
-public interface DBRecordListFactory<T extends DBRecord>
+public interface DBRecordListFactory<T extends DBRecordBase>
{
void prepareQuery(DBCommand cmd, DBContext context);
diff --git
a/empire-db/src/main/java/org/apache/empire/db/list/DBRecordListFactoryImpl.java
b/empire-db/src/main/java/org/apache/empire/db/list/DBRecordListFactoryImpl.java
index fae7866..e520053 100644
---
a/empire-db/src/main/java/org/apache/empire/db/list/DBRecordListFactoryImpl.java
+++
b/empire-db/src/main/java/org/apache/empire/db/list/DBRecordListFactoryImpl.java
@@ -27,6 +27,8 @@ import org.apache.empire.commons.ClassUtils;
import org.apache.empire.db.DBCommand;
import org.apache.empire.db.DBContext;
import org.apache.empire.db.DBRecord;
+import org.apache.empire.db.DBRecordBase;
+import org.apache.empire.db.DBRecordBean;
import org.apache.empire.db.DBRecordData;
import org.apache.empire.db.DBRowSet;
import org.apache.empire.exceptions.InternalException;
@@ -40,7 +42,7 @@ import org.slf4j.LoggerFactory;
* Implements the DBRecordListFactory interface
* @author rainer
*/
-public class DBRecordListFactoryImpl<T extends DBRecord> implements
DBRecordListFactory<T>
+public class DBRecordListFactoryImpl<T extends DBRecordBase> implements
DBRecordListFactory<T>
{
// Logger
protected static final Logger log =
LoggerFactory.getLogger(DBRecordListFactoryImpl.class);
@@ -53,13 +55,20 @@ public class DBRecordListFactoryImpl<T extends DBRecord>
implements DBRecordList
* @return the constructor
*/
@SuppressWarnings("unchecked")
- protected static <T extends DBRecord> Constructor<T>
findRecordConstructor(Class<T> recordClass, Class<? extends DBContext>
contextClass, Class<? extends DBRowSet> rowsetClass)
+ protected static <T extends DBRecordBase> Constructor<T>
findRecordConstructor(Class<T> recordClass, Class<? extends DBContext>
contextClass, Class<? extends DBRowSet> rowsetClass)
{
- // try (context+rowset or just context)
- Constructor<?> constructor =
ClassUtils.findMatchingAccessibleConstructor(recordClass, 1, contextClass,
rowsetClass);
- if (constructor==null)
- { // nothing suitable
- throw new UnsupportedTypeException(recordClass);
+ Constructor<?> constructor;
+ if (DBRecordBean.class.isAssignableFrom(recordClass))
+ { // find standard constructor
+ constructor =
ClassUtils.findMatchingAccessibleConstructor(recordClass, 0);
+ }
+ else
+ { // try (context+rowset or just context)
+ constructor =
ClassUtils.findMatchingAccessibleConstructor(recordClass, 1, contextClass,
rowsetClass);
+ if (constructor==null)
+ { // nothing suitable
+ throw new UnsupportedTypeException(recordClass);
+ }
}
// found
return (Constructor<T>)constructor;
@@ -122,11 +131,12 @@ public class DBRecordListFactoryImpl<T extends DBRecord>
implements DBRecordList
{
case 2: record = constructor.newInstance(recData.getContext(),
rowset);break;
case 1: record =
constructor.newInstance(recData.getContext());break;
+ case 0: record = constructor.newInstance();break;
default:
throw new
UnsupportedTypeException(constructor.getClass());
}
// check
- if (rowset.isSame(record.getRowSet())==false)
+ if ((record instanceof DBRecord) &&
!rowset.isSame(record.getRowSet()))
{ // log warning
log.warn("DBRecordListFactoryImpl rowset ({}) and actual
record rowset ({}) don't match!", rowset.getName(),
record.getRowSet().getName());
throw new InvalidPropertyException("rowset",
record.getRowSet());