package com.processpuzzle.fitnesse.persistence; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.processpuzzle.application.configuration.domain.ProcessPuzzleContext; import com.processpuzzle.application.configuration.domain.RepositoryInstantiationException; import com.processpuzzle.commons.persistence.AggregateRoot; import com.processpuzzle.commons.persistence.PersistentObject; import com.processpuzzle.commons.persistence.Repository; import com.processpuzzle.commons.persistence.RepositoryResultSet; import com.processpuzzle.fundamental_types.domain.ParameterValueList; import com.processpuzzle.persistence.domain.SimpleResultSet; import com.processpuzzle.persistence.domain.TestEntity; import com.processpuzzle.user_session.domain.UserRequestManager; import fit.RowFixture; import fitlibrary.DoFixture; public class RepositoryTester extends DoFixture { private static final Logger logger = LoggerFactory.getLogger( RepositoryTester.class ); private ProcessPuzzleContext applicationContext = null; private String repositoryClassName; private Class<? extends Repository<?>> repositoryClass; private Class<? extends AggregateRoot> aggregateRootClass; private Repository<?> repository; private RepositoryResultSet<?> repositoryResultSet; private ParameterValueList parameterValueList; //Constructors public RepositoryTester() { super(); logger.debug( "New 'RepositoryTester' was instantiated." ); } //Public accessors and mutators public void executeWithParameter( String methodName, String parameters ) throws NoSuchRepositoryMethodException, RepositoryMethodExecutionException, ClassNotFoundException, InstantiationException, IllegalAccessException { logger.debug( "Trying to execute method: '" + methodName + "' with parameters: '" + parameters + "'."); parameterValueList = parseParameters( parameters ); Method repositoryMethod = determineRepositoryMethod( methodName, parameterValueList ); repositoryResultSet = executeRepositoryMethod( repositoryMethod, parameterValueList ); logger.debug( "'" + methodName + "' returned: '" + repositoryResultSet.size() + "' objects." ); } public RowFixture expectedResultSet() { logger.debug( "Wrapping result set." ); RepositoryResultSetChecker resultSetChecker = new RepositoryResultSetChecker( repositoryResultSet, aggregateRootClass ); return resultSetChecker; } public void useRepository( String repositoryClassName ) { lazyInitialization(); try{ this.repositoryClassName = repositoryClassName; this.repositoryClass = determineRepositoryClass(); this.repository = applicationContext.getRepository( repositoryClass ); this.aggregateRootClass = this.repository.getSupportedAggregateRootClass() != null ? this.repository.getSupportedAggregateRootClass() : TestEntity.class; }catch( Exception e ){ String message = "Repository '" + repositoryClassName + "' not found."; logger.error( message ); throw new RepositoryTesterException( message, e ); } logger.debug( "Repository '" + repositoryClassName + "' was selected." ); } //Properties public ProcessPuzzleContext getApplicationContext() { return applicationContext; } public ParameterValueList getParameterValueList() { return parameterValueList; } public Repository<?> getRepository() { return repository; } public RepositoryResultSet<? extends PersistentObject> getRepositoryResultSet() { return repositoryResultSet; } public Class<? extends Repository<?>> getRepositoryClass() { return repositoryClass; } //Protected, private helper methods @SuppressWarnings("unchecked") private Class<? extends Repository<?>> determineRepositoryClass() { try{ repositoryClass = (Class<? extends Repository<?>>) Class.forName( repositoryClassName ); }catch( ClassNotFoundException e ){ throw new RepositoryInstantiationException( repositoryClassName, null, e ); } return repositoryClass; } private Method determineRepositoryMethod( String methodName, ParameterValueList parameterList ) throws NoSuchRepositoryMethodException { List<Method> foundMethods = new ArrayList<Method>(); for( Method method : repositoryClass.getDeclaredMethods() ) { if( method.getName().equals( methodName )) foundMethods.add( method ); } if( foundMethods.size() == 0 ) { throw new NoSuchRepositoryMethodException( repositoryClass, methodName ); }else if( foundMethods.size() == 1 ) { return foundMethods.get( 0 ); }else { Class<?>[] parameterTypes = parameterList.getParameterTypes(); for( Method method : foundMethods ) { if( Arrays.equals( method.getParameterTypes(), parameterTypes )) { return method; } } } throw new NoSuchRepositoryMethodException( repositoryClass, methodName ); } @SuppressWarnings("unchecked") private RepositoryResultSet<?> executeRepositoryMethod( Method repositoryMethod, ParameterValueList parameterList ) throws RepositoryMethodExecutionException { RepositoryResultSet<?> resultSet = null; List<Object> resultList = new ArrayList(); try{ Object returnValue = repositoryMethod.invoke( repository, parameterList.getValues() ); if( repositoryMethod.getReturnType().isAssignableFrom( RepositoryResultSet.class ) ) { resultSet = (RepositoryResultSet<?>) returnValue; }else if( returnValue != null ){ resultList.add( returnValue ); resultSet = new SimpleResultSet( resultList ); }else { resultSet = new SimpleResultSet( resultList ); } }catch( IllegalArgumentException e ){ throw new RepositoryMethodExecutionException( repositoryClass, repositoryMethod.getName(), parameterList.toString(), e ); }catch( IllegalAccessException e ){ throw new RepositoryMethodExecutionException( repositoryClass, repositoryMethod.getName(), parameterList.toString(), e ); }catch( InvocationTargetException e ){ throw new RepositoryMethodExecutionException( repositoryClass, repositoryMethod.getName(), parameterList.toString(), e ); } return resultSet; } private void lazyInitialization() { if( applicationContext == null ) { applicationContext = UserRequestManager.getInstance().getApplicationContext(); if( applicationContext == null ) throw new UnconfiguredApplicationException(); } } private ParameterValueList parseParameters( String parameters ) throws ClassNotFoundException, InstantiationException, IllegalAccessException { ParameterValueList parameterList = ParameterValueList.parse( parameters ); return parameterList; } }