/*
* Patterns Library - Implementation of various design patterns
* Copyright (C) 2004 Philippe Herlin
*
* This library 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.
*
* This library 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 library; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact: philippe_herlin@yahoo.fr
*
*/
package name.herlin.command;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* Base class for processable commands. Such command doesn't execute on itself
* but are explicitly executed by a processor which acts as an execution
* environment.
* @see name.herlin.command.CommandProcessor for more details on processor.
*/
public abstract class AbstractProcessableCommand implements Command {
private static final long serialVersionUID = 1L;
// @PMD:REVIEWED:SingularField: by Herlin on 10/05/05 23:24
private CommandProcessor commandProcessor;
private boolean terminated;
/**
* Implementation method of a processable command. Developers of concrete
* commands are expected to implement the command logic there.
* @throws CommandException
*/
public abstract void execute() throws CommandException;
/**
* @return whether the command has result properties
*/
public abstract boolean hasOutputProperties();
/**
* Implement the execution of the command through a processor. Developer
* of concrete command cannot override this method. They are expected to
* implement the execute method instead.
*/
public final void performExecute() throws CommandException {
if (!isReadyToExecute()) {
throw new UnsetInputPropertiesException();
}
getCommandProcessor().processCommand(this);
}
/**
* @see Command#join()
*/
public final void join() throws CommandException {
getCommandProcessor().waitCommandToFinish(this);
}
/**
* @return the command preferred processor. The default is to return null
* which means the command doesn't have a preferred processor. Developers
* of concrete commands may override this methods to return a concrete
* command processor of their own.
*/
public CommandProcessor getPreferredCommandProcessor() {
return null;
}
/**
* @see name.herlin.command.Command#getDescription()
*/
public abstract String getDescription();
/**
* @see name.herlin.command.Command#getName()
*/
public abstract String getName();
/**
* @see name.herlin.command.Command#isReadOnly()
*/
public abstract boolean isReadOnly();
/**
* @see name.herlin.command.Command#isReadyToExecute()
*/
public abstract boolean isReadyToExecute();
/**
* @return Returns the terminated.
*/
public final boolean isTerminated() {
return terminated;
}
/**
* @param terminated The terminated to set.
*/
public final void setTerminated(final boolean terminated) {
this.terminated = terminated;
}
/**
* @see name.herlin.command.Command#reset()
*/
public abstract void reset();
/**
* @return the current strategy to compute the best processor for that
* command. The default is to find a concrete strategy in the strategy
* bundle. If none found (or if the class cannot be loaded or instantiated)
* the default strategy of the framework is returned. Developers of
* concrete commands may override this method to return a strategy of their
* own without using the bundle. But in any case, the return of that method
* MUST NOT be null.
*/
protected CommandProcessorStrategy getCommandProcessorStrategy() {
CommandProcessorStrategy strategy = null;
try {
ResourceBundle bundle = ResourceBundle.getBundle(CommandProcessorStrategy.COMMAND_PROCESSOR_STRATEGY_BUNDLE);
String strategyClassName = bundle.getString(CommandProcessorStrategy.STRATEGY_CLASS_KEY);
Class<?> strategyClass = Class.forName(strategyClassName);
strategy = (CommandProcessorStrategy) strategyClass.newInstance();
} catch (ClassNotFoundException e) {
// @PMD:REVIEWED:EmptyCatchBlock: by Herlin on 01/05/05 19:00
// ignored
} catch (InstantiationException e) {
// @PMD:REVIEWED:EmptyCatchBlock: by Herlin on 01/05/05 19:00
// ignored
} catch (IllegalAccessException e) {
// @PMD:REVIEWED:EmptyCatchBlock: by Herlin on 01/05/05 19:00
// ignored
} catch (MissingResourceException e) {
// @PMD:REVIEWED:EmptyCatchBlock: by Herlin on 01/05/05 19:00
// ignored
} finally {
if (strategy == null) {
strategy = new DefaultCommandProcessorStrategy();
}
}
return strategy;
}
/**
* @return the command processor for that command
*/
protected CommandProcessor getCommandProcessor() throws CommandException {
if (commandProcessor == null) {
final CommandProcessorStrategy strategy = getCommandProcessorStrategy();
commandProcessor = strategy.getCommandProcessor(this);
if (commandProcessor == null) {
throw new UnregisteredCommandException("Processor cannot be found for that command");
}
}
return commandProcessor;
}
}