All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jpattern.core.command.CommandChain Maven / Gradle / Ivy

package com.jpattern.core.command;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import com.jpattern.core.IProvider;
import com.jpattern.shared.result.ErrorMessage;
import com.jpattern.shared.result.IErrorMessage;

/**
 * 
 * @author Francesco Cina'
 *
 * 11/set/2011
 */
public final class CommandChain extends ICommand {

	private List> commands = new ArrayList>();
	private final ICommandChainStrategy chainStrategy;
	private boolean executed = false;
	private boolean rolledback = false;

	public CommandChain() {
		this(new ConditionalCommandChainStrategy());
	}
	
	public CommandChain(ICommandChainStrategy chainStrategy) {
		this.chainStrategy = chainStrategy;
	}

	@Override
	protected final void doExec(boolean catchRuntimeException, ACommandResult commandResult) {
		executed = false;
		rolledback = false;
		CommandChainResult commandChainResult = new CommandChainResult(commandResult);
		commandChainResult.setExecutionStart(this);
		Iterator> commandsIterator = commands.iterator();
		while (commandsIterator.hasNext() &&  chainStrategy.executeNext( commandChainResult )) {
			ICommand command = null;
			try {
				command = commandsIterator.next();
				command.visit(getProvider());
				commandChainResult.setExecutionStart(command);
				chainStrategy.doExec(command, commandChainResult, catchRuntimeException, getCommandExecutor());
			} catch (RuntimeException e) {
				if (!catchRuntimeException) throw e;
				getLogger().error("doExec", "RuntimeException thrown during command chain execution", e);
				commandChainResult.addErrorMessage(new ErrorMessage(ICommandErrorsCostants.RUNTIME_EXEC_ERROR_NAME, e.getMessage()));
			} 
		}
		executed = true;
		checkIfRollback(catchRuntimeException, commandChainResult);
		commandChainResult.setExecutionEnd(this);
	}
	
	@Override
	protected final void doRollback(boolean catchRuntimeException, ACommandResult commandResult) {
		if (executed && !rolledback) {
			CommandChainResult commandChainResult = new CommandChainResult(commandResult);
			commandChainResult.setExecutionStart(this);
			for (int i = (commands.size()-1); i>=0 ; i--) {
				ICommand command = null;
				try {
					command = commands.get(i);
					command.visit(getProvider());
					commandChainResult.setExecutionStart(command);
					chainStrategy.doRollback(command, commandChainResult, catchRuntimeException, getCommandExecutor());
				} catch (RuntimeException e) {
					if (!catchRuntimeException) throw e;
					getLogger().error("doRollback", "RuntimeException thrown during command chain rollback", e);
					commandChainResult.addErrorMessage(new ErrorMessage(ICommandErrorsCostants.RUNTIME_ROLLBACK_ERROR_NAME, e.getMessage()));
				}
			}
			rolledback = true;
			commandChainResult.setExecutionEnd(this);
		}
	}
	
	private final void checkIfRollback(boolean catchRuntimeException, ACommandResult commandResult) {
		if (!commandResult.getErrorMessages().isEmpty() && chainStrategy.executeRollback()) {
			for (int i = (commands.size()-1); i>=0 ; i--) {
				commands.get(i).doRollback(catchRuntimeException, commandResult);
			}
			rolledback = true;
		}
	}
	
	public final void addCommand(ICommand command) {
		commands.add(command);
	}
	
	private class CommandChainResult extends ACommandResult {

		private static final long serialVersionUID = 1L;
		private final ACommandResult commandResult;
		private List> commandInExecutionList = new Vector>();
		
		CommandChainResult(ACommandResult commandResult) {
			this.commandResult = commandResult;
		}
		
		@Override
		public synchronized void addErrorMessage(IErrorMessage errorMessage) {
			commandResult.addErrorMessage(errorMessage);
		}

		@Override
		public synchronized String asString() {
			return commandResult.asString();
		}

		@Override
		public synchronized List getErrorMessages() {
			return commandResult.getErrorMessages();
		}

		@Override
		public synchronized boolean isValid() {
			return commandResult.isValid();
		}

		@Override
		public synchronized boolean isExecutionEnd() {
			return commandInExecutionList.isEmpty();
		}

		@Override
		public synchronized void waitExecutionEnd() throws InterruptedException {
			commandResult.waitExecutionEnd();
		}

		@Override
		protected synchronized void setExecutionEnd(ICommand command) {
			commandInExecutionList.remove(command);
			if (isExecutionEnd()) {
				commandResult.setExecutionEnd(CommandChain.this);
			}			
		}
		
		protected final synchronized void setExecutionStart(ICommand command) {
			commandInExecutionList.add(command);
		}
		
	}


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy