package simpleorm.data;
import org.apache.commons.beanutils.PropertyUtils;
import java.util.Collections;
/**
* A real instance of a record, eg. an Employee or a Department.
* Normally specialized for the actual record, eg. Emp extends DRecordInstance.<p>
*
* This delegates the actual storage of the record's field to a Commons-beanutils bean.
* If needed, users can specialize with dyna beans.
* (Not as elegant as our own hashMap of DFieldInstances, for old values etc., but simpler
* given main implementation will be simple beans or ddlutils.)
*/
public class DRecordInstance {
final DRecordMeta recordMeta;
Object bean; // that stores the acual values.
public DRecordInstance(DRecordMeta meta) { // SORM no param so can be newInstanced
this.recordMeta = meta;
}
/**
* Get value as its base object, without any conversion, from the Bean.
*
*/
public Object getObject(DFieldMeta meta) {
return getObject(meta.getName());
}
public Object getObject(String property) {
try {
return PropertyUtils.getSimpleProperty(bean, property);
} catch (Exception ex) {
throw new DException("Could not access prop " + property, ex);
}
}
public void setObject(DFieldMeta meta, Object value) {
setObject(meta.name, value);
}
public void setObject(String property, Object value) {
try {
PropertyUtils.setSimpleProperty(bean, property, value);
} catch (Exception ex) {
throw new DException("While " + this + "." + property + " = " + value, ex);
}
}
/** just GetObject.toString */
public String getString(DFieldMeta meta) {
Object res = getObject(meta);
return res == null ? null : res.toString();
}
/** Compares primary keys only. */
public boolean equals(Object other) {
DRecordInstance otherRec = (DRecordInstance)other;
for ( DFieldMeta field: recordMeta.getFields() )
if ( field.isPrimaryKey() ) {
Object val1 = getObject(field);
if ( val1 == null )
throw new DException("Null Primary Key " + this);
Object val2 = otherRec.getObject(field);
if ( ! val1.equals(val2) ) return false;
}
return true;
}
/** Of the primary keys only. */
public int hashCode() {
int hash = 0;
for ( DFieldMeta field: recordMeta.getFields() ) {
if ( field.isPrimaryKey() ) {
Object val1 = getObject(field);
if ( val1 == null )
throw new DException("Null Primary Key " + this);
hash = (hash<<13) + hash + val1.hashCode(); // Java doesn;t detect int overflow.
}
}
return hash;
}
/** Hack, and badly implemented (key could contain "~"). */
public String hackPrimaryKeyString() {
String pkey="";
for ( DFieldMeta field: recordMeta.getFields() )
if ( field.isPrimaryKey() )
pkey += getObject(field) + "~"; // hack
return pkey;
}
public String toString(){
StringBuilder buf = new StringBuilder("{"+ recordMeta.getTableName() + " ");
for ( DFieldMeta field: recordMeta.getFields() )
if ( field.isPrimaryKey() ) {
buf.append(getObject(field)+"");
buf.append(", ");
}
buf.append("}");
return buf.toString();
}
public String toLongString() {
try {
StringBuilder buf = new StringBuilder("{ "+ recordMeta.getTableName() + " ");
for ( Object propName: PropertyUtils.describe(bean).keySet() ) {
buf.append(getObject((String)propName) + "");
buf.append(", ");
}
buf.append("}");
return buf.toString();
} catch (Exception ex) {throw new DException(ex);}
}
/** Called whenever the record is updated or inserted, override in subtypes.
* Mainly used to validate. Use onPostUpSert to update related tables.
*/
public void onPreUpSert(DConnection connection, QueryMode mode) {}
public enum QueryMode {INSERT, UPDATE}
///////////////////////////
public DRecordMeta getRecordMeta() {
return recordMeta;
}
}
|