package Express.services;
import java.io.Serializable;
import DisplayProject.binding.beans.Observable;
import Express.services.interfaces.IBusinessMgr;
import Express.services.interfaces.IBusinessServiceMgr;
import Framework.Constants;
import Framework.DataValue;
import Framework.Mutex;
import Framework.RuntimeProperties;
import Framework.ServiceObjectContext;
import GenericDBMS.TransactionMgr;
/**
* The BusinessServiceMgr class accepts select and update requests from BusinessClient class objects and sends them to the BusinessMgr of the appropriate subclass. The BusinessServiceMgr maintains a list of all the BusinessMgr objects contained within the BusinessService being managed by the current BusinessServiceMgr object.
* <p>
* @author ITerative Consulting
* @since 26-Feb-2008
*/
@RuntimeProperties(isDistributed=true, isAnchored=true, isShared=false, isTransactional=false)
@SuppressWarnings("serial")
public class BusinessServiceMgr
extends BusinessMgr
implements Serializable, Observable, IBusinessServiceMgr
{
// ----------
// Attributes
// ----------
private ServiceConcurrency concurrency;
private Mutex initLock;
private Array_Of_IBusinessMgr<IBusinessMgr> managers;
private SqlStatementCache statementCache;
// ------------
// Constructors
// ------------
public BusinessServiceMgr() {
// Explicitly call the superclass constructor to prevent the implicit call
super();
this.setInitLock(new Framework.Mutex());
this.setTrace(new Trace());
this.getTrace().setDefaultServiceID(Constants.SP_ST_EX);
this.setup((Array_Of_IBusinessMgr<IBusinessMgr>)null);
}
public BusinessServiceMgr(ServiceObjectContext pContext) {
super(pContext);
}
// ----------------------
// Accessors and Mutators
// ----------------------
public void setConcurrency(ServiceConcurrency concurrency) {
ServiceConcurrency oldValue = this.concurrency;
this.concurrency = concurrency;
this.qq_Listeners.firePropertyChange("concurrency", oldValue, this.concurrency);
}
public ServiceConcurrency getConcurrency() {
return this.concurrency;
}
public void setInitLock(Mutex initLock) {
Mutex oldValue = this.initLock;
this.initLock = initLock;
this.qq_Listeners.firePropertyChange("initLock", oldValue, this.initLock);
}
public Mutex getInitLock() {
return this.initLock;
}
public void setManagers(Array_Of_IBusinessMgr<IBusinessMgr> managers) {
Array_Of_IBusinessMgr<IBusinessMgr> oldValue = this.managers;
this.managers = managers;
this.qq_Listeners.firePropertyChange("managers", oldValue, this.managers);
}
public Array_Of_IBusinessMgr<IBusinessMgr> getManagers() {
return this.managers;
}
public void setStatementCache(SqlStatementCache statementCache) {
SqlStatementCache oldValue = this.statementCache;
this.statementCache = statementCache;
this.qq_Listeners.firePropertyChange("statementCache", oldValue, this.statementCache);
}
public SqlStatementCache getStatementCache() {
return this.statementCache;
}
// -------
// Methods
// -------
/**
* afterSelect<p>
* AfterSelect<br>
* AfterSelect gets executed by the SelectQueries method after performing<br>
* the select against the server. The generic method, i.e. this method<br>
* is always empty. You may override this method in the custom class<br>
* to provide implementation for any actions you want performed after<br>
* the select is done.<br>
* <p>
* queries<br>
* The queries parameter passed to this method is the queries parameter<br>
* passed to the SelectQueries method.<br>
* <p>
* transactionMode<br>
* The transactionMode parameter passed to this method is the<br>
* transactionMode parameter passed to the SelectQueries method.<br>
* <p>
* result<br>
* The result parameter contains the array of BusinessClasses the<br>
* SelectQueries method is about to return. Any changes made to it will<br>
* affect the classes actually returned from Select.<br>
* <p>
* @param queries Type: Array_Of_BusinessQuery<BusinessQuery>
* @param transactionMode Type: int
* @param result Type: Array_Of_BusinessClass<BusinessClass>
*/
public void afterSelect(Array_Of_BusinessQuery<BusinessQuery> queries, int transactionMode, Array_Of_BusinessClass<BusinessClass> result) {
}
/**
* afterUpdate<p>
* AfterUpdate<br>
* AfterUpdate gets executed by the Update method after performing<br>
* the update against the server. The generic method, i.e. this method<br>
* is always empty. You may override this method in the custom class<br>
* to provide implementation for any actions you want performed after<br>
* the update is done.<br>
* <p>
* queries<br>
* The queries parameter contains the array of BusinessQuerries passed<br>
* to the Update method.<br>
* <p>
* transactionMode<br>
* The transactionMode parameter passed to this method is the<br>
* transactionMode parameter passed to the Update method.<br>
* <p>
* @param queries Type: Array_Of_BusinessQuery<BusinessQuery>
* @param transactionMode Type: int
*/
public void afterUpdate(Array_Of_BusinessQuery<BusinessQuery> queries, int transactionMode) {
}
/**
* beforeSelect<p>
* BeforeSelect<br>
* BeforeSelect gets executed by the Select method before performing<br>
* the select against the database. The generic method, i.e. this method<br>
* is always empty. You may override this method in the custom class<br>
* to provide implementation for any actions you want performed before<br>
* the select is done.<br>
* <p>
* queries<br>
* The queries parameter passed to this method is the queries parameter<br>
* passed to the SelectQueries method. Any changes made to it will<br>
* affect the query actually performed.<br>
* <p>
* transactionMode<br>
* The transactionMode parameter passed to this method is the<br>
* transactionMode parameter passed to the Select method.<br>
* <p>
* @param queries Type: Array_Of_BusinessQuery<BusinessQuery>
* @param transactionMode Type: int
*/
public void beforeSelect(Array_Of_BusinessQuery<BusinessQuery> queries, int transactionMode) {
}
/**
* beforeUpdate<p>
* BeforeUpdate<br>
* BeforeUpdate gets executed by the Update method before performing<br>
* the update against the server. The generic method, i.e. this method<br>
* is always empty. You may override this method in the custom class<br>
* to provide implementation for any actions you want performed before<br>
* the update is done.<br>
* <p>
* queries<br>
* The queries parameter contains the array of BusinessQuerries passed<br>
* to the Update method. Any changes made to it will affect the<br>
* classes actually updated by Update.<br>
* <p>
* transactionMode<br>
* The transactionMode parameter passed to this method is the<br>
* transactionMode parameter passed to the Update method.<br>
* <p>
* @param queries Type: Array_Of_BusinessQuery<BusinessQuery>
* @param transactionMode Type: int
*/
public void beforeUpdate(Array_Of_BusinessQuery<BusinessQuery> queries, int transactionMode) {
}
/**
* getClientConcurrency<p>
* GetClientConcurrency<br>
* The GetClientConcurrency method returns a ClientConcurrency object<br>
* initialized for the concurrency mode being practiced by this<br>
* BusinessServiceMgr. Every BusinessClient will need to get one.<br>
* <p>
* @return ClientConcurrency
*/
public ClientConcurrency getClientConcurrency() {
return this.getConcurrency().getClientConcurrency();
}
/**
* getMgr<p>
* GetMgr<br>
* The GetMgr method returns the BusinessMgr which this BusinessServiceMgr<br>
* is using to process queries of the sub-class of the passed query<br>
* parameter.<br>
* <p>
* query<br>
* The query parameter hold a BusinessQuery of a custom sub-class<br>
* for which the associated BusinessMgr is needed.<br>
* <p>
* @param query Type: BusinessQuery
* @return BusinessMgr
*/
public IBusinessMgr getMgr(BusinessQuery query) {
int mgrID = query.getMgrID();
if (mgrID < 1 || mgrID > this.getManagers().size()) {
throw new Error(Error.BS_ILLEGAL_BM, "GetMgr", this, query, Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
}
else if (this.getManagers().get(mgrID-1) == null) {
throw new Error(Error.BS_UNKNOWN_BM, "GetMgr", this, query, Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
}
return this.getManagers().get(mgrID-1);
}
/**
* newKey<p>
* NewKey<br>
* The NewKey method fills in the key attributes of a BusinessClass by<br>
* requesting one from its associated BusinessMgr.<br>
* <p>
* source<br>
* The source parameter holds the BusinessClass which is to get a<br>
* new key.<br>
* <p>
* @param source Type: BusinessClass
*/
public void newKey(BusinessClass source) {
this.getMgr(source.newQuery()).newKey(source);
}
/**
* selectQueries<p>
* Select<br>
* The Select method uses each BusinessQuery in the query parameter to<br>
* prepare an SQL query to retrieve data from the database. All the rows<br>
* for each query thus generated are placed into separate business<br>
* entities, stuffed into an array and returned to the caller.<br>
* <p>
* The concurrency object is notified that a transaction should begin<br>
* before the select is performed and all rows are registered with the<br>
* concurrency object after the select is complete.<br>
* <p>
* clientID<br>
* The clientID parameter identifies the client issuing the Select.<br>
* <p>
* queries<br>
* The queries parameter contains one or more BusinessQuerries to be<br>
* run.<br>
* <p>
* transactionMode<br>
* The transactionMode parameter specifies whether this select starts<br>
* a new transaction, which is the default, or continues one already<br>
* in progress. See BusinessClient.Select for legal values.<br>
* <p>
* @param clientID Type: int
* @param queries Type: Array_Of_BusinessQuery<BusinessQuery>
* @param transactionMode Type: int (Copy Input) (default in Forte: 1)
* @return Array_Of_BusinessClass<BusinessClass>
*/
@SuppressWarnings("deprecation")
public Array_Of_BusinessClass<BusinessClass> selectQueries(int clientID, Array_Of_BusinessQuery<BusinessQuery> queries, int transactionMode) {
Array_Of_BusinessClass<BusinessClass> result = null;
Array_Of_BusinessClass<BusinessClass> previousResult = null;
this.getTrace().setup(Trace.ES_SELECT);
TransactionMgr.beginDependentTransaction();
try {
this.getInitLock().lock();
if (this.getConcurrency() != null) {
this.getConcurrency().startTrans(clientID, transactionMode);
}
this.beforeSelect(queries, transactionMode);
//
// Run SQLselect for each query in the array.
//
if (queries != null) {
for (BusinessQuery q : queries) {
if ((q != null) && (q.getOperation() == BusinessQuery.OP_SELECT)) {
//
// If last time through we got a result we had better remember it
// because we are going to get another result this time.
//
if (result != null) {
if (previousResult == null) {
previousResult = result;
}
else {
if (result != null) {
for (BusinessClass r : result) {
previousResult.add(r);
}
}
}
}
if ((this.getConcurrency().getConcurrencyMode()&ConcurrencyMgr.CO_MASK_LOCK) > 0) {
q.addConstraint(ConstraintOperation.OP_FOR_UPDATE, (DataValue)null);
}
result = this.getMgr(q).select(q);
}
}
}
if (result != null) {
//
// We have results, if we have any previous results put them together.
//
if (previousResult != null) {
if (result != null) {
for (BusinessClass r : result) {
previousResult.add(r);
}
}
result = previousResult;
}
//
// Time to tell the concurrency manager what we fetched from the
// database.
//
if (this.getConcurrency() != null) {
// RESOLVE: need to skip this if we got a cache hit
this.getConcurrency().load(clientID, transactionMode, result);
}
this.afterSelect(queries, transactionMode, result);
}
this.getInitLock().unlock();
}
catch (RuntimeException e) {
TransactionMgr.setRollback();
this.getInitLock().unlock();
throw (RuntimeException)e;
}
finally {
TransactionMgr.endTransaction();
}
return result;
}
/**
* setConcurrency<p>
* SetConcurrency<br>
* The SetConcurrency method is used to initialize this BusinessServiceMgrs<br>
* ServiceConcurrency object to the concurrency policy which should be<br>
* enforced by this BusinessServiceMgr. The method is invoked by the<br>
* generated Setup method.<br>
* <p>
* parentService<br>
* The parentService parameter specifies who our root<br>
* BusinessServiceMgr is. It's usually us.<br>
* <p>
* concurrencyMode<br>
* The concurrencyMode parameter specifies the concurrency policy<br>
* we should use.<br>
* <p>
* concurrencyMgr<br>
* The concurrencyMgr parameter specifies an external concurrency<br>
* manager, if any, needed to enforce our concurrency policy.<br>
* <p>
* cacheMode<br>
* The cacheMode parameter specifies the caching policy desired.<br>
* <p>
* @param parentService Type: BusinessServiceMgr
* @param concurrencyMode Type: int
* @param concurrencyMgr Type: ConcurrencyMgr (Input) (default in Forte: NIL)
* @param cacheMode Type: int (Input) (default in Forte: 0)
*/
public void setConcurrency(IBusinessServiceMgr parentService, int concurrencyMode, ConcurrencyMgr concurrencyMgr, int cacheMode) {
this.getConcurrency().setConcurrency(parentService, concurrencyMode, concurrencyMgr, 0);
}
/**
* updateQueries<p>
* Update<br>
* The Update method uses each BusinessQuery in the query parameter to<br>
* prepare an SQL query to update data in the database.<br>
* <p>
* The concurrency object is notified that a transaction may be committed<br>
* before the update is performed. After the update is complete the<br>
* concurrency object is again notified as to its success so it can<br>
* commit or rollback.<br>
* <p>
* clientID<br>
* The clientID parameter identifies the client issuing the Update.<br>
* <p>
* query<br>
* The query parameter contains one or more BusinessQuerries to be<br>
* run.<br>
* <p>
* transactionMode<br>
* The transactionMode parameter specifies whether this update ends<br>
* the transaction, which is the default, or leaves the transaction in<br>
* progress. See BusinessClient.Update for legal values.<br>
* <p>
* @param clientID Type: int
* @param queries Type: Array_Of_BusinessQuery<BusinessQuery>
* @param transactionMode Type: int (Copy Input) (default in Forte: 0)
*/
public void updateQueries(int clientID, Array_Of_BusinessQuery<BusinessQuery> queries, int transactionMode) {
this.getTrace().setup(Trace.ES_UPDATE);
TransactionMgr.beginDependentTransaction();
if (this.getConcurrency() != null) {
// Ask the concurrency manager if its OK to do the update. He will
// raise an exception if it isn't.
//
this.getConcurrency().readyToCommit(clientID, transactionMode, queries);
}
try {
this.getInitLock().lock();
this.beforeUpdate(queries, transactionMode);
if (queries != null) {
for (BusinessQuery q : queries) {
this.getMgr(q).update(q);
}
}
this.afterUpdate(queries, transactionMode);
this.getInitLock().unlock();
}
catch (Throwable qq_ElseException) {
this.getInitLock().unlock();
if (this.getConcurrency() != null) {
this.getConcurrency().rollback(clientID, transactionMode, queries);
}
throw (RuntimeException)qq_ElseException;
}
if (this.getConcurrency() != null) {
this.getConcurrency().commitTrans(clientID, transactionMode, queries);
}
TransactionMgr.commitTransaction();
}
} // end class BusinessServiceMgr
// c Pass 2 Conversion Time: 735 milliseconds