[jboss-svn-commits] JBL Code SVN: r29278 - in labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src: main/java/uk/ac/ncl/sdia/a8905943/handle and 9 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Wed Sep 9 12:36:03 EDT 2009


Author: whitingjr
Date: 2009-09-09 12:36:03 -0400 (Wed, 09 Sep 2009)
New Revision: 29278

Added:
   labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/stm/field/IdentityFieldWriteParameter.java
Modified:
   labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/entitymanager/STMEntityManagerImpl.java
   labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/handle/FieldUtils.java
   labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/handle/HandleUtils.java
   labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/impl/STMTransactionImpl.java
   labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/isolation/AbstractFieldParameter.java
   labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/isolation/RepeatableReadIsolationImpl.java
   labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/persistence/jdbc/STMConnection.java
   labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/persistence/xa/STMXAConnectionImpl.java
   labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/stm/field/FieldReadParameter.java
   labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/stm/field/FieldWriteParameter.java
   labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/stm/transaction/TransactionManager.java
   labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/resources/META-INF/jboss-aop.xml
   labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/resources/log4j.xml
   labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/test/java/uk/ac/ncl/sdia/a8905943/entitymanager/TestSTMEntityManagerImpl.java
Log:
Added test cases. Added funtionality to EntityManager.
Started to add modification persistence of model store.

Modified: labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/entitymanager/STMEntityManagerImpl.java
===================================================================
--- labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/entitymanager/STMEntityManagerImpl.java	2009-09-09 14:48:32 UTC (rev 29277)
+++ labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/entitymanager/STMEntityManagerImpl.java	2009-09-09 16:36:03 UTC (rev 29278)
@@ -6,19 +6,19 @@
  */
 package uk.ac.ncl.sdia.a8905943.entitymanager;
 
-import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.sql.Connection;
 import java.sql.SQLException;
 
+import javax.persistence.EntityExistsException;
 import javax.persistence.EntityManager;
 import javax.persistence.EntityTransaction;
 import javax.persistence.FlushModeType;
 import javax.persistence.LockModeType;
 import javax.persistence.Query;
 import javax.persistence.spi.PersistenceUnitTransactionType;
-import javax.transaction.Synchronization;
 
 import org.apache.commons.jxpath.JXPathContext;
 import org.apache.log4j.Logger;
@@ -26,358 +26,440 @@
 
 import uk.ac.ncl.sdia.a8905943.factory.STMFactory;
 import uk.ac.ncl.sdia.a8905943.handle.FieldUtils;
+import uk.ac.ncl.sdia.a8905943.handle.HandleUtils;
 import uk.ac.ncl.sdia.a8905943.handle.exception.FieldNotFoundException;
 import uk.ac.ncl.sdia.a8905943.persistence.jdbc.STMConnection;
+import uk.ac.ncl.sdia.a8905943.stm.field.FieldWriteParameter;
+import uk.ac.ncl.sdia.a8905943.stm.field.IdentityFieldWriteParameter;
+import uk.ac.ncl.sdia.a8905943.stm.query.STMQueryImpl;
 
-final class STMEntityManagerImpl implements EntityManager {
-	private PersistenceUnitTransactionType type;
+final class STMEntityManagerImpl implements EntityManager
+{
+   private PersistenceUnitTransactionType type;
 
-	// this reference is a wrapped object
-	protected Connection connection;
+   // this reference is a wrapped object
+   protected Connection connection;
 
-	private static final Logger logger = Logger
-			.getLogger(STMEntityManagerImpl.class);
+   private static final Logger logger = Logger
+         .getLogger(STMEntityManagerImpl.class);
 
-	private boolean isOpen = false;
+   private boolean isOpen = false;
 
-	@Override
-	public void clear() {
-		STMFactory.getFactoryInstance().deallocate();
-	}
+   @Override
+   public void clear()
+   {
+      STMFactory.getFactoryInstance().deallocate();
+   }
 
-	@Override
-	public void close() {
-		/*
-		 * get the currently active transaction on this thread, register a
-		 * synchronization to close the Connection object.
-		 */
-		if (logger.isDebugEnabled()) {
-			logger.debug("STMEntityManagerImpl.close called.");
-		}
+   @Override
+   public void close()
+   {
+      if (logger.isDebugEnabled())
+      {
+         logger.debug("STMEntityManagerImpl.close called.");
+      }
 
-		// TransactionManager transactionManager =
-		// ServiceLocator.findLocalPersonManager();
-		try {
-			this.connection.close();
-			/*
-			 * Transaction transaction = transactionManager.getTransaction(); if
-			 * (null != transaction) { transaction.registerSynchronization(new
-			 * CloseSTMEM()); }
-			 */
-		}
-		/*
-		 * catch (SystemException se) { logger .error(
-		 * "Problem occured when registering a synchronization to close the Connection after the Transaction has completed."
-		 * , se); throw new RuntimeException(se); } catch (RollbackException re)
-		 * {
-		 * logger.error("Could not register a Synchronization for STMEntityManager"
-		 * ); throw new RuntimeException(re); }
-		 */
-		catch (SQLException sqle) {
-			logger
-					.error("SQLException occured when closing the connection object when, the EM is closed.");
-			throw new RuntimeException(sqle);
-		}
-		STMFactory.getFactoryInstance().deallocate();
+      try
+      {
+         this.connection.close();
+      }
+      catch (SQLException sqle)
+      {
+         logger
+               .error("SQLException occured when closing the connection object when, the EM is closed.");
+         throw new RuntimeException(sqle);
+      }
+      STMFactory.getFactoryInstance().deallocate();
 
-		this.isOpen = false;
-	}
+      this.isOpen = false;
+   }
 
-	/**
-	 * This method will use the entity class details and the unique identity to
-	 * verify if the entity exists in the model store.
-	 */
-	@Override
-	public boolean contains(Object entity) {// check the memory store for the
-											// presence of the managed entity
-		boolean returnValue = false;
-		String entityFQCN = null;
-		Long entityUniqueIdentity = null;
+   /**
+    * This method will use the entity class details and the unique identity to
+    * verify if the entity exists in the model store.
+    */
+   @Override
+   public boolean contains(Object entity)
+   {// check the memory store for the
+      // presence of the managed entity
+      detectectClosedConnection();
+      boolean returnValue = false;
+      String entityFQCN = null;
+      Long entityUniqueIdentity = null;
 
-		if (null != entity) {
-			entityFQCN = entity.getClass().getName();
-			FieldUtils fieldUtils = new FieldUtils();
-			try
-			{
-				Field idField = fieldUtils.findIdField(entity.getClass());
-				entityUniqueIdentity = fieldUtils.getValue(idField, entity);
-				JXPathContext context = JXPathContext.newContext(getSTMConnection().getSTM());
-				context.getVariables().declareVariable("entityType", entityFQCN);
-				context.getVariables().declareVariable("identityField", idField.getName());
-				context.getVariables().declareVariable("identityValue", entityUniqueIdentity);
-				returnValue = (null == context.getValue("model/$entityType[$identityField=$identityValue]") ? Boolean.FALSE.booleanValue(): Boolean.TRUE.booleanValue());
-			}
-			catch (FieldNotFoundException fnfe)
-			{
-				this.logger.error(fnfe.getMessage(), fnfe);
-			}
-		}
-		return returnValue;
-	}
+      if (null != entity)
+      {
+         entityFQCN = entity.getClass().getName();
+         FieldUtils fieldUtils = new FieldUtils();
+         try
+         {
+            Field idField = fieldUtils.findIdField(entity.getClass());
+            entityUniqueIdentity = fieldUtils.getValue(idField, entity);
+            
+            /* Check the field store for the identity field first, doing this detects if the entity has been removed beforehand. The model store*/
+            
+            JXPathContext context = JXPathContext.newContext(getSTMConnection()
+                  .getSTM());
+            context.setLenient(true);
+            StringBuffer query = new StringBuffer();
+            query.append("model/").append(entityFQCN).append("[");
+            query.append(idField.getName()).append("=$identityValue]");
+            context.getVariables().declareVariable("identityValue",
+                  entityUniqueIdentity);
+            if (logger.isTraceEnabled())
+            {
+               logger.trace("executing query [" + query.toString() + "]");
+            }
+            returnValue = (null == context.getValue(query.toString()) ? Boolean.FALSE
+                  .booleanValue()
+                  : Boolean.TRUE.booleanValue());
+         }
+         catch (FieldNotFoundException fnfe)
+         {
+            logger.error(fnfe.getMessage(), fnfe);
+         }
+      }
+      return returnValue;
+   }
 
-	@Override
-	public Query createNamedQuery(String name) {
-		if (true) {
-			throw new UnsupportedOperationException(
-					"Unsupported operation createNamedQuery(String)");
-		}
-		return null;
-	}
+   @Override
+   public Query createNamedQuery(String name)
+   {
+      if (true)
+      {
+         throw new UnsupportedOperationException(
+               "Unsupported operation createNamedQuery(String)");
+      }
+      return null;
+   }
 
-	@Override
-	public Query createNativeQuery(String sqlString) {
-		if (true) {
-			throw new UnsupportedOperationException(
-					"Unsupported operation createNamedQuery(String)");
-		}
+   @Override
+   public Query createNativeQuery(String sqlString)
+   {
+      if (true)
+      {
+         throw new UnsupportedOperationException(
+               "Unsupported operation createNamedQuery(String)");
+      }
 
-		return null;
-	}
+      return null;
+   }
 
-	@Override
-	public Query createNativeQuery(String sqlString, Class resultClass) {
-		if (true) {
-			throw new UnsupportedOperationException(
-					"Unsupported operation createNamedQuery(String)");
-		}
-		return null;
-	}
+   @Override
+   public Query createNativeQuery(String sqlString, Class resultClass)
+   {
+      if (true)
+      {
+         throw new UnsupportedOperationException(
+               "Unsupported operation createNamedQuery(String)");
+      }
+      return null;
+   }
 
-	@Override
-	public Query createNativeQuery(String sqlString, String resultSetMapping) {
-		if (true) {
-			throw new UnsupportedOperationException(
-					"Unsupported operation createNamedQuery(String)");
-		}
-		return null;
-	}
+   @Override
+   public Query createNativeQuery(String sqlString, String resultSetMapping)
+   {
+      if (true)
+      {
+         throw new UnsupportedOperationException(
+               "Unsupported operation createNamedQuery(String)");
+      }
+      return null;
+   }
 
-	@Override
-	public Query createQuery(String qlString) {
-		if (true) {
-			throw new UnsupportedOperationException(
-					"Unsupported operation createNamedQuery(String)");
-		}
-		return null;
-	}
+   /**
+    * This method returns a Query object to query the STM data store.
+    */
+   @Override
+   public Query createQuery(String qlString) throws IllegalArgumentException
+   {
+      detectectClosedConnection();
+      Query returnValue = null;
+      if (null != qlString)
+      {
+         JXPathContext context = JXPathContext.newContext(this
+               .getSTMConnection().getSTM());
+         returnValue = new STMQueryImpl(context, qlString);
+      }
+      else
+      {
+         throw new IllegalArgumentException(
+               "The query string provided is null.");
+      }
+      return returnValue;
+   }
 
-	@Override
-	/**
-	 * To call this method the entity object is expected to follow this contract.
-	 * Entity has one constructor that is public, contains only one field and is of
-	 * type {@link java.lang.Long}.
-	 * The entity class is annotated with the STMEntity annotation.
-	 * This method does not hit the STM system and only uses reflection to create
-	 * an instance of the entity.
-	 */
-	public <T> T find(Class<T> entityClass, Object primaryKey) {
-		if (logger.isDebugEnabled()) {
-			logger.debug("STMEntityManagerImpl.find called.");
-		}
-		T returnValue = null;
-		// check if the class has been annotated using the STM annotations.
-		boolean isstmEntity = false;
+   @SuppressWarnings("unchecked")
+   @Override
+   /**
+    * To call this method the entity object is expected to follow this contract.
+    * Entity has one constructor that is public, contains only one field and is of
+    * type {@link java.lang.Long}.
+    * The entity class is annotated with the STMEntity annotation.
+    * This method does not hit the STM system and only uses reflection to create
+    * an instance of the entity.
+    */
+   public <T> T find(Class<T> entityClass, Object primaryKey)
+   {
+      detectectClosedConnection();
+      T returnValue = null;
+      if (logger.isDebugEnabled())
+      {
+         logger.debug("STMEntityManagerImpl.find called.");
+      }
 
-		/**
-		 * This no longer works, using AOP means the reference given is an
-		 * instance of some proxy class.
-		 */
-		/*
-		 * for (Annotation annotation : entityClass.getAnnotations()) { if
-		 * (annotation instanceof STMEntity) { isstmEntity = true; } }
-		 */
-		// TODO: jrw replace this implementation, should go into STM and check
-		// the model store for existence.
-		isstmEntity = true;
-		if (isstmEntity) {// STM entity class, create an instance
-			try {
-				Constructor<T> targetConstructor = entityClass
-						.getConstructor(Long.class);
-				returnValue = targetConstructor.newInstance(primaryKey);
-			} catch (InstantiationException ie) {
-				logger
-						.error(
-								"Problem occured when creating an instance of an entity object.",
-								ie);
-			} catch (IllegalAccessException iae) {
-				logger
-						.error(
-								"Problem occured when creating an entity, constructor is expected to be public.",
-								iae);
-			} catch (NoSuchMethodException nsme) {
-				logger
-						.error(
-								"Expected constructor does not exist, please create a public constructor taking the primary key field only.",
-								nsme);
-				if (logger.isDebugEnabled()) {
-					logger.debug(log(entityClass));
-					for (Constructor constructor : entityClass
-							.getConstructors()) {
-						logger.debug("Constructor ["
-								+ constructor.toGenericString() + "]");
-					}
-				}
-			} catch (IllegalArgumentException illae) {
-				logger.error(
-						"Expected primary key type is expected to be Long.",
-						illae);
-			} catch (InvocationTargetException e) {
-				logger
-						.error(
-								"Something went wrong when getting creating an entity object",
-								e);
-			}
-		} else {
-			if (logger.isDebugEnabled()) {
-				logger.debug(log(entityClass));
-			}
-		}
-		return returnValue;
-	}
+      detectectClosedConnection();
 
-	@Override
-	public void flush() {
-		if (true) {
-			throw new UnsupportedOperationException(
-					"Unsupported operation createNamedQuery(String)");
-		}
-	}
+      FieldUtils fieldUtils = new FieldUtils();
+      try
+      {
+         Field idField = fieldUtils.findIdField(entityClass);
+         StringBuffer queryStatement = new StringBuffer();
 
-	public String log(Class entityClass) {
-		String name = entityClass.getName();
-		name = name.substring(name.lastIndexOf(".") + 1) + ".class";
-		return name + " loaded from " + entityClass.getResource(name);
-	}
+         queryStatement.append("model/").append(entityClass.getName()).append(
+               "[").append(idField.getName());
+         queryStatement.append("=$identityValue]");
+         Query query = this.createQuery(queryStatement.toString());
+         query.setParameter("identityValue", primaryKey);
+         if (logger.isTraceEnabled())
+         {
+            logger.trace("Executing query [" + queryStatement.toString()
+                  + "] with primary key value [" + primaryKey + "].");
+         }
+         returnValue = (T) query.getSingleResult();
+      }
+      catch (FieldNotFoundException fnfe)
+      {
+         logger.error("Identity field not found when finding entity.", fnfe);
+         throw new IllegalArgumentException(fnfe.getMessage());
+      }
 
-	@Override
-	public Object getDelegate() {
-		// FIXME getDelegate
-		return null;
-	}
+      return returnValue;
+   }
 
-	@Override
-	public FlushModeType getFlushMode() {
-		// FIXME getFlushMode
-		return null;
-	}
+   @Override
+   public void flush()
+   {
+      if (true)
+      {
+         throw new UnsupportedOperationException(
+               "Unsupported operation createNamedQuery(String)");
+      }
+   }
 
-	@Override
-	public <T> T getReference(Class<T> entityClass, Object primaryKey) {
-		// FIXME getReference
-		return null;
-	}
+   public String log(Class entityClass)
+   {
+      String name = entityClass.getName();
+      name = name.substring(name.lastIndexOf(".") + 1) + ".class";
+      return name + " loaded from " + entityClass.getResource(name);
+   }
 
-	@Override
-	public EntityTransaction getTransaction() {
-		if (PersistenceUnitTransactionType.JTA == this.type) {
-			throw new IllegalStateException(
-					"An EntityTransaction used bye EXTENDED entity managers is not allowed for the JTA transaction types.");
-		}
-		return null;
-	}
+   @Override
+   public Object getDelegate()
+   {
+      detectectClosedConnection();
+      // FIXME getDelegate
+      return null;
+   }
 
-	@Override
-	public boolean isOpen() {
-		return this.isOpen;
-	}
+   @Override
+   public FlushModeType getFlushMode()
+   {
+      detectectClosedConnection();
+      // FIXME getFlushMode
+      return null;
+   }
 
-	@Override
-	public void joinTransaction() {
-		// FIXME joinTransaction
+   @Override
+   public <T> T getReference(Class<T> entityClass, Object primaryKey)
+   {
+      detectectClosedConnection();
+      return find(entityClass, primaryKey);
+   }
 
-	}
+   @Override
+   public EntityTransaction getTransaction()
+   {
+      if (PersistenceUnitTransactionType.JTA == this.type)
+      {
+         throw new IllegalStateException(
+               "An EntityTransaction used bye EXTENDED entity managers is not allowed for the JTA transaction types.");
+      }
+      return null;
+   }
 
-	@Override
-	public void lock(Object entity, LockModeType lockMode) {
-		// FIXME lock
+   @Override
+   public boolean isOpen()
+   {
+      return this.isOpen;
+   }
 
-	}
+   @Override
+   public void joinTransaction()
+   {
+      detectectClosedConnection();
+      // FIXME joinTransaction
 
-	@Override
-	public <T> T merge(T entity) {
-		// FIXME merge
-		return null;
-	}
+   }
 
-	@Override
-	public void persist(Object entity) {
-		// FIXME persist
+   @Override
+   public void lock(Object entity, LockModeType lockMode)
+   {
+      detectectClosedConnection();
+      // FIXME lock
 
-	}
+   }
 
-	@Override
-	public void refresh(Object entity) {
-		// FIXME refresh
+   @Override
+   public <T> T merge(T entity)
+   {
+      detectectClosedConnection();
+      // FIXME merge
+      return null;
+   }
 
-	}
+   @Override
+   public void persist(Object entity)
+      throws EntityExistsException
+   {
+      detectectClosedConnection();
+      FieldUtils fieldUtils = new FieldUtils();
+      try
+      {
+         Field identityField = fieldUtils.findIdField(entity.getClass());
+         Long id = fieldUtils.getValue(identityField, entity  );
+         if (this.contains(entity))
+         {
+            throw new EntityExistsException("Attempt to persist an entity which already exists in the system with unique identity.");
+         }
+         // TODO: jrw, think about what has been already persisted considering an entity is directly "wired" into the persistence system.
+      }
+      catch (FieldNotFoundException fnfe)
+      {
+         logger.error("Error occured when attempting to persist an entity.", fnfe);
+      }
+   }
 
-	@Override
-	public void remove(Object entity) {
-		// FIXME remove
+   @Override
+   public void refresh(Object entity)
+   {
+      detectectClosedConnection();
+      //TODO: jrw, Should anything be necessary here, any changes made by the application are already part of the transation
 
-	}
+   }
 
-	@Override
-	public void setFlushMode(FlushModeType flushMode) {
-		// FIXME setFlushMode
+   @Override
+   public void remove(Object entity)
+   {
+      detectectClosedConnection();
+      //TODO: jrw: complete method, find all the setter methods of this entity. loop through and set each to null. Do not notify the model store leave this till committment.
+      /* Nullify all the entity fields. identity is excluded */
+      Object nullref =null;
+      FieldUtils fieldUtils = new FieldUtils();
+      for (Method method :  fieldUtils.retrieveTransactionalSetterMethods(entity.getClass()))
+      {
+         try
+         {
+            method.invoke(entity, nullref);
+         }
+         catch (InvocationTargetException ite)
+         {
+            logger.error("Error occurred when invoking each write method on entity.", ite);
+            throw new RuntimeException("Problem occurred invoking method to remove it's contents. Potential cleanup operation required.");
+         }
+         catch (IllegalAccessException iae)
+         {
+            logger.error("Error occurred when invoking each write method on entity.", iae);
+            throw new RuntimeException("Problem occured accessing method to remove the field from field store. Potential cleanup operation required.");
+         }
+      }
+      try
+      {/* Now nullify the identity field */
+         Field identityField = fieldUtils.findIdField(entity.getClass());
+         Long identity = fieldUtils.getValue(identityField, entity);
+         long fieldStoreHandle = new HandleUtils().getHandle(entity.getClass(), identity, identityField.getName());
+         
+         IdentityFieldWriteParameter write = new IdentityFieldWriteParameter(fieldStoreHandle, nullref, identity);
+         this.getSTMConnection().getSTM().write(write);
+      }
+      catch (FieldNotFoundException fnfe)
+      {
+         logger.error(fnfe.getMessage());
+      }
+      
+      
+   }
 
-	}
+   @Override
+   public void setFlushMode(FlushModeType flushMode)
+   {
+      detectectClosedConnection();
+      // FIXME setFlushMode
 
-	private STMEntityManagerImpl() {
-	}
+   }
 
-	public STMEntityManagerImpl(Connection connection) {
-		this();
-		this.connection = connection;
-		STMFactory.getFactoryInstance().allocate(getSTMConnection().getSTM());
-	}
+   private STMEntityManagerImpl()
+   {
+   }
 
-	public STMConnection getSTMConnection() {
-		STMConnection returnValue = null;
-		if (null != this.connection) {
-			try {
-				returnValue = (STMConnection) ((WrappedConnection) this.connection)
-						.getUnderlyingConnection();
-			} catch (SQLException sqle) {
-				logger.error(sqle);
-				throw new RuntimeException(sqle);
-			} catch (ClassCastException cce) {// check to see if this connection
-												// is a basic STMConnection,
-												// used in unit testing
-				if (this.connection instanceof STMConnection) {
-					returnValue = (STMConnection) this.connection;
-				}
-			}
-		}
-		return returnValue;
-	}
+   public STMEntityManagerImpl(Connection connection)
+   {
+      this();
+      this.connection = connection;
+      STMFactory.getFactoryInstance().allocate(getSTMConnection().getSTM());
+   }
 
-	public void setConnection(Connection connection) {
-		this.connection = connection;
-	}
+   public STMConnection getSTMConnection()
+   {
+      STMConnection returnValue = null;
+      if (null != this.connection)
+      {
+         try
+         {
+            returnValue = (STMConnection) ((WrappedConnection) this.connection)
+                  .getUnderlyingConnection();
+         }
+         catch (SQLException sqle)
+         {
+            logger.error(sqle);
+            throw new RuntimeException(sqle);
+         }
+         catch (ClassCastException cce)
+         {// check to see if this connection
+            // is a basic STMConnection,
+            // used in unit testing
+            if (this.connection instanceof STMConnection)
+            {
+               returnValue = (STMConnection) this.connection;
+            }
+         }
+      }
+      return returnValue;
+   }
 
-	private class CloseSTMEM implements Synchronization {
-		private final Logger logger = Logger.getLogger(CloseSTMEM.class);
+   public void setConnection(Connection connection)
+   {
+      this.connection = connection;
+   }
 
-		@Override
-		public void beforeCompletion() {
-			// do nothing
-		}
-
-		@Override
-		public void afterCompletion(int status) {
-			/*
-			 * Check to see if the Connection has been release back to the pool.
-			 */
-			try {
-				STMFactory.getFactoryInstance().deallocate();
-				if (!connection.isClosed()) {
-					connection.close();// release connection back into container
-										// pool
-				}
-			} catch (SQLException e) {
-				logger.error("Error", e);
-			}
-		}
-	}
+   private void detectectClosedConnection() throws IllegalStateException
+   {
+      try
+      {
+         if (this.getSTMConnection().isClosed())
+         {
+            throw new IllegalStateException(
+                  "The connection associated with this EntityManager has been closed.");
+         }
+      }
+      catch (SQLException sqle)
+      {
+         logger
+               .error(
+                     "Underlying database connection threw a SQLException when attempting to detect if the connection was closed.",
+                     sqle);
+         throw new IllegalStateException(
+               "The underlying connection threw a SQLException.");
+      }
+   }
 }

Modified: labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/handle/FieldUtils.java
===================================================================
--- labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/handle/FieldUtils.java	2009-09-09 14:48:32 UTC (rev 29277)
+++ labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/handle/FieldUtils.java	2009-09-09 16:36:03 UTC (rev 29278)
@@ -8,12 +8,16 @@
 
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
 
 import javax.persistence.Id;
 
 import org.apache.commons.beanutils.PropertyUtils;
 import org.apache.log4j.Logger;
 
+import uk.ac.ncl.sdia.a8905943.aspects.annotation.STMWriteable;
 import uk.ac.ncl.sdia.a8905943.handle.exception.FieldNotFoundException;
 
 public class FieldUtils
@@ -62,4 +66,20 @@
       }
       return returnValue; 
    }
