/*
* Copyright (c) 2000-2006 ASP Converters Pty Ltd.
*
* www.aspconverters.com.au
*
* All Rights Reserved.
*
* This software is the proprietary information of
* ASP Converters Pty Ltd.
* Use is subject to license terms.
*/
package com.aspc.DBObj;
import org.apache.commons.logging.Log;
import com.aspc.message.DBMessage;
import com.aspc.DBObj.Contact.Login;
import com.aspc.DBObj.Archive.*;
import com.aspc.DBObj.Errors.*;
import com.aspc.DBObj.Formula.DBFieldQuery;
import com.aspc.DBObj.Formula.DBFormula;
import com.aspc.DBObj.Internal.*;
import com.aspc.DBObj.Internal.DataLoader.LazyLoadValue;
import com.aspc.DBObj.Internal.DataLoader.LinkedValue;
import com.aspc.DBObj.Internal.DataLoader.StoredArrayValue;
import com.aspc.DBObj.Internal.Helper.DBObjectHelper;
import com.aspc.DBObj.Internal.Holders.PossibleRowsHolder;
import com.aspc.DBObj.Language.*;
import com.aspc.DBObj.Language.Internal.MutableMultiLingualValue;
import com.aspc.DBObj.Language.Internal.ReadOnlyMultiLingualValue;
import com.aspc.DBObj.Listeners.ReloadEventListener;
import com.aspc.DBObj.Query.DBCriteria;
import com.aspc.remote.database.InvalidDataException;
import com.aspc.remote.database.NotFoundException;
import com.aspc.remote.database.DeletedRecordException;
import com.aspc.remote.database.NullValueException;
import com.aspc.remote.database.TooManyRowsException;
import com.aspc.remote.util.misc.CLogger;
import com.aspc.remote.util.misc.StringUtilities;
import com.aspc.remote.util.misc.TimeUtil;
import com.aspc.DBObj.Misc.AutoEnterPredefined;
import com.aspc.Util.Memory.HashLongMap;
import com.aspc.remote.util.misc.ConcurrentDecimalFormat;
import java.lang.ref.WeakReference;
import java.util.*;
/**
* DBObject is an instance of a DBClass.
* Extend this class to add functionality to Super-Tracker
* The class represents a single row in the database. Each datasource will generate a
* new instance of a DBObject which holds the specific state of this record for a datasource.
*
* MIXED MODE THREADING: When a DBObject is comes from a mutable data source or
* archive data source the DBObject is in SINGLE THREADED mode and is NOT
* shared. When the DBObject is retrieved via a VirtualDB (Read only data source) the DBObject is in
* MULTI-THREADED mode and is shared.
*
* TODO: Create a "SingleThreadDBObject" interface to mark a DBObject as only being able to be accessed in single thread mode.
*
*
*
*
Extending a DBObject |
* |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
* Boolean fields * -------------- * "True|False" or "Sexy|Ugly" or "on|off" or anything separated by a '|' * * Date & Timestamp fields * ----------------------- * We use the standard Java SimpleDateFormat patterns * * Integer and Long fields * ----------------------- * We use the standard Java DecimalFormat patterns *
* * @return The formatted string * @param params The parameters for this field eg. language= or default= * @param field The field to get. * @param specificFormat The format */ public final String getFormattedString( final DBField field, final String specificFormat, final FldParams params) { Object obj; obj = getValue(field, params); if( obj instanceof MultiLingualValue) { MultiLingualValue mlv = (MultiLingualValue)obj; obj = mlv.getText( params); } if( obj == null) return ""; return field.makeFormattedString( ds, obj, specificFormat, params); } /** * Returns the formatted value of the field.* Boolean fields * -------------- * "True|False" or "Sexy|Ugly" or "on|off" or anything separated by a '|' * * Date & Timestamp fields * ----------------------- * We use the standard Java SimpleDateFormat patterns * * Integer and Long fields * ----------------------- * We use the standard Java DecimalFormat patterns *
* * @return The formatted string * @param params The parameters for this field eg. language= or default= * @param name The field name to be formatted * @param specificFormat The format */ public final String getFormattedString(final String name, final String specificFormat, final FldParams params) { DBField field; if( dbClass == null) { return ""; } field = dbClass.getDBField(name); if( field == null) return ""; return getFormattedString(field, specificFormat, params); } /* ============================= Get String =============================== */ /** * Get String * * @param field The field to get. * @return The string value * * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password */ public final String getString( final DBField field) { return getString(field, (FldParams)null); } /** * Get String * * @param params The parameters for this field eg. language= or default= * @param field The field to get. * @return The string value * * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password */ public final String getString( final DBField field, final String params) { FldParams theParams = null; if( params != null) { if( params.indexOf( "=") != -1) { theParams = new FldParams( params); return getString( field, theParams); } } String temp = getString( field, (FldParams)null); if( StringUtilities.isBlank( temp)) { return params; } return temp; } /** * Get String * * @return The string value * @param name The name of the field * @param params The parameters for this field eg. language= or default= * * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password */ public final String getString( final String name, final String params) { return getString( dbClass.getDBField(name), params); } /** * Get String * * @return The string value * @param params The parameters for this field eg. language= or default= * @param field The field to get. * * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password */ public final String getString( final DBField field, final FldParams params) { Object obj; obj = getValue(field, params); /* Ok so we have a multi lingual field result. */ if( obj instanceof MultiLingualValue) { MultiLingualValue mlv = (MultiLingualValue)obj; obj = mlv.getText( params); } if( obj instanceof String) { if( "".equals( obj)) { obj = null; } else { return (String)obj; } } if( obj == null) { if( params != null) { return params.getDefaultString(ds); } return ""; } return field.makeString( ds, obj); } /** * Get String * * @param name The name of the field * @return The string value * * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password */ public final String getString(final String name) { return getString( dbClass.getDBField( name), (FldParams)null); } /** * Get String * * @return The string value * @param params The parameters for this field eg. language= or default= * @param name The name of the field * * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password */ public final String getString(final String name, final FldParams params) { return getString( dbClass.getDBField(name), params); } /* ============================ Get Int ================================== */ /** * Get Int * * @param field The field to get. * @return The int value * * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password */ public final int getInt( final DBField field) { return getInt(field, null); } /** * Get Int * * @return The int value * @param defaultValue The default value * @param field The field to get. * * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password */ public final int getInt( final DBField field, final int defaultValue) { FldParams params = null; if( defaultValue != 0) { params = new FldParams( defaultValue); } return getInt(field, params); } /** * Get Int * * @param name The field name * @param defaultValue the default value * @return The int value * * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password */ public final int getInt( final String name, final int defaultValue) { return getInt( dbClass.getDBField( name), defaultValue); } /** * * Get Int * @return The int value * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password * @param name The field name * @param params The parameters for this field eg. language= or default= */ public final int getInt(final String name, final FldParams params) { return getInt(dbClass.getDBField( name), params); } /** * Get Int * * @param name The field Name * @return The int value * * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password */ public final int getInt(final String name) { return getInt( dbClass.getDBField( name), null); } /** * * Get Int * @return The int value * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password * @param field The field * @param params The parameters for this field eg. language= or default= */ public final int getInt( final DBField field, final FldParams params) { Object obj; obj = getValue(field, params); long value; if( obj instanceof Number) { value = ((Number)obj).longValue(); } else { if( StringUtilities.isBlank(obj)) { if( params == null) return 0; return params.getDefaultInt(); } try { value = Integer.parseInt(obj.toString()); } catch( NumberFormatException nf) { LOGGER.warn( "getInt( " + field + ")", nf); if( params == null) return 0; return params.getDefaultInt(); } } if( value > Integer.MAX_VALUE || value < Integer.MIN_VALUE) { LOGGER.warn( "Warning: Long {" + value + "}->Int {" + ((int)value) + "}"); Thread.dumpStack(); } return (int)value; } /* ============================ Get Double ================================== */ /** * Get Double * * @param field The field to get. * @return The double value * * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password */ public final double getDouble( final DBField field) { return getDouble(field, 0.0); } /** * Get Double * @return The double value * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password * @param name The field name * @param defaultValue The default value. */ public final double getDouble(final String name, final double defaultValue) { return getDouble( dbClass.getDBField( name), defaultValue); } /** * Get Double * * @param name The name of the field * @return The double value * * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password */ public final double getDouble(final String name) { return getDouble( dbClass.getDBField( name), 0); } /** * Get Double * @return The double value * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password * @param field The field * @param defaultValue The default value for the field. */ public final double getDouble( final DBField field, final double defaultValue) { Object obj; obj = getValue(field, null); if( obj instanceof Number) { return ((Number)obj).doubleValue(); } return defaultValue; } /* ============================ Get Long ================================== */ /** * Get Long * * @param field The field to get. * @return The long value * * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password */ public final long getLong( final DBField field) { return getLong(field, 0); } /** * Get Long * @return The long value * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password * @param name The field name * @param defaultValue The default value for the field */ public final long getLong(final String name, final long defaultValue) { return getLong(dbClass.getDBField( name), defaultValue); } /** * Get Long * * @param name The field name * @return The long value * * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password */ public final long getLong(final String name) { return getLong( dbClass.getDBField( name), 0); } /** * Get Long * @return The long value * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password * @param field The field * @param defaultValue The default value. */ public final long getLong( final DBField field, final long defaultValue) { Object obj; obj = getValue(field); if( obj instanceof Number) { return ((Number)obj).longValue(); } return defaultValue; } /* ============================ Get Boolean ================================== */ /** * Get Boolean * * @param field The field to get. * @return The boolean value * * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password */ public final boolean getBoolean( final DBField field) { return getBoolean(field, false); } /** * Get Boolean * * @param field The field to get. * @param flag The default value * @return The boolean value * * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password */ public final boolean getBoolean( final DBField field, final boolean flag) { Object obj; obj = getValue(field, null); if( obj == null) return flag; return ((Boolean)obj).booleanValue(); } /** * The boolean value * @param field The field * @param params The parameters * @return The value */ public final boolean getBoolean( final DBField field, final FldParams params) { Object obj; obj = getValue(field, params); if( obj == null) return false; return ((Boolean)obj).booleanValue(); } /** * The boolean value for a field * @param name The field name * @param params The parameters * @return The boolean value */ public final boolean getBoolean( final String name, final FldParams params) { Object obj; obj = getValue( dbClass.getDBField(name), params); if( obj == null) return false; return ((Boolean)obj).booleanValue(); } /** * Get Boolean * * @param name The field name * @return The boolean value * * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password */ public final boolean getBoolean(final String name) { return getBoolean( dbClass.getDBField(name), false); } /** * Get Boolean * * @param name The Field Name * @param flag The default value * @return The boolean value * * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password */ public final boolean getBoolean(final String name, final boolean flag) { return getBoolean(dbClass.getDBField(name), flag); } /* ============================ Get Date ================================== */ /** * Get Date * * @param field The field to get. * @return The Date value * * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password */ public final Date getDate( final DBField field) { return getDate(field, null); } /** * Get Date * * @param field The field to get. * @param theDate The default value * @return The date value * * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password */ public final Date getDate( final DBField field, final Date theDate) { Object obj; obj = getValue(field, null); if( obj instanceof Date) { return (Date)obj; } return theDate; } /** * Get Date * * @param name The field name * @return The date value * * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password */ public final Date getDate(final String name) { return getDate( dbClass.getDBField(name), null); } /** * Get Date * * @param name The Field Name * @param theDate The default value * @return The date value * * @see #extGetValue(DBField, FldParams) extGetValue() To filter public accessible values eg. **** for a password */ public final Date getDate(final String name, final Date theDate) { return getDate(dbClass.getDBField(name), theDate); } /* ============================ Get Raw Value ================================== */ /** * Returns the raw value for this field from the underlying DBData or the updated fields. * * @param fieldId The field's global key * @return The raw value */ public final Object getRawValue(final GlobalKey fieldId) { try { return getRawValue( dbClass.getDBField(fieldId)); } catch(Exception e) { LOGGER.error( "getRawValue(" + fieldId + ")",e); return null; } } /** * Returns the raw value for this field from the underlying DBData or the updated fields. * * @param field The field to get the raw value. * @return The Raw value. */ public final Object getRawValue( final DBField field) { if( field.isRuntimeEval()) return null; return iGetRawValue( field); } /* ============================ Get Original Value ================================== */ /** * Returns the original value for this field from the underlying DBData. * * @param fieldKey The field key * @return The original value. */ public final Object getOriginalValue(final GlobalKey fieldKey) { try { DBField field = dbClass.getDBField(fieldKey); return getOriginalValue( field); } catch(Exception e) { LOGGER.error( "getOriginalField(" + fieldKey + ")",e); return null; } } /** * Returns the original value for this field from the underlying DBData. * * @param field The field to get the raw value. * @return The original value. */ public final Object getOriginalValue( final DBField field) { if( data != null && field != null) { return data.getRawValue(ds.getDataBase(), field, null); } return null; } /** * Returns the original key for this field from the underlying DBData. * * @param field The field to get the raw value. * @return The original value. */ public final GlobalKey getOriginalKey( final DBField field) { if( data != null) { return data.getGlobalKey(ds.getDataBase(), field, null); } return null; } /*====================================================================================================*/ /*===== UTILITIES METHODS =====*/ /*====================================================================================================*/ /** * Copies the fields from another DBObject into this one. * fields such as derived and keys are ignored * * @param orig The original object to be copied. * @throws Exception A serious error. */ public final void copyFields( final DBObject orig) throws Exception { boolean originalFlag = getDisableOnChangeEvent(); setDisableOnChangeEvent( true); // Find common dbClass DBClassConcrete commonClass = null; // Search through class heirachy for both this class and original // to find which class is the same DBClassConcrete c1, c2; c1 = dbClass; while( c1 != null && commonClass == null) { c2 = orig.dbClass; while( c2 != null && commonClass == null) { if( c1.getGlobalKey().equals( c2.getGlobalKey())) { commonClass = c1; } c2 = c2.getParentDBClassConcrete(); } c1 = c1.getParentDBClassConcrete(); } if( commonClass == null) { throw new RuntimeException(); } /* Copy Fields */ DBField[] list = commonClass.getDBFieldListAll(); for(int f=0; f < list.length; f++) { DBField field = list[f]; if(copyIncludeField(orig, field)) { if( field.isIncremental() == false && field.isDeleted() == false && field.isRuntimeEval() == false && field.isKey() == false && field.isUnique() == false && StringUtilities.isBlank(field.getAutoFillPredefinedValue()) ) { Object o; o = orig.getGlobalKey( field); if( o == null) { o = orig.getValue( field); } setValue( field, o); } } } setDisableOnChangeEvent( originalFlag); } /** * To filter the field's not to copy. It can be overriden to add additional funcionality. * @param orig The original object to be copied. * @param field The field to be copied * @return false if the field is not allowed to copy. * @throws Exception A serious error. */ public boolean copyIncludeField( final DBObject orig, final DBField field) throws Exception { return true; } /** * Copies the objects pointing to this object. * @param orig The reference object * @param linkedField The Linked Field ? * @throws Exception A serious problem * @return The objects */ public final DBObject[] copyInwardLinks( final DBObject orig, final DBField linkedField) throws Exception { DBResult res = orig.getInwardLinkage( linkedField, null); ArrayList array = new ArrayList(); MutableDataSource mds = (MutableDataSource)ds; while( true) { DBObject origLink = res.next(); if( origLink == null) break; DBObject o = origLink.copy( mds); o.setValue( linkedField, getGlobalKey()); array.add( o); } DBObject[] list = new DBObject[ array.size()]; array.toArray( list); return list; } /** * Mark the save point which we can rollback to later. * @param id the save point id * @throws com.aspc.DBObj.Errors.NotInUniverseException DBObject had not been touched */ public final void markSavePoint( final String id) throws NotInUniverseException { if( helper == null) { throw new NotInUniverseException( "Not part of the universe"); } DBObjectHelper oldHelper = helper; helper = oldHelper.makeSavePoint( id); MutableArrayValue list[] = MutableArrayValue.list(this); if( list != null && list.length > 0) { for( int i = 0; i < list.length; i++) { MutableArrayValue mav = list[i]; if( mav.isSaved() == false) { mav.setSavePointHelper( this, mav.getField(), helper, oldHelper); } } } extMarkSavePoint( id); } /** * Rollback to save point. * * @param id the save point id * @throws NoSavePointException no save point found */ public final void rollbackTo( final String id) throws NoSavePointException { if( helper != null) { helper = helper.rollbackTo( id); } MutableArrayValue list[] = MutableArrayValue.list(this); if( list != null && list.length > 0) { if( helper == null) { helper = new DBObjectHelper(this); } for( int i = 0; i < list.length; i++) { MutableArrayValue mav = list[i]; if( mav.isSaved() == false) { mav.setSavePointHelper( this, mav.getField(), helper, null); } } } extRollbackTo( id); } /** * DEBUG dump of the current object's fields values to std. out */ public final void dump() { DBField list[] = dbClass.getDBFieldListAll(); String temp = ""; if( isNew()) { temp = " (NEW)"; } if( isDeleted()) { temp = " (DELETED)"; } LOGGER.info( dbClass.getName() + ":" + getGlobalKey() + temp); LOGGER.info( " |"); for( int i = 0; i < list.length; i++) { LOGGER.info( " +-> " + list[i].getName()); if( i + 1 != list.length) { LOGGER.info( " |"); } else { LOGGER.info( " "); } LOGGER.info( " =" + getString(list[i])); if( list[i].isLinked()) { if( i + 1 != list.length) { LOGGER.info( " |"); } else { LOGGER.info( " "); } LOGGER.info( " IS " + getGlobalKey(list[i])); } } } /*====================================================================================================*/ /*===== INTERNAL PUBLIC FUNCTIONS =====*/ /*====================================================================================================*/ /** * INTERNAL USE ONLYextGetValue
method the SAME value should be return.
* Examples of use are to blank fields that you don't have access to or to return ***** instead of the password. The
* database search uses getPureField which is final so you could do a search for a field value
* even if it is being blanked. Real security can only be given by creating an associated record
* and supplying a ACL to restrict access to it.
*
* @return The value of the field.
*
* @param params The parameters for this field eg. language= or default=
* @param field The field to get
*/
protected Object extGetValue(final DBField field, final FldParams params)
{
return getPureValue( field, params);
}
/**
* The extended fix up routine
* @throws Exception a serious problem
*/
protected void extFixUp() throws Exception
{
//#DEV_ONLY_START
extFixUpCalled = true;
//#DEV_ONLY_END
}
/**
* Extend this method to add functionality when a new DBObject is created.setIsAutoEntered(true)
* so that system does not misunderstand that this object is changed by user.
*
* @throws Exception A serious problem
*/
protected void extAutoEnterCreate() throws Exception
{
//#DEV_ONLY_START
extAutoEnterCreateCalled = true;
//#DEV_ONLY_END
}
/**
* Extend this method to add validation to a record then deleted.
*
* @param list The validation list
*
* @throws Exception A serious problem
*/
protected void extValidateDelete(final ValidationList list) throws Exception
{
//#DEV_ONLY_START
extValidateDeleteCalled = true;
//#DEV_ONLY_END
}
/**
* Additional functionality when an object is marked for deletion by calling delete().
*
* @throws Exception A serious problem
*/
protected void extDelete() throws Exception
{
//#DEV_ONLY_START
extDeleteCalled = true;
//#DEV_ONLY_END
}
/**
* Additional functionality when an object is undeleted.
*
* @throws Exception A serious problem
*/
protected void extUndelete() throws Exception
{
//#DEV_ONLY_START
extUndeleteCalled = true;
//#DEV_ONLY_END
}
/**
* Additional functionality when an object is copied.
*
* @param target the target object
*
* @throws Exception A serious problem
*/
protected void extCopy( final DBObject target) throws Exception
{
//#DEV_ONLY_START
extCopyCalled = true;
//#DEV_ONLY_END
}
/**
* Additional access checking for create access of this object.
*
* @throws DBAccessException No access to create
*/
protected void extCheckCreateAccess() throws DBAccessException
{
//#DEV_ONLY_START
extCheckCreateAccessCalled = true;
//#DEV_ONLY_END
}
/**
* Additional access checking for delete access of this object.
*
* @throws DBAccessException No access to delete
*/
protected void extCheckDeleteAccess() throws DBAccessException
{
//#DEV_ONLY_START
extCheckDeleteAccessCalled = true;
//#DEV_ONLY_END
}
/**
* Additional access checking for read access of this object.
*
* @throws DBAccessException No access to read
*/
protected void extCheckReadAccess() throws DBAccessException
{
//#DEV_ONLY_START
boolean extCheckReadAccessCalled[] = (boolean[])localExtCheckReadAccessCalled.get();
if( extCheckReadAccessCalled != null)
{
extCheckReadAccessCalled[0] = true;
}
//#DEV_ONLY_END
}
/**
* Additional access checking for write access of this object.
*
* @throws DBAccessException No access to modify
*/
protected void extCheckModifyAccess() throws DBAccessException
{
//#DEV_ONLY_START
extCheckModifyAccessCalled = true;
//#DEV_ONLY_END
}
/**
* Additional access checking for write access for a field of this object.
*
* @param field Can we change this field ?
* @throws DBAccessException No access to change
*/
protected void extCheckModifyAccess(final DBField field) throws DBAccessException
{
//#DEV_ONLY_START
extCheckModifyAccessCalled = true;
//#DEV_ONLY_END
}
/**
* OVERRIDE this method to add functionallity to Super-Tracker BEFORE saving the record to the database.
*
* At this stage the final validation ( internally called by save) has NOT been performed. This is your chance to
* create other associated records etc. This method is called for all created and modified records NOT deleted.
* The database transaction has not been started yet. Your changes will NOT be rollback in case of failure.
*
* @throws Exception A Serious problem
*/
protected void extPreSaveRecord() throws Exception
{
//#DEV_ONLY_START
extPreSaveRecordCalled = true;
//#DEV_ONLY_END
}
/**
* OVERRIDE this method to add functionality to Super-Tracker BEFORE deleting a record from the datbase.
*
* At this stage the final validation ( internally called by save) has NOT been performed. This is your chance to
* create other associated records etc. This method is called for all created and modified records NOT deleted.
* The database transaction has not been started yet. Your changes will NOT be rollback in case of failure.
*
* @throws Exception A Serious problem
*/
protected void extPreDeleteRecord() throws Exception
{
//#DEV_ONLY_START
extPreDeleteRecordCalled = true;
//#DEV_ONLY_END
}
/**
* OVERRIDE this method to add functionality to Super-Tracker WHILE deleting the record from the database.
*
* At this stage we are within a database transaction. YOU MAY NOT CHANGE THE UNIVERSE AT THIS STAGE.
*
* @param transNr This transaction number that was just saved.
* @throws Exception A serious Error
*/
protected void extDeleteRecord( final long transNr) throws Exception
{
//#DEV_ONLY_START
extDeleteRecordCalled = true;
//#DEV_ONLY_END
}
/**
* OVERRIDE this method to add functionality to Super-Tracker WHILE saving the record to the database.
*
* At this stage we are within a database transaction. YOU MAY NOT CHANGE THE UNIVERSE AT THIS STAGE.
*
* @param transNr This transaction number that was just saved.
* @throws Exception A serious Error
*/
protected void extSaveRecord( final long transNr) throws Exception
{
//#DEV_ONLY_START
extSaveRecordCalled = true;
//#DEV_ONLY_END
}
/**
* OVERRIDE this method to add functionality to Super-Tracker AFTER deleting the record from the database.
*
* At this stage the database transaction has been committed. YOU MAY NOT CHANGE THE UNIVERSE AT THIS STAGE.
*
* @param transNr This transaction number that was just saved.
*/
protected void extPostDeleteRecord( final long transNr)
{
//#DEV_ONLY_START
extPostDeleteRecordCalled = true;
//#DEV_ONLY_END
}
/**
* OVERRIDE this method to add functionality to Super-Tracker AFTER saving the record to the database.
*
* At this stage the database transaction has been committed. YOU MAY NOT CHANGE THE UNIVERSE AT THIS STAGE.
*
* @param transNr This transaction number that was just saved.
*/
protected void extPostSaveRecord( final long transNr)
{
//#DEV_ONLY_START
extPostSaveRecordCalled = true;
//#DEV_ONLY_END
}
/**
* When the underlying DBData is changed/ loaded. This may be call via other
* threads/servers saving the object.
*