/***
 * Excerpted from "Domain-Driven Design Using Naked Objects",
 * published by The Pragmatic Bookshelf.
 * Copyrights apply to this code. It may not be used to create training material, 
 * courses, books, articles, and the like. Contact us if you are in doubt.
 * We make no guarantees that this code is fit for any purpose. 
 * Visit http://www.pragmaticprogrammer.com/titles/dhnako for more book information.
***/
package com.pragprog.dhnako.carserv.camel.inout.processors;

import org.apache.camel.Exchange;
import org.apache.camel.Message;
import org.apache.camel.Processor;
import org.nakedobjects.metamodel.adapter.NakedObject;
import org.nakedobjects.metamodel.authentication.AuthenticationSession;
import org.nakedobjects.metamodel.spec.NakedObjectSpecification;
import org.nakedobjects.metamodel.spec.feature.NakedObjectAction;
import org.nakedobjects.metamodel.spec.feature.NakedObjectActionConstants;
import org.nakedobjects.metamodel.specloader.SpecificationLoader;
import org.nakedobjects.runtime.context.NakedObjectsContext;
import org.nakedobjects.runtime.persistence.PersistenceSession;
import org.nakedobjects.runtime.persistence.adaptermanager.AdapterManager;
import org.nakedobjects.runtime.transaction.NakedObjectTransactionManager;

public abstract class AbstractNakedObjectsProcessor implements Processor {
	
	public void process(Exchange exchange) throws Exception {
		
		Message message = exchange.getIn();
		
		AuthenticationSession session = (AuthenticationSession)message.getHeader("nakedObjectsSession");
		NakedObjectsContext.openSession(session);
		
		startTransaction();
		try {
			doProcess(exchange);
			endTransaction();
		} catch(Exception ex) {
			exchange.setException(ex);
			abortTransaction();
		} finally {
			NakedObjectsContext.closeSession();
		}
		
	}

	protected abstract void doProcess(Exchange exchange);

	//////////////////////////////////////////////////////////////////////
	// Helpers
	//////////////////////////////////////////////////////////////////////

	protected void startTransaction() {
		getTransactionManager().startTransaction();
	}
	
	protected void endTransaction() {
		getTransactionManager().endTransaction();
	}
	
	protected void abortTransaction() {
		getTransactionManager().abortTransaction();
	}
	
	protected NakedObject adapterFor(Object pojo) {
		return getAdapterManager().adapterFor(pojo);
	}
	
	protected NakedObjectAction getAction(
			NakedObject adapter, String actionId, NakedObjectSpecification... parameters) {
		return adapter.getSpecification().getObjectAction(NakedObjectActionConstants.USER, actionId, parameters);
	}
	
	protected NakedObject executeAction(
			final NakedObjectAction action, 
			final NakedObject target, NakedObject... arguments) {
		return action.execute(target, arguments);
	}

	protected NakedObjectSpecification loadSpecification(Class<String> cls) {
		return getSpecificationLoader().loadSpecification(cls);
	}
	
	protected NakedObject getService(Class<?> serviceClass) {
		return getService(serviceClass.getName());
	}
	
	protected NakedObject getService(String serviceId) {
		return getPersistenceSession().getService(serviceId);
	}
	
	
	//////////////////////////////////////////////////////////////////////
	// Dependencies (from context)
	//////////////////////////////////////////////////////////////////////

	protected static SpecificationLoader getSpecificationLoader() {
		return NakedObjectsContext.getSpecificationLoader();
	}

	protected static PersistenceSession getPersistenceSession() {
		return NakedObjectsContext.getPersistenceSession();
	}
	
	protected static AdapterManager getAdapterManager() {
		return getPersistenceSession().getAdapterManager();
	}
	
	protected static NakedObjectTransactionManager getTransactionManager() {
		return NakedObjectsContext.getTransactionManager();
	}
}