+   
+   public List<Method> retrieveTransactionalSetterMethods(Class entityClass)
+   {
+      List<Method> returnValue = new ArrayList<Method>();
+      for (Method method : entityClass.getDeclaredMethods())
+      {
+         for (Annotation annotation: method.getAnnotations())
+         {
+            if (annotation instanceof STMWriteable)
+            {
+               returnValue.add(method);
+            }
+         }
+      }
+      return returnValue;
+   }
 }

Modified: labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/handle/HandleUtils.java
===================================================================
--- labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/handle/HandleUtils.java	2009-09-09 14:48:32 UTC (rev 29277)
+++ labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/handle/HandleUtils.java	2009-09-09 16:36:03 UTC (rev 29278)
@@ -12,7 +12,9 @@
 
 public class HandleUtils
 {
-
+   /**
+    * @deprecated
+    */
    public long getHandle(Class entity, String id, Field field )
    {
       return new HashCodeBuilder(17, 37).append(entity.getName()).append(id).append(field.getName()).toHashCode();
@@ -21,10 +23,16 @@
    {
       return new HashCodeBuilder(17, 37).append(entity.getName()).append(id).append(fieldName).toHashCode();
    }
+   /**
+    * @deprecated
+    */
    public long getFieldHandle(Class entity, String entityId, int fieldIndex)
    {
       return new HashCodeBuilder(17, 37).append(entity.getName()).append(entityId).append(fieldIndex).toHashCode();
    }
+   /**
+    * @deprecated
+    */
    public long getHandle(Class entity, int fieldIndex)
    {
       return new HashCodeBuilder(17, 37).append(entity.getName()).append(fieldIndex).toHashCode();

Modified: labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/impl/STMTransactionImpl.java
===================================================================
--- labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/impl/STMTransactionImpl.java	2009-09-09 14:48:32 UTC (rev 29277)
+++ labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/impl/STMTransactionImpl.java	2009-09-09 16:36:03 UTC (rev 29278)
@@ -9,8 +9,10 @@
 import java.util.ArrayDeque;
 import java.util.Deque;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 
 import javax.transaction.Status;
@@ -36,6 +38,12 @@
    protected volatile int status = Status.STATUS_NO_TRANSACTION;
    protected final Map<Long, TransactedObjectReference> deferredReads = new HashMap<Long, TransactedObjectReference>();
    protected final Map<Long, TransactedObjectReference> deferredWrites = new HashMap<Long, TransactedObjectReference>();
+   protected final Set<Long> deletedEntities = new HashSet<Long>();
+   public Set<Long> getDeletedEntities()
+   {
+      return deletedEntities;
+   }
+
    private final CountDownLatch phaseTwoTerminated = new CountDownLatch(1);
 
    /**
@@ -95,6 +103,7 @@
    {
       fieldWrite.setWrites(this.deferredWrites);
       fieldWrite.setVersion(this.version);
+      fieldWrite.setWrittenIdentityFields(this.deletedEntities);
       return this.isolation.write(fieldWrite);
    }
 

Modified: labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/isolation/AbstractFieldParameter.java
===================================================================
--- labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/isolation/AbstractFieldParameter.java	2009-09-09 14:48:32 UTC (rev 29277)
+++ labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/isolation/AbstractFieldParameter.java	2009-09-09 16:36:03 UTC (rev 29278)
@@ -10,18 +10,28 @@
 
 import uk.ac.ncl.sdia.a8905943.stm.object.TransactedObjectReference;
 
-public class AbstractFieldParameter
+public abstract class AbstractFieldParameter
 {
    protected Map<Long, TransactedObjectReference> objectStore;
    protected long handle;
    protected Map<Long, TransactedObjectReference> writes;
    private long version;
    private boolean isTransactional = true;// this should be turned off for queries ?
+   private Long identity;
 
+   public Long getIdentity()
+   {
+      return identity;
+   }
+   public void setIdentity(Long identity)
+   {
+      this.identity = identity;
+   }
    public AbstractFieldParameter()
    {
       super();
    }
+   public abstract boolean isIdentityField();
 
    public Map<Long, TransactedObjectReference> getObjectStore()
    {

Modified: labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/isolation/RepeatableReadIsolationImpl.java
===================================================================
--- labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/isolation/RepeatableReadIsolationImpl.java	2009-09-09 14:48:32 UTC (rev 29277)
+++ labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/isolation/RepeatableReadIsolationImpl.java	2009-09-09 16:36:03 UTC (rev 29278)
@@ -77,6 +77,10 @@
             fieldReference = new TransactedObjectReference(fieldWrite.getHandle(), fieldWrite.getNewObject(), fieldWrite.getVersion());
             fieldWrite.getWrites().put(fieldWrite.getHandle(), fieldReference);
          }
+         if (null == fieldWrite.getNewObject() && fieldWrite.isIdentityField())
+         {
+            fieldWrite.getWrittenIdentityFields().add(fieldWrite.getIdentity());
+         }
          
          returnValue = Boolean.TRUE;
       }

Modified: labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/persistence/jdbc/STMConnection.java
===================================================================
--- labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/persistence/jdbc/STMConnection.java	2009-09-09 14:48:32 UTC (rev 29277)
+++ labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/persistence/jdbc/STMConnection.java	2009-09-09 16:36:03 UTC (rev 29278)
@@ -40,7 +40,7 @@
 {
    private static final Logger logger = Logger.getLogger(STMConnection.class);
    private final boolean autoCommit = false;
-   private boolean isActive = false;
+   private boolean isActive = true;
    private final STMXAConnectionImpl xaConnection ;
    
    @Override
@@ -414,4 +414,9 @@
       return this.xaConnection.getSTM();
    }
    
+   public void setActive(boolean isActiveState)
+   {
+	   this.isActive = isActiveState;
+   }
+   
 }

Modified: labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/persistence/xa/STMXAConnectionImpl.java
===================================================================
--- labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/persistence/xa/STMXAConnectionImpl.java	2009-09-09 14:48:32 UTC (rev 29277)
+++ labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/persistence/xa/STMXAConnectionImpl.java	2009-09-09 16:36:03 UTC (rev 29278)
@@ -96,7 +96,7 @@
          this.logicalConnection.compareAndSet(null, new STMConnection(this));
       }
       returnValue = this.logicalConnection.get();
-      
+      returnValue.setActive(true);
       return returnValue;
    }
 

Modified: labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/stm/field/FieldReadParameter.java
===================================================================
--- labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/stm/field/FieldReadParameter.java	2009-09-09 14:48:32 UTC (rev 29277)
+++ labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/stm/field/FieldReadParameter.java	2009-09-09 16:36:03 UTC (rev 29278)
@@ -38,4 +38,10 @@
    {
       this.handle = handle;
    }
+
+   @Override
+   public boolean isIdentityField()
+   {
+      return false;
+   }
 }
\ No newline at end of file

Modified: labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/stm/field/FieldWriteParameter.java
===================================================================
--- labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/stm/field/FieldWriteParameter.java	2009-09-09 14:48:32 UTC (rev 29277)
+++ labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/stm/field/FieldWriteParameter.java	2009-09-09 16:36:03 UTC (rev 29278)
@@ -6,13 +6,24 @@
  */
 package uk.ac.ncl.sdia.a8905943.stm.field;
 
+import java.util.Set;
+
 import uk.ac.ncl.sdia.a8905943.isolation.AbstractFieldParameter;
 
 
 public class FieldWriteParameter extends AbstractFieldParameter
 {
    private Object newObject;
+   private Set<Long> writtenIdentityFields;
 
+   public Set<Long> getWrittenIdentityFields()
+   {
+      return writtenIdentityFields;
+   }
+   public void setWrittenIdentityFields(Set<Long> writtenIdentityFields)
+   {
+      this.writtenIdentityFields = writtenIdentityFields;
+   }
    public Object getNewObject()
    {
       return newObject;
@@ -26,4 +37,9 @@
       this.handle = handle;
       this.newObject = newObject;
    }
+   @Override
+   public boolean isIdentityField()
+   {
+      return false;
+   }
 }
\ No newline at end of file

Added: labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/stm/field/IdentityFieldWriteParameter.java
===================================================================
--- labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/stm/field/IdentityFieldWriteParameter.java	                        (rev 0)
+++ labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/stm/field/IdentityFieldWriteParameter.java	2009-09-09 16:36:03 UTC (rev 29278)
@@ -0,0 +1,39 @@
+ /*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2005, JBoss Inc., and individual contributors as indicated
+  * by the @authors tag. See the copyright.txt in the distribution for a
+  * full listing of individual contributors.
+  *
+  * This is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU Lesser General Public License as
+  * published by the Free Software Foundation; either version 2.1 of
+  * the License, or (at your option) any later version.
+  *
+  * This software is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
+  * License along with this software; if not, write to the Free
+  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  */
+
+package uk.ac.ncl.sdia.a8905943.stm.field;
+
+public final class IdentityFieldWriteParameter extends FieldWriteParameter
+{
+   @Override
+   public boolean isIdentityField()
+   {
+      return true;
+   }
+
+   public IdentityFieldWriteParameter(long handle, Object newObject, Long identity)
+   {
+      super(handle, newObject);
+      setIdentity(identity);
+   }
+
+}

Modified: labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/stm/transaction/TransactionManager.java
===================================================================
--- labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/stm/transaction/TransactionManager.java	2009-09-09 14:48:32 UTC (rev 29277)
+++ labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/stm/transaction/TransactionManager.java	2009-09-09 16:36:03 UTC (rev 29278)
@@ -78,10 +78,11 @@
       /* Depending on how far this transaction has progressed need to undo locks and clear 
        * collection objects. */
       logger.info("STMTransaction has been called to abort the transaction.");
-      try
+      
+      transaction.setStatus(Status.STATUS_MARKED_ROLLBACK);
+      for (TransactedObjectReference reference : transaction.getDeferredWrites().values())
       {
-         transaction.setStatus(Status.STATUS_MARKED_ROLLBACK);
-         for (TransactedObjectReference reference : transaction.getDeferredWrites().values())
+         try
          {
             TransactedObjectReference sharedReference = fieldMemory.get(reference.getLookupIdentity());
             if (null != sharedReference)
@@ -96,16 +97,17 @@
                {
                   logger.error("Problem occured, prepared lock is not held by current thread. Interleaving threads not working properly.");
                }
+            
             }
+         }            
+         catch (Exception e)
+         {
+            logger.error(e.getMessage(), e);
          }
          logger.info("STMTransaction has finished releasing all the locks aquired during prepare phase.");
          transaction.setStatus(Status.STATUS_ROLLEDBACK);
          transaction.getPhaseTwoTerminated().countDown();
       }
-      catch (Exception e)
-      {
-         logger.error(e.getMessage(), e);
-      }
    }
    /**
     * The purpose of this method is to lock all resources needed by the transaction. Need to keep a list of the 
@@ -280,6 +282,8 @@
          /* don't really want to substitute the shared version with the deferred write. 
           * should update values and use the count down latch to notify resource available. */
          // go ahead and replace all the values inside the shared transacted reference.
+         
+         //TODO: jrw refactor the update mechanism. Needs to be architected to support complex update mechanisms such as modifying the model store as well as removing something from field store.
          sharedReference.setValue(deferredWrite.getValue());
          sharedReference.setVersion(deferredWrite.getVersion());
          sharedReference.setPreparedVersion(null);

Modified: labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/resources/META-INF/jboss-aop.xml
===================================================================
--- labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/resources/META-INF/jboss-aop.xml	2009-09-09 14:48:32 UTC (rev 29277)
+++ labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/resources/META-INF/jboss-aop.xml	2009-09-09 16:36:03 UTC (rev 29278)
@@ -5,21 +5,7 @@
 	<aspect name="stminjectionaspect"
 		class="uk.ac.ncl.sdia.a8905943.aspects.STMInjectionAspect" />
 
-	<!-- bind
-		pointcut="execution(* *->@uk.ac.ncl.sdia.a8905943.aspects.annotation.STMWriteable(..))">
-		<advice name="stmwrite" aspect="stmwriteaspect" />
-	</bind>
 
-	<bind
-		pointcut="execution(* *->@uk.ac.ncl.sdia.a8905943.aspects.annotation.STMReadable(..))">
-		<advice name="stmread" aspect="stmreadaspect" />
-	</bind>
-
-	<bind
-		pointcut="field(uk.ac.ncl.sdia.a8905943.stm.STM *->@uk.ac.ncl.sdia.a8905943.stm.annotation.InjectedSTM )">
-		<advice name="access" aspect="stminjectionaspect" />
-	</bind-->
-
    <bind
       pointcut="execution(* *->@uk.ac.ncl.sdia.a8905943.aspects.annotation.STMWriteable(..))">
       <advice name="stmwrite" aspect="stmwriteaspect" />

Modified: labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/resources/log4j.xml
===================================================================
--- labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/resources/log4j.xml	2009-09-09 14:48:32 UTC (rev 29277)
+++ labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/resources/log4j.xml	2009-09-09 16:36:03 UTC (rev 29278)
@@ -37,7 +37,7 @@
 
 	<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
 		<param name="Target" value="System.out" />
-		<param name="Threshold" value="DEBUG" />
+		<param name="Threshold" value="TRACE" />
 
 		<layout class="org.apache.log4j.PatternLayout">
 			<!-- The default pattern: Date Priority [Category] Message\n -->
@@ -290,7 +290,7 @@
 	<!-- ======================= -->
 
 	<root>
-		<priority value="DEBUG" />
+		<priority value="TRACE" />
 		<appender-ref ref="CONSOLE" />
 	</root>
 

Modified: labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/test/java/uk/ac/ncl/sdia/a8905943/entitymanager/TestSTMEntityManagerImpl.java
===================================================================
--- labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/test/java/uk/ac/ncl/sdia/a8905943/entitymanager/TestSTMEntityManagerImpl.java	2009-09-09 14:48:32 UTC (rev 29277)
+++ labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/test/java/uk/ac/ncl/sdia/a8905943/entitymanager/TestSTMEntityManagerImpl.java	2009-09-09 16:36:03 UTC (rev 29278)
@@ -1,12 +1,17 @@
 package uk.ac.ncl.sdia.a8905943.entitymanager;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
+import javax.persistence.EntityExistsException;
+import javax.persistence.NoResultException;
+import javax.persistence.NonUniqueResultException;
+import javax.persistence.Query;
+
 import junit.framework.Assert;
 
+import org.apache.commons.jxpath.JXPathContext;
 import org.junit.Test;
 
 import uk.ac.ncl.sdia.a8905943.model.LeccyCar;
@@ -15,34 +20,167 @@
 import uk.ac.ncl.sdia.a8905943.persistence.xa.STMXADatasourceImpl;
 import uk.ac.ncl.sdia.a8905943.stm.AbstractUnitT;
 
-public class TestSTMEntityManagerImpl extends AbstractUnitT
-{
-	private STMEntityManagerImpl entityManager ;
+public class TestSTMEntityManagerImpl extends AbstractUnitT {
+	private STMEntityManagerImpl entityManager;
+
 	/**
 	 * This test case puts a known entity into the persistent store. Calls the
-	 * EntityManager to see if the entity can be found. 
+	 * EntityManager to see if the entity can be found.
 	 */
 	@Test
-	public void testCheckEntityFound()
+	public void testCheckContainsMethodWorks() {
+		Map<String, List<Object>> modelStore = this.stm.getModel();
+		Long carId = new Long(1);
+		LeccyCar car = new LeccyCar(carId);
+		List<Object> carList = new ArrayList<Object>();
+		carList.add(car);
+		String carFQCN = "uk.ac.ncl.sdia.a8905943.model.LeccyCar";
+		Assert.assertEquals(carFQCN, car.getClass().getName());
+		modelStore.put(car.getClass().getName(), carList);
+
+		Assert.assertNotNull(this.entityManager);
+		Assert.assertTrue(this.entityManager.contains(car));
+
+		LeccyCar hydrogenCar = new LeccyCar(4l);
+		Assert.assertFalse(this.entityManager.contains(hydrogenCar));
+	}
+
+	@Test
+	public void testCheckCheckForNonExistingEntityNoException() {
+		LeccyCar hydrogenCar = new LeccyCar(4l);
+		Assert.assertFalse(this.entityManager.contains(hydrogenCar));
+	}
+
+	/**
+	 * This test checks a single result query works.
+	 */
+	@Test
+	public void testCheckSingleResultQueryWorks() {
+		Map<String, List<Object>> modelStore = this.stm.getModel();
+		Long carId = new Long(1);
+		LeccyCar car = new LeccyCar(carId);
+		List<Object> carList = new ArrayList<Object>();
+		carList.add(car);
+		String carFQCN = "uk.ac.ncl.sdia.a8905943.model.LeccyCar";
+		Assert.assertEquals(carFQCN, car.getClass().getName());
+		modelStore.put(car.getClass().getName(), carList);
+
+		Assert.assertNotNull(this.entityManager);
+		Query query = this.entityManager.createQuery("model/"+carFQCN);
+		Object entity = query.getSingleResult();
+		Assert.assertNotNull(entity);
+		Assert.assertNotNull(entity.getClass());
+		Assert.assertEquals(entity.getClass(), car.getClass());
+		LeccyCar resultEntity = (LeccyCar)entity;
+		Assert.assertEquals(car.getId(), resultEntity.getId());
+	}
+	/**
+	 * Check the Query object throws an exception.
+	 *
+	 */
+	@Test (expected=NoResultException.class)
+	public void testCheckSingleResultQueryThrowsNoResultException()
 	{
+		Query query = this.entityManager.createQuery("model/duff");
+		query.getSingleResult();
+	}
+	/**
+	 * check multiple entities in result set throws an exception
+	 */
+	@Test (expected=NonUniqueResultException.class)
+	public void testCheckSingleResultQueryThrowsNonUniqueException()
+	{
 		Map<String, List<Object>> modelStore = this.stm.getModel();
 		Long carId = new Long(1);
 		LeccyCar car = new LeccyCar(carId);
 		List<Object> carList = new ArrayList<Object>();
 		carList.add(car);
+		carList.add(new LeccyCar(new Long(2)));
 		String carFQCN = "uk.ac.ncl.sdia.a8905943.model.LeccyCar";
 		Assert.assertEquals(carFQCN, car.getClass().getName());
 		modelStore.put(car.getClass().getName(), carList);
 		
 		Assert.assertNotNull(this.entityManager);
-		Assert.assertTrue(this.entityManager.contains(car));
+		Query query = this.entityManager.createQuery("model/"+carFQCN);
+		Object entity = query.getSingleResult();
+	}
+
+	@Test
+	public void testCheckFindEntity()
+	{
+		Map<String, List<Object>> modelStore = this.stm.getModel();
+		Long carId = new Long(1);
+		LeccyCar car = new LeccyCar(carId);
+		List<Object> carList = new ArrayList<Object>();
+		carList.add(car);
+		carList.add(new LeccyCar(new Long(2)));
+		String carFQCN = "uk.ac.ncl.sdia.a8905943.model.LeccyCar";
+		Assert.assertEquals(carFQCN, car.getClass().getName());
+		modelStore.put(car.getClass().getName(), carList);
 		
+		Assert.assertNotNull(this.entityManager);
+		LeccyCar foundEntity = this.entityManager.find(LeccyCar.class, carId);
+		Assert.assertNotNull(foundEntity);
+		Assert.assertNotNull(foundEntity.getId());
+		Assert.assertEquals(foundEntity.getId(), carId	);
+		
 	}
 	
+	@Test
+	public void testCheckSelectedNodesMethodBehaviour()
+	{// the default setLenient is false, does the method explode?
+		JXPathContext context = JXPathContext.newContext(this.stm);
+		List entities = context.selectNodes("model/nothing");
+		Assert.assertNotNull(entities);
+		Assert.assertEquals(0, entities.size());
+	}
+	
+	@Test (expected=EntityExistsException.class)
+	public void testCheckPersistThrowsEntityExistsExceptino()
+	{
+		Map<String, List<Object>> modelStore = this.stm.getModel();
+		Long carId = new Long(1);
+		LeccyCar car = new LeccyCar(carId);
+		List<Object> carList = new ArrayList<Object>();
+		carList.add(car);
+		String carFQCN = "uk.ac.ncl.sdia.a8905943.model.LeccyCar";
+		Assert.assertEquals(carFQCN, car.getClass().getName());
+		modelStore.put(car.getClass().getName(), carList);
+		
+		LeccyCar duplicate = new LeccyCar(new Long(1));
+		Assert.assertEquals(car.getId(), duplicate.getId());
+		
+		this.entityManager.persist(duplicate);
+	}
+	
+	@Test
+	public void testCheckQueryDoesNotReturnRemovedEntity()
+	{
+	   Map<String, List<Object>> modelStore = this.stm.getModel();
+      Long carId = new Long(1);
+      LeccyCar car = new LeccyCar(carId);
+      List<Object> carList = new ArrayList<Object>();
+      carList.add(car);
+      modelStore.put(car.getClass().getName(), carList);
+      
+      this.entityManager.remove(car);
+      Query query = this.entityManager.createQuery("model/"+car.getClass().getName());
+      List resultSet = query.getResultList();
+      Assert.assertNotNull(resultSet);
+      Assert.assertEquals(0, resultSet.size());
+	}
+
 	@Override
 	public void setUp() {
 		super.setUp();
-		this.entityManager = new STMEntityManagerImpl(new STMConnection(new STMXAConnectionImpl(new STMXADatasourceImpl(), this.stm)));
+		STMConnection stmConnection = new STMConnection(
+				new STMXAConnectionImpl(new STMXADatasourceImpl(), this.stm));
+		
+		this.entityManager = new STMEntityManagerImpl(stmConnection);
 	}
-	
+	@Override
+	public void tearDown() {
+		super.tearDown();
+		this.entityManager = null;
+	}
 }



More information about the jboss-svn-commits mailing list