/*******************************************************************************
* Copyright (c) 2007, 2014 compeople AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* compeople AG - initial API and implementation
*******************************************************************************/
package org.eclipse.riena.objecttransaction;
import java.lang.reflect.Proxy;
import org.eclipse.riena.objecttransaction.context.BasicContextHolder;
import org.eclipse.riena.objecttransaction.context.ContextProxy;
import org.eclipse.riena.objecttransaction.context.IContextHolder;
import org.eclipse.riena.objecttransaction.context.IObjectTransactionContext;
import org.eclipse.riena.objecttransaction.context.ObjectTransactionContext;
/**
* An abstract superclass simplifying the implementation of application managers
* based on an object transaction.
*
* To ensure that all methods of a concrete manager are running in the context
* of the currently set Transaction IT IS STRONGLY recomended not to provide any
* public contructors. Istead provide a factory method creating the needed Proxy
* by calling cover() on the newly created instance of the manager.
*
* This superclass supports the follwing tasks: * surrounding all functions of
* the manager by a context * surrounding all functions of any object exposed by
* the manager * provides convenience methods for the creation of a new
* transaction
*
* The Transaction to actually work on, has to be provided by a concrete
* subclass. Since the abstract class do not know the business context the
* concrete subclass works on.
*
*/
public abstract class AbstractTransactedManager {
private final IContextHolder contextHolder;
private final IObjectTransactionContext objectTransactionContext;
/**
* Creates a new ObjectTransactionContextManager Initializes the context
* contained.
*
* @param context
*/
protected AbstractTransactedManager() {
super();
this.objectTransactionContext = new ObjectTransactionContext();
this.contextHolder = new BasicContextHolder(objectTransactionContext);
}
/**
* Delgates the Transaction to work on to the contained context. The setting
* of the Transaction is not public per default, thus this method is
* protected. The Object Transaction passed to this method is aktivated
* immediately!
*
* @param pObjectTransaction
* the ObjectTransaction to set.
*/
protected final void setCurrentObjectTransaction(final IObjectTransaction pObjectTransaction) {
objectTransactionContext.setObjectTransaction(pObjectTransaction);
}
/**
* @return the IObjectTransaction beeing current from the point of view of
* the concrete subclass of the manager
*/
protected final IObjectTransaction getCurrentObjectTransaction() {
return objectTransactionContext.getObjectTransaction();
}
/**
* Creates a new ObjectTransaction without setting it current. The
* transaction set from the context will remain.
*
* @return an IObjectTransaction newly created
*/
protected final IObjectTransaction createObjectTransaction() {
// TODO: the object Transaction shold not aktivate itself, talk about
// with cc, this moment the current context is reactivated!
final IObjectTransaction oldTransaction = ObjectTransactionManager.getInstance().getCurrent();
final IObjectTransaction result = ObjectTransactionFactory.getInstance().createObjectTransaction();
ObjectTransactionManager.getInstance().setCurrent(oldTransaction);
return result;
}
/**
* Creates a new SubObjectTransaction relative to the current object
* Transaction.
*
* @return the newly create sub object transaction
*/
protected final IObjectTransaction createSubObjectTransaction() {
final IObjectTransaction cobj = getCurrentObjectTransaction();
IObjectTransaction result = null;
if (cobj != null) {
result = this.createSubObjectTransaction(cobj);
}
return result;
}
/**
* Creates a new SubObjectTransaction without setting it current. The
* transaction set from the context will remain.
*
* @return an IObjectTransaction newly created
*/
protected final IObjectTransaction createSubObjectTransaction(final IObjectTransaction pParentTransaction) {
// TODO: the object Transaction shold not aktivate itself, talk about
// with cc, this moment the current context is reactivated!
final IObjectTransaction oldTransaction = ObjectTransactionManager.getInstance().getCurrent();
final IObjectTransaction result = pParentTransaction.createSubObjectTransaction();
ObjectTransactionManager.getInstance().setCurrent(oldTransaction);
return result;
}
/**
* @param oObject
* the Object to cover with the contained context
* @param <T>
* the Type extected to return
* @return a Context Proxy on any concrete Manager
*/
public final <T> T cover(final T pObject) {
return ContextProxy.cover(pObject, contextHolder);
}
/**
* Uncovers an object from a Context proxy, if the passed object is one
*
* @param <T>
* the extected type
* @param pCovered
* the covered object
* @return
*/
// During uncovering the object will be automatically castet
public final <T> T uncover(final T pCovered) {
T result = null;
if (pCovered != null && Proxy.isProxyClass(pCovered.getClass())
&& (Proxy.getInvocationHandler(pCovered) instanceof ContextProxy)) {
result = (T) ((ContextProxy) Proxy.getInvocationHandler(pCovered)).getService();
} else {
result = pCovered;
}
return result;
}
/**
* Commits the curren transaction if any
*/
public void commit() {
final IObjectTransaction cot = this.getCurrentObjectTransaction();
if (cot != null) {
cot.commit();
}
}
/**
* Roll back the current transaction if any
*/
public void rollback() {
final IObjectTransaction cot = this.getCurrentObjectTransaction();
if (cot != null) {
cot.rollback();
}
}
}