Revision: 1674 http://svn.sourceforge.net/spring-rich-c/?rev=1674&view=rev Author: kevinstembridge Date: 2007-01-16 12:22:31 -0800 (Tue, 16 Jan 2007)
Log Message: ----------- Fix for problems in DefaultCommandRegistry as described in RCP-457 Modified Paths: -------------- trunk/spring-richclient/support/src/main/java/org/springframework/richclient/command/CommandRegistry.java trunk/spring-richclient/support/src/main/java/org/springframework/richclient/command/CommandRegistryEvent.java trunk/spring-richclient/support/src/main/java/org/springframework/richclient/command/support/DefaultCommandManager.java trunk/spring-richclient/support/src/main/java/org/springframework/richclient/command/support/DefaultCommandRegistry.java trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/support/DefaultCommandRegistryTests.java trunk/spring-richclient/support/src/test/java/org/springframework/richclient/config/DefaultApplicationLifecycleAdvisorTests.java Added Paths: ----------- trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/AbstractCommandRegistryTests.java trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/CommandRegistryEventTests.java Modified: trunk/spring-richclient/support/src/main/java/org/springframework/richclient/command/CommandRegistry.java =================================================================== --- trunk/spring-richclient/support/src/main/java/org/springframework/richclient/command/CommandRegistry.java 2007-01-16 20:16:54 UTC (rev 1673) +++ trunk/spring-richclient/support/src/main/java/org/springframework/richclient/command/CommandRegistry.java 2007-01-16 20:22:31 UTC (rev 1674) @@ -15,20 +15,181 @@ */ package org.springframework.richclient.command; +/** + * A registry for command objects. + * + * <p> + * The commands to be placed in the registry must have non-null identifiers available via their + * [EMAIL PROTECTED] AbstractCommand#getId()} method, and this id is expected to be unique amongst all the + * commands in the application. Generally speaking, this uniqueness will not be enforced by the + * framework but will instead allow commands to be overwritten by others with the same id. + * </p> + * + * <p> + * Implementations may allow for the creation of hierarchical registries whereby a registry may have + * a parent registry. In this case, if a registry does not contain a requested command it will + * delegate to its parent to find the command. Commands in a child registry will override commands + * with the same ID in any ancestor registries. + * </p> + * + * @author Keith Donald + * @author Kevin Stembridge + * + */ public interface CommandRegistry { - public ActionCommand getActionCommand(String commandId); + + /** + * Returns true if the registry contains a command with the given identifier. + * + * @param commandId The ID of the command to search for. + * @return true if the registry contains the command, false otherwise. + * + * @throws IllegalArgumentException if [EMAIL PROTECTED] commandId} is null. + */ + boolean containsCommand(String commandId); + + /** + * Retrieves from the registry the command with the given identifier. + * + * @param commandId The ID of the command to be retrieved. + * @return The command with the given ID, or null if no such command could be found. + * + * @throws IllegalArgumentException if [EMAIL PROTECTED] commandId} is null. + */ + Object getCommand(String commandId); + + /** + * Retrieves from the registry the command with the given identifier. An exception is thrown + * if the retrieved command is not assignable to the required type. + * + * @param commandId The identifier of the command to be retrieved. Must not be null. + * @param requiredType The required type of the command with the given id. + * + * @return The command with the given id if it exists in the registry and is of the required type. + * + * @throws CommandNotOfRequiredTypeException if the retrieved command is not assignable to + * the required type. + */ + Object getCommand(String commandId, Class requiredType) throws CommandNotOfRequiredTypeException; + + /** + * Returns the type of the command with the given identifier, if it is contained in the + * registry. + * + * @param commandId The ID of the command whose type is to be returned. Must not be null. + * @return The type of the command with the given ID, or null if no such command exists in + * the registry. + * + * @throws IllegalArgumentException if [EMAIL PROTECTED] commandId} is null. + */ + Class getType(String commandId); + + /** + * Returns true if the command with the given identifier is assignable to the given type. + * + * @param commandId The ID of the command whose type will be checked. Must not be null. + * @param targetType The type to be checked against the type of the command. Must not be null. + * @return true if a command with the given ID exists in the registry and it is assignable to + * the given target type, false otherwise. + * + * @throws IllegalArgumentException if either argument is null. + */ + boolean isTypeMatch(String commandId, Class targetType); + + /** + * Returns the [EMAIL PROTECTED] ActionCommand} that has the given id. + * + * @param commandId The id of the action command to be returned. + * @return The action command with the given id, or null if no such command exists in the + * registry. + * + * @throws IllegalArgumentException if [EMAIL PROTECTED] commandId} is null. + * @throws CommandNotOfRequiredTypeException if there is a command with the given id in the + * registry but it is not of type [EMAIL PROTECTED] ActionCommand}. + * + * @deprecated use [EMAIL PROTECTED] #getCommand(String, Class)} instead. You may choose to either catch + * the [EMAIL PROTECTED] CommandNotOfRequiredTypeException} or call [EMAIL PROTECTED] #isTypeMatch(String, Class)} first. + */ + ActionCommand getActionCommand(String commandId); - public CommandGroup getCommandGroup(String groupId); + /** + * Returns the [EMAIL PROTECTED] CommandGroup} that has the given id. + * + * @param groupId The id of the command group to be returned. + * @return The command group with the given id, or null if no such command group exists in the + * registry. + * + * @throws IllegalArgumentException if [EMAIL PROTECTED] commandId} is null. + * @throws CommandNotOfRequiredTypeException if there is a command with the given id in the + * registry but it is not of type [EMAIL PROTECTED] CommandGroup}. + * + * @deprecated use [EMAIL PROTECTED] #getCommand(String, Class)} instead. You may choose to either catch + * the [EMAIL PROTECTED] CommandNotOfRequiredTypeException} or call [EMAIL PROTECTED] #isTypeMatch(String, Class)} first. + */ + CommandGroup getCommandGroup(String groupId); - public boolean containsActionCommand(String commandId); + /** + * Returns true if the registry contains a command of type [EMAIL PROTECTED] ActionCommand} with the + * given id. + * + * @param commandId The id of the command to be searched for. + * @return true if the registry contains the command and it is assignable to [EMAIL PROTECTED] ActionCommand}. + * + * @deprecated Replaced by [EMAIL PROTECTED] #isTypeMatch(String, Class)} + */ + boolean containsActionCommand(String commandId); - public boolean containsCommandGroup(String groupId); + /** + * Returns true if the registry contains a command of type [EMAIL PROTECTED] CommandGroup} with the + * given id. + * + * @param groupId The id of the command group to be searched for. + * @return true if the registry contains the command and it is assignable to [EMAIL PROTECTED] CommandGroup}. + * + * @deprecated Replaced by [EMAIL PROTECTED] #isTypeMatch(String, Class)} + */ + boolean containsCommandGroup(String groupId); - public void registerCommand(AbstractCommand command); + /** + * Registers the given command with the registry. Neither the command nor its id can be null. + * All registered listeners will be notified of the newly registered command via their + * [EMAIL PROTECTED] CommandRegistryListener#commandRegistered(CommandRegistryEvent)} method. If the + * given command is an instance of [EMAIL PROTECTED] CommandGroup}, its + * [EMAIL PROTECTED] CommandGroup#setCommandRegistry(CommandRegistry)} method must be called to set this + * instance as the registry for the command group. + * + * @param command The command to be registered. Must not be null. + * + * @throws IllegalArgumentException if [EMAIL PROTECTED] command} is null or if its id is null. + */ + void registerCommand(AbstractCommand command); - public void setTargetableActionCommandExecutor(String targetableCommandId, ActionCommandExecutor commandExecutor); + /** + * Sets a command executor for the command with the given id. The actual type of the command + * must be assignable to [EMAIL PROTECTED] TargetableActionCommand}. + * + * @param targetableCommandId The id of the targetable command that will have its executor set. + * Must not be null. + * @param commandExecutor The command executor. May be null. + * + * @throws IllegalArgumentException if [EMAIL PROTECTED] targetableCommandId} is null. + * @throws CommandNotOfRequiredTypeException if the command with the given id is not a + * [EMAIL PROTECTED] TargetableActionCommand}. + */ + void setTargetableActionCommandExecutor(String targetableCommandId, ActionCommandExecutor commandExecutor); - public void addCommandRegistryListener(CommandRegistryListener l); + /** + * Adds the given listener to the colleciton of listeners that will be notified of registry events. + * + * @param listener The listener to be added. Must not be null. + */ + void addCommandRegistryListener(CommandRegistryListener listener); - public void removeCommandRegistryListener(CommandRegistryListener l); -} \ No newline at end of file + /** + * Remove the given listener from the collection of listeners that will be notified of registry events. + * + * @param listener The listener to be removed. + */ + void removeCommandRegistryListener(CommandRegistryListener listener); + +} Modified: trunk/spring-richclient/support/src/main/java/org/springframework/richclient/command/CommandRegistryEvent.java =================================================================== --- trunk/spring-richclient/support/src/main/java/org/springframework/richclient/command/CommandRegistryEvent.java 2007-01-16 20:16:54 UTC (rev 1673) +++ trunk/spring-richclient/support/src/main/java/org/springframework/richclient/command/CommandRegistryEvent.java 2007-01-16 20:22:31 UTC (rev 1674) @@ -17,16 +17,40 @@ import java.util.EventObject; +import org.springframework.richclient.util.Assert; + +/** + * An event object that originated from a [EMAIL PROTECTED] CommandRegistry}. + * + */ public class CommandRegistryEvent extends EventObject { - private AbstractCommand command; + private static final long serialVersionUID = 740046110521079234L; + + private final AbstractCommand command; - public CommandRegistryEvent(Object source, AbstractCommand command) { + /** + * Creates a new [EMAIL PROTECTED] CommandRegistryEvent} for the given registry and command. + * + * @param source The command registry that originated the event. Must not be null. + * @param command The command that the event relates to. Must not be null. + * + * @throws IllegalArgumentException if either argument is null. + */ + public CommandRegistryEvent(CommandRegistry source, AbstractCommand command) { super(source); + Assert.required(source, "source"); + Assert.required(command, "command"); this.command = command; } + /** + * Returns the command that the event relates to. + * + * @return The command, never null. + */ public AbstractCommand getCommand() { return command; } -} \ No newline at end of file + +} Modified: trunk/spring-richclient/support/src/main/java/org/springframework/richclient/command/support/DefaultCommandManager.java =================================================================== --- trunk/spring-richclient/support/src/main/java/org/springframework/richclient/command/support/DefaultCommandManager.java 2007-01-16 20:16:54 UTC (rev 1673) +++ trunk/spring-richclient/support/src/main/java/org/springframework/richclient/command/support/DefaultCommandManager.java 2007-01-16 20:22:31 UTC (rev 1674) @@ -30,6 +30,7 @@ import org.springframework.richclient.command.CommandGroup; import org.springframework.richclient.command.CommandGroupFactoryBean; import org.springframework.richclient.command.CommandManager; +import org.springframework.richclient.command.CommandNotOfRequiredTypeException; import org.springframework.richclient.command.CommandRegistry; import org.springframework.richclient.command.CommandRegistryListener; import org.springframework.richclient.command.CommandServices; @@ -50,7 +51,7 @@ private BeanFactory beanFactory; - private DefaultCommandRegistry commandRegistry = new DefaultCommandRegistry(); + private final DefaultCommandRegistry commandRegistry = new DefaultCommandRegistry(); private CommandServices commandServices; @@ -231,4 +232,40 @@ } return bean; } + + /** + * [EMAIL PROTECTED] + */ + public boolean containsCommand(String commandId) { + return this.commandRegistry.containsCommand(commandId); + } + + /** + * [EMAIL PROTECTED] + */ + public Object getCommand(String commandId, Class requiredType) throws CommandNotOfRequiredTypeException { + return this.commandRegistry.getCommand(commandId, requiredType); + } + + /** + * [EMAIL PROTECTED] + */ + public Object getCommand(String commandId) { + return this.commandRegistry.getCommand(commandId); + } + + /** + * [EMAIL PROTECTED] + */ + public Class getType(String commandId) { + return this.commandRegistry.getType(commandId); + } + + /** + * [EMAIL PROTECTED] + */ + public boolean isTypeMatch(String commandId, Class targetType) { + return this.commandRegistry.isTypeMatch(commandId, targetType); + } + } \ No newline at end of file Modified: trunk/spring-richclient/support/src/main/java/org/springframework/richclient/command/support/DefaultCommandRegistry.java =================================================================== --- trunk/spring-richclient/support/src/main/java/org/springframework/richclient/command/support/DefaultCommandRegistry.java 2007-01-16 20:16:54 UTC (rev 1673) +++ trunk/spring-richclient/support/src/main/java/org/springframework/richclient/command/support/DefaultCommandRegistry.java 2007-01-16 20:22:31 UTC (rev 1674) @@ -15,9 +15,9 @@ */ package org.springframework.richclient.command.support; -import java.util.ArrayList; -import java.util.HashMap; +import java.util.Hashtable; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -27,87 +27,185 @@ import org.springframework.richclient.command.ActionCommand; import org.springframework.richclient.command.ActionCommandExecutor; import org.springframework.richclient.command.CommandGroup; +import org.springframework.richclient.command.CommandNotOfRequiredTypeException; import org.springframework.richclient.command.CommandRegistry; import org.springframework.richclient.command.CommandRegistryEvent; import org.springframework.richclient.command.CommandRegistryListener; import org.springframework.richclient.command.TargetableActionCommand; -import org.springframework.util.Assert; +import org.springframework.richclient.util.Assert; +import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; /** + * The default implementation of the [EMAIL PROTECTED] CommandRegistry} interface. This implementation + * may act as the child of another registry, allowing for a hierarchy of registries to be created. + * If a command is requested from this registry but cannot be found, the request will be delegated + * to the parent registry. + * + * * @author Keith Donald + * @author Kevin Stembridge */ public class DefaultCommandRegistry implements CommandRegistry, CommandRegistryListener { + + /** + * Class logger, available to subclasses. + */ protected final Log logger = LogFactory.getLog(getClass()); - private List commandRegistryListeners; + private final List commandRegistryListeners = new LinkedList(); - private Map commandRegistry = new HashMap(); + private final Map commandMap = new Hashtable(); private CommandRegistry parent; + /** + * Creates a new uninitialized [EMAIL PROTECTED] DefaultCommandRegistry}. + */ public DefaultCommandRegistry() { - + //do nothing } + /** + * Creates a new [EMAIL PROTECTED] DefaultCommandRegistry} as a child of the given registry. The newly + * created instance will be added as a listener on the parent registry. + * + * @param parent The parent registry. May be null. + */ public DefaultCommandRegistry(CommandRegistry parent) { - setParent(parent); + internalSetParent(parent); } + /** + * Sets the given registry to be the parent of this instance. If the new parent is not null, + * this instance will act as a registry listener on it. + * + * @param parent The parent registry. May be null. + */ public void setParent(CommandRegistry parent) { - if (!ObjectUtils.nullSafeEquals(this.parent, parent)) { + internalSetParent(parent); + } + + /** + * This method is provided as a private helper so that it can be called by the constructor, + * instead of the constructor having to call the public overridable setParent method. + */ + private void internalSetParent(CommandRegistry parentRegistry) { + + if (!ObjectUtils.nullSafeEquals(this.parent, parentRegistry)) { + if (this.parent != null) { this.parent.removeCommandRegistryListener(this); } - this.parent = parent; + + this.parent = parentRegistry; + if (this.parent != null) { this.parent.addCommandRegistryListener(this); } + } + } + /** + * [EMAIL PROTECTED] + */ public void commandRegistered(CommandRegistryEvent event) { + Assert.required(event, "event"); fireCommandRegistered(event.getCommand()); } + /** + * [EMAIL PROTECTED] + * @deprecated + */ public ActionCommand getActionCommand(String commandId) { - ActionCommand command = (ActionCommand)commandRegistry.get(commandId); - if (command == null) { - if (parent != null) { - command = parent.getActionCommand(commandId); - } + + if (logger.isDebugEnabled()) { + logger.debug("Attempting to retrieve ActionCommand with id [" + + commandId + + "] from the command registry."); } + + Assert.required(commandId, "commandId"); + + Object command = commandMap.get(commandId); + + if (command == null && this.parent != null) { + command = this.parent.getActionCommand(commandId); + } + if (command == null) { - logger.warn("No action command with id '" + commandId + "' exists in registry; returning null"); + logger.debug("command not found, returning null."); + return null; + } + + if (!(command instanceof ActionCommand)) { + throw new CommandNotOfRequiredTypeException(commandId, ActionCommand.class, command.getClass()); } - return command; + + return (ActionCommand) command; + } + /** + * [EMAIL PROTECTED] + * @deprecated + */ public CommandGroup getCommandGroup(String groupId) { - CommandGroup group = (CommandGroup)commandRegistry.get(groupId); - if (group == null) { - if (parent != null) { - group = parent.getCommandGroup(groupId); - } + + if (logger.isDebugEnabled()) { + logger.debug("Attempting to retrieve command group with id [" + + groupId + + "] from the command registry."); } - if (group == null) { - logger.warn("No command group with id '" + groupId + "' exists in registry; returning null"); + + Assert.required(groupId, "groupId"); + + Object command = commandMap.get(groupId); + + if (command == null && this.parent != null) { + command = this.parent.getCommandGroup(groupId); } - return group; + + if (command == null) { + logger.debug("Command group not found, returning null."); + return null; + } + + if (!(command instanceof CommandGroup)) { + throw new CommandNotOfRequiredTypeException(groupId, CommandGroup.class, command.getClass()); + } + + return (CommandGroup) command; + } + /** + * [EMAIL PROTECTED] + * @deprecated + */ public boolean containsActionCommand(String commandId) { - if (commandRegistry.containsKey(commandId)) { + + if (commandMap.containsKey(commandId)) { return true; } + if (parent != null) { return parent.containsActionCommand(commandId); } + return false; + } + /** + * [EMAIL PROTECTED] + * @deprecated + */ public boolean containsCommandGroup(String groupId) { - if (commandRegistry.get(groupId) instanceof CommandGroup) { + if (commandMap.get(groupId) instanceof CommandGroup) { return true; } if (parent != null) { @@ -116,71 +214,197 @@ return false; } + /** + * [EMAIL PROTECTED] + */ public void registerCommand(AbstractCommand command) { + Assert.notNull(command, "Command cannot be null."); Assert.isTrue(command.getId() != null, "A command must have an identifier to be placed in a registry."); - if (containsActionCommand(command.getId())) { - if (logger.isWarnEnabled()) { - logger.warn("This command registry already contains a command with id '" + command.getId() - + "'; will overwrite..."); - } + + Object previousCommand = this.commandMap.put(command.getId(), command); + + if (previousCommand != null && logger.isWarnEnabled()) { + logger.warn("The command [" + + previousCommand + + "] was overwritten in the registry with the command [" + + command + + "]"); } - commandRegistry.put(command.getId(), command); + if (command instanceof CommandGroup) { - ((CommandGroup)command).setCommandRegistry(this); + ((CommandGroup) command).setCommandRegistry(this); } + if (logger.isDebugEnabled()) { logger.debug("Command registered '" + command.getId() + "'"); } + fireCommandRegistered(command); + } + /** + * Fires a 'commandRegistered' [EMAIL PROTECTED] CommandRegistryEvent} for the given command to all + * registered listeners. + * + * @param command The command that has been registered. Must not be null. + * + * @throws IllegalArgumentException if [EMAIL PROTECTED] command} is null. + */ protected void fireCommandRegistered(AbstractCommand command) { - if (commandRegistryListeners == null) { + + Assert.required(command, "command"); + + if (commandRegistryListeners.isEmpty()) { return; } - CommandRegistryEvent e = null; + + CommandRegistryEvent event = new CommandRegistryEvent(this, command); + for (Iterator i = commandRegistryListeners.iterator(); i.hasNext();) { - if (e == null) { - e = new CommandRegistryEvent(this, command); - } - ((CommandRegistryListener)i.next()).commandRegistered(e); + ((CommandRegistryListener)i.next()).commandRegistered(event); } + } - public void setTargetableActionCommandExecutor(String commandId, ActionCommandExecutor delegate) { - try { - TargetableActionCommand command = (TargetableActionCommand)getActionCommand(commandId); - Assert.isTrue(command != null, "No targetable command found with id " + commandId); - command.setCommandExecutor(delegate); + /** + * [EMAIL PROTECTED] + */ + public void setTargetableActionCommandExecutor(String commandId, ActionCommandExecutor executor) { + + Assert.required(commandId, "commandId"); + + TargetableActionCommand command + = (TargetableActionCommand) getCommand(commandId, TargetableActionCommand.class); + + if (command != null) { + command.setCommandExecutor(executor); } - catch (ClassCastException e) { - throw new IllegalArgumentException( - "Command delegates can only be attached to targetable action commands; commandId '" + commandId - + "' is not an instanceof TargetableActionCommand."); - } + } - public void addCommandRegistryListener(CommandRegistryListener l) { - if (commandRegistryListeners == null) { - commandRegistryListeners = new ArrayList(); - } + /** + * [EMAIL PROTECTED] + */ + public void addCommandRegistryListener(CommandRegistryListener listener) { + if (logger.isDebugEnabled()) { - logger.debug("Adding command registry listener " + l); + logger.debug("Adding command registry listener " + listener); } - commandRegistryListeners.add(l); + + commandRegistryListeners.add(listener); + } - public void removeCommandRegistryListener(CommandRegistryListener l) { - Assert.notNull(commandRegistryListeners, "Listenerlist not yet created; add a listener first!"); + /** + * [EMAIL PROTECTED] + */ + public void removeCommandRegistryListener(CommandRegistryListener listener) { + if (logger.isDebugEnabled()) { - logger.debug("Removing command registry listener " + l); + logger.debug("Removing command registry listener " + listener); } - commandRegistryListeners.remove(l); + + commandRegistryListeners.remove(listener); + } + /** + * Returns the parent registry of this instance. + * + * @return The parent registry, or null. + */ public CommandRegistry getParent() { return parent; } -} \ No newline at end of file + /** + * [EMAIL PROTECTED] + */ + public boolean containsCommand(String commandId) { + + Assert.required(commandId, "commandId"); + + if (this.commandMap.containsKey(commandId)) { + return true; + } + + if (this.parent != null) { + return this.parent.containsCommand(commandId); + } + + return false; + + } + + /** + * [EMAIL PROTECTED] + */ + public Object getCommand(String commandId) { + return getCommand(commandId, null); + } + + /** + * [EMAIL PROTECTED] + */ + public Object getCommand(String commandId, Class requiredType) throws CommandNotOfRequiredTypeException { + + Assert.required(commandId, "commandId"); + + Object command = this.commandMap.get(commandId); + + if (command == null && this.parent != null) { + command = this.parent.getCommand(commandId); + } + + if (command == null) { + return null; + } + + if (requiredType != null && !ClassUtils.isAssignableValue(requiredType, command)) { + throw new CommandNotOfRequiredTypeException(commandId, requiredType, command.getClass()); + } + + return command; + + } + + /** + * [EMAIL PROTECTED] + */ + public Class getType(String commandId) { + + Assert.required(commandId, "commandId"); + + Object command = getCommand(commandId); + + if (command == null) { + return null; + } + else { + return command.getClass(); + } + + } + + /** + * [EMAIL PROTECTED] + */ + public boolean isTypeMatch(String commandId, Class targetType) { + + Assert.required(commandId, "commandId"); + Assert.required(targetType, "targetType"); + + Class commandType = getType(commandId); + + if (commandType == null) { + return false; + } + else { + return ClassUtils.isAssignable(targetType, commandType); + } + + } + +} Added: trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/AbstractCommandRegistryTests.java =================================================================== --- trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/AbstractCommandRegistryTests.java (rev 0) +++ trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/AbstractCommandRegistryTests.java 2007-01-16 20:22:31 UTC (rev 1674) @@ -0,0 +1,450 @@ +/* + * Copyright 2002-2004 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.springframework.richclient.command; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.easymock.EasyMock; +import org.easymock.IArgumentMatcher; +import org.springframework.util.ObjectUtils; + + +/** + * This is an abstract test case for implementations of the [EMAIL PROTECTED] CommandRegistry} interface. + * Subclasses only need to override the [EMAIL PROTECTED] #getCommandRegistry()} method to return the + * concrete implementation to be tested. + * + * @author Kevin Stembridge + * @since 0.3 + * + */ +public abstract class AbstractCommandRegistryTests extends TestCase { + + /** + * Creates a new uninitialized [EMAIL PROTECTED] AbstractCommandRegistryTests}. + */ + protected AbstractCommandRegistryTests() { + super(); + } + + /** + * Subclasses must override this method to provide the concrete implementation of the registry + * to be tested. A new, empy registry must be provided. This method may be called often, so + * subclasses should take care to not repeat any unnecessary initialization. + * + * @return The registry implementation to be tested, never null. + */ + protected abstract CommandRegistry getCommandRegistry(); + + /** + * Tests the [EMAIL PROTECTED] CommandRegistry#registerCommand(AbstractCommand)} method. + */ + public void testRegisterCommand() { + + CommandRegistry registry = getCommandRegistry(); + CommandRegistryListener listener + = (CommandRegistryListener) EasyMock.createStrictMock(CommandRegistryListener.class); + registry.addCommandRegistryListener(listener); + + EasyMock.replay(listener); + + try { + registry.registerCommand(null); + Assert.fail("Should throw IllegalArgumentException"); + } + catch (IllegalArgumentException e) { + //test passes + } + + EasyMock.verify(listener); + EasyMock.reset(listener); + EasyMock.replay(listener); + + try { + registry.registerCommand(new TestCommand()); + Assert.fail("Should throw IllegalArgumentException because commandId has not been set"); + } + catch (IllegalArgumentException e) { + //test passes + } + + EasyMock.verify(listener); + EasyMock.reset(listener); + + TestCommand command1 = new TestCommand("command"); + CommandRegistryEvent event = new CommandRegistryEvent(registry, command1); + + listener.commandRegistered(matchEvent(event)); + + EasyMock.replay(listener); + registry.registerCommand(command1); + EasyMock.verify(listener); + + Assert.assertTrue("command1 not registered", registry.containsCommand(command1.getId())); + Assert.assertEquals("command1 not registered", command1, registry.getCommand(command1.getId())); + + TestCommand command2 = new TestCommand(command1.getId()); + event = new CommandRegistryEvent(registry, command2); + + EasyMock.reset(listener); + + listener.commandRegistered(matchEvent(event)); + EasyMock.replay(listener); + registry.registerCommand(command2); + EasyMock.verify(listener); + + Assert.assertTrue(registry.containsCommand(command2.getId())); + Assert.assertEquals("command1 not overridden", command2, registry.getCommand(command2.getId())); + + } + + /** + * Confirms that if a CommandGroup is being registered, it will obtain a reference to the + * registry that it is being added to. + */ + public void testRegisterCommandGroup() { + + CommandRegistry registry = getCommandRegistry(); + + CommandGroup commandGroup = new CommandGroup("testCommandGroup"); + registry.registerCommand(commandGroup); + + assertTrue("commandgroup not registered", registry.containsCommand("testCommandGroup")); + assertEquals("commandgroup not registered", commandGroup, registry.getCommand("testCommandGroup")); + + Assert.assertEquals(registry, commandGroup.getCommandRegistry()); + + } + + /** + * Tests the [EMAIL PROTECTED] CommandRegistry#isTypeMatch(String, Class)} method. + */ + public final void testIsTypeMatch() { + + CommandRegistry registry = getCommandRegistry(); + + try { + registry.isTypeMatch(null, Object.class); + Assert.fail("Should have thrown IllegalArgumentException for null commandId"); + } + catch (IllegalArgumentException e) { + //test passes + } + + try { + registry.isTypeMatch("bogusCommandId", null); + Assert.fail("Should have thrown IllegalArgumentException for null targetType"); + } + catch (IllegalArgumentException e) { + //test passes + } + + //Add a command to the registry which is a subclass of AbstractCommand + TestCommand testCommand = new TestCommand("testCommand"); + registry.registerCommand(testCommand); + + Assert.assertTrue("Assert isTypeMatch", registry.isTypeMatch(testCommand.getId(), TestCommand.class)); + Assert.assertTrue("Assert isTypeMatch", registry.isTypeMatch(testCommand.getId(), AbstractCommand.class)); + Assert.assertFalse("Assert isTypeMatch", registry.isTypeMatch(testCommand.getId(), String.class)); + + } + + /** + * Tests the [EMAIL PROTECTED] CommandRegistry#containsCommand(String)} method. + */ + public final void testContainsCommand() { + + CommandRegistry registry = getCommandRegistry(); + + try { + registry.containsCommand(null); + Assert.fail("Should have thrown an IllegalArgumentException for null commandId"); + } + catch (IllegalArgumentException e) { + //test passes + } + + Assert.assertFalse("Assert registry does not contain a command", registry.containsCommand("bogusCommandId")); + + TestCommand testCommand = new TestCommand("testCommand"); + registry.registerCommand(testCommand); + + Assert.assertTrue("Assert registry contains command", registry.containsCommand(testCommand.getId())); + + } + + /** + * Tests the [EMAIL PROTECTED] CommandRegistry#getCommand(String)} method. + */ + public final void testGetCommandById() { + + CommandRegistry registry = getCommandRegistry(); + + try { + registry.getCommand(null); + Assert.fail("Should have thrown an IllegalArgumentException for null commandId"); + } + catch (IllegalArgumentException e) { + //test passes + } + + Assert.assertNull("getCommand should return null", registry.getCommand("bogusCommandId")); + + TestCommand testCommand = new TestCommand("testCommand"); + registry.registerCommand(testCommand); + + Assert.assertEquals(testCommand, registry.getCommand(testCommand.getId())); + + } + + /** + * Tests the [EMAIL PROTECTED] CommandRegistry#getCommand(String, Class)} method. + */ + public final void testGetCommandByIdAndRequiredType() { + + CommandRegistry registry = getCommandRegistry(); + + try { + registry.getCommand(null, Object.class); + Assert.fail("Should have thrown an IllegalArgumentException for null commandId"); + } + catch (IllegalArgumentException e) { + //test passes + } + + Assert.assertNull(registry.getCommand("bogusCommandId", null)); + + Assert.assertNull("getCommand should return null", registry.getCommand("bogusCommandId", TestCommand.class)); + + TestCommand testCommand = new TestCommand("testCommand"); + TestCommand2 testCommand2 = new TestCommand2("testCommand2"); + registry.registerCommand(testCommand); + registry.registerCommand(testCommand2); + + Assert.assertEquals(testCommand, registry.getCommand(testCommand.getId(), TestCommand.class)); + Assert.assertEquals(testCommand, registry.getCommand(testCommand.getId(), AbstractCommand.class)); + + try { + registry.getCommand(testCommand.getId(), TestCommand2.class); + Assert.fail("Should have thrown CommandNotOfRequiredTypeException"); + } + catch (CommandNotOfRequiredTypeException e) { + Assert.assertEquals(testCommand.getId(), e.getCommandId()); + Assert.assertEquals(TestCommand2.class, e.getRequiredType()); + Assert.assertEquals(TestCommand.class, e.getActualType()); + } + + } + + /** + * Tests the [EMAIL PROTECTED] CommandRegistry#getType(String)} method. + */ + public final void testGetType() { + + CommandRegistry registry = getCommandRegistry(); + + try { + registry.getType(null); + Assert.fail("Should have thrown an IllegalArgumentException for null commandId"); + } + catch (IllegalArgumentException e) { + //test passes + } + + Assert.assertNull("getType should return null", registry.getType("bogusCommandId")); + + TestCommand testCommand = new TestCommand("testCommand"); + TestCommand2 testCommand2 = new TestCommand2("testCommand2"); + registry.registerCommand(testCommand); + registry.registerCommand(testCommand2); + + Assert.assertEquals(testCommand.getClass(), registry.getType(testCommand.getId())); + Assert.assertEquals(testCommand2.getClass(), registry.getType(testCommand2.getId())); + + } + + /** + * Tests the [EMAIL PROTECTED] CommandRegistry#setTargetableActionCommandExecutor(String, ActionCommandExecutor)} + * method. + */ + public void testSetTargetableActionCommandExecutor() { + + CommandRegistry registry = getCommandRegistry(); + TestTargetableActionCommand targetableCommand = new TestTargetableActionCommand(); + targetableCommand.setId("bogusId"); + registry.registerCommand(targetableCommand); + ActionCommandExecutor executor = (ActionCommandExecutor) EasyMock.createMock(ActionCommandExecutor.class); + + try { + registry.setTargetableActionCommandExecutor(null, null); + Assert.fail("Should have thrown an IllegalArgumentException for null commandId"); + } + catch (IllegalArgumentException e) { + //test passes + } + + registry.setTargetableActionCommandExecutor(targetableCommand.getId(), executor); + + Assert.assertEquals(executor, targetableCommand.getCommandExecutor()); + + registry.setTargetableActionCommandExecutor(targetableCommand.getId(), null); + + Assert.assertEquals(null, targetableCommand.getCommandExecutor()); + + } + + private static class TestCommand extends AbstractCommand { + + private String id; + + /** + * Creates a new uninitialized [EMAIL PROTECTED] TestCommand}. + * + */ + public TestCommand() { + //do nothing + } + + /** + * Creates a new uninitialized [EMAIL PROTECTED] TestCommand}. + * + * @param id + */ + public TestCommand(String id) { + this.id = id; + } + + public String getId() { + return this.id; + } + + /** + * [EMAIL PROTECTED] + */ + public void execute() { + //do nothing + } + + } + + private static class TestCommand2 extends AbstractCommand { + + private String id; + + /** + * Creates a new uninitialized [EMAIL PROTECTED] TestCommand2}. + * + */ + public TestCommand2() { + //do nothing + } + + /** + * Creates a new uninitialized [EMAIL PROTECTED] TestCommand2}. + * + * @param id + */ + public TestCommand2(String id) { + this.id = id; + } + + public String getId() { + return this.id; + } + + /** + * [EMAIL PROTECTED] + */ + public void execute() { + //do nothing + } + + } + + private static CommandRegistryEvent matchEvent(CommandRegistryEvent event) { + EasyMock.reportMatcher(new CommandRegistryEventMatcher(event)); + return event; + } + + private static class CommandRegistryEventMatcher implements IArgumentMatcher { + + private CommandRegistryEvent expectedEvent; + + /** + * Creates a new [EMAIL PROTECTED] CommandRegistryEventMatcher}. + * + * @param expectedEvent + */ + public CommandRegistryEventMatcher(CommandRegistryEvent expectedEvent) { + this.expectedEvent = expectedEvent; + } + + /** + * [EMAIL PROTECTED] + */ + public void appendTo(StringBuffer buffer) { + buffer.append("("); + buffer.append(expectedEvent.getClass().getName()); + buffer.append(" with message \""); + buffer.append(expectedEvent.getSource()); + buffer.append("\"\")"); + + } + + /** + * [EMAIL PROTECTED] + */ + public boolean matches(Object argument) { + + if (!(argument instanceof CommandRegistryEvent)) { + return false; + } + + CommandRegistryEvent other = (CommandRegistryEvent) argument; + + if (!ObjectUtils.nullSafeEquals(expectedEvent.getSource(), other.getSource())) { + return false; + } + + if (!ObjectUtils.nullSafeEquals(expectedEvent.getCommand(), other.getCommand())) { + return false; + } + + return true; + + } + + } + + private static class TestTargetableActionCommand extends TargetableActionCommand { + + private ActionCommandExecutor executor; + + /** + * [EMAIL PROTECTED] + */ + public void setCommandExecutor(ActionCommandExecutor commandExecutor) { + this.executor = commandExecutor; + } + + public ActionCommandExecutor getCommandExecutor() { + return this.executor; + } + + } + +} Property changes on: trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/AbstractCommandRegistryTests.java ___________________________________________________________________ Name: svn:keywords + Author Id Revision Date HeadURL Name: svn:eol-style + native Added: trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/CommandRegistryEventTests.java =================================================================== --- trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/CommandRegistryEventTests.java (rev 0) +++ trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/CommandRegistryEventTests.java 2007-01-16 20:22:31 UTC (rev 1674) @@ -0,0 +1,76 @@ +/* + * Copyright 2002-2004 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.springframework.richclient.command; + +import org.easymock.EasyMock; + +import junit.framework.Assert; +import junit.framework.TestCase; + + +/** + * Provides unit tests for the [EMAIL PROTECTED] CommandRegistryEvent} class. + * + * @author Kevin Stembridge + * @since 0.3 + * + */ +public class CommandRegistryEventTests extends TestCase { + + /** + * Creates a new uninitialized [EMAIL PROTECTED] CommandRegistryEventTests}. + */ + public CommandRegistryEventTests() { + super(); + } + + /** + * Tests that the event object can be created and its properties correctly retrieved. + */ + public final void testAll() { + + AbstractCommand command = new AbstractCommand("noOpCommand") { + public void execute() { + //do nothing + } + }; + + CommandRegistry registry = (CommandRegistry) EasyMock.createMock(CommandRegistry.class); + + try { + new CommandRegistryEvent(null, command); + Assert.fail("Should have thrown an IllegalArgumentException for null registry"); + } + catch (IllegalArgumentException e) { + //test passes + } + + try { + new CommandRegistryEvent(registry, null); + Assert.fail("Should have thrown an IllegalArgumentException for null command"); + } + catch (IllegalArgumentException e) { + //test passes + } + + CommandRegistryEvent event = new CommandRegistryEvent(registry, command); + + Assert.assertEquals(command, event.getCommand()); + Assert.assertEquals(registry, event.getSource()); + + } + +} Property changes on: trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/CommandRegistryEventTests.java ___________________________________________________________________ Name: svn:keywords + Author Id Revision Date HeadURL Name: svn:eol-style + native Modified: trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/support/DefaultCommandRegistryTests.java =================================================================== --- trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/support/DefaultCommandRegistryTests.java 2007-01-16 20:16:54 UTC (rev 1673) +++ trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/support/DefaultCommandRegistryTests.java 2007-01-16 20:22:31 UTC (rev 1674) @@ -18,20 +18,30 @@ import java.util.ArrayList; import java.util.List; -import junit.framework.TestCase; - import org.springframework.richclient.command.AbstractCommand; +import org.springframework.richclient.command.AbstractCommandRegistryTests; import org.springframework.richclient.command.ActionCommand; import org.springframework.richclient.command.ActionCommandExecutor; import org.springframework.richclient.command.CommandGroup; +import org.springframework.richclient.command.CommandNotOfRequiredTypeException; import org.springframework.richclient.command.CommandRegistry; -import org.springframework.richclient.command.CommandRegistryEvent; import org.springframework.richclient.command.CommandRegistryListener; /** + * Provides unit tests for the [EMAIL PROTECTED] DefaultCommandRegistry} class. + * * @author Peter De Bruycker + * @author Kevin Stembridge */ -public class DefaultCommandRegistryTests extends TestCase { +public class DefaultCommandRegistryTests extends AbstractCommandRegistryTests { + + /** + * [EMAIL PROTECTED] + */ + protected CommandRegistry getCommandRegistry() { + return new DefaultCommandRegistry(); + } + public void testConstructor() { DefaultCommandRegistry registry = new DefaultCommandRegistry(); assertNull("parent must be null", registry.getParent()); @@ -70,69 +80,7 @@ assertEquals("registry not removed from parent", 1, parent2.removedListeners.size()); } - public void testRegisterCommand() { - DefaultCommandRegistry registry = new DefaultCommandRegistry(); - TestableRegistryListener listener = new TestableRegistryListener(); - registry.addCommandRegistryListener(listener); - - try { - registry.registerCommand(null); - fail("Should throw IllegalArgumentException"); - } - catch (IllegalArgumentException e) { - pass(); - } - - try { - registry.registerCommand(new TestCommand()); - fail("Should throw IllegalArgumentException"); - } - catch (IllegalArgumentException e) { - pass(); - } - - TestCommand command1 = new TestCommand("testCommand"); - // command1 and command2 have same id's - TestCommand command2 = new TestCommand("testCommand"); - - registry.registerCommand(command1); - assertTrue("command1 not registered", registry.containsActionCommand("testCommand")); - assertEquals("command1 not registered", command1, registry.getActionCommand("testCommand")); - assertEquals("event not fired", command1, listener.registeredCommand); - - registry.registerCommand(command2); - assertTrue(registry.containsActionCommand("testCommand")); - assertEquals("command1 not overridden", command2, registry.getActionCommand("testCommand")); - assertEquals("event not fired", command2, listener.registeredCommand); - } - - public void testRegisterCommandGroup() { - DefaultCommandRegistry registry = new DefaultCommandRegistry(); - - CommandGroup commandGroup = new CommandGroup("testCommandGroup"); - registry.registerCommand(commandGroup); - - assertTrue("commandgroup not registered", registry.containsCommandGroup("testCommandGroup")); - assertEquals("commandgroup not registered", commandGroup, registry.getCommandGroup("testCommandGroup")); - } - - private static void pass() { - // test passes - } - - public static class TestableRegistryListener implements CommandRegistryListener { - - private AbstractCommand registeredCommand; - - /** - * @see org.springframework.richclient.command.CommandRegistryListener#commandRegistered(org.springframework.richclient.command.CommandRegistryEvent) - */ - public void commandRegistered(CommandRegistryEvent event) { - registeredCommand = event.getCommand(); - } - } - - public static class TestCommandRegistry implements CommandRegistry { + private static class TestCommandRegistry implements CommandRegistry { private List addedListeners = new ArrayList(); private List removedListeners = new ArrayList(); @@ -171,5 +119,42 @@ addedListeners.clear(); removedListeners.clear(); } + + /** + * [EMAIL PROTECTED] + */ + public boolean containsCommand(String commandId) { + return false; + } + + /** + * [EMAIL PROTECTED] + */ + public Object getCommand(String commandId) { + return null; + } + + /** + * [EMAIL PROTECTED] + */ + public Object getCommand(String commandId, Class requiredType) throws CommandNotOfRequiredTypeException { + return null; + } + + /** + * [EMAIL PROTECTED] + */ + public Class getType(String commandId) { + return null; + } + + /** + * [EMAIL PROTECTED] + */ + public boolean isTypeMatch(String commandId, Class targetType) { + return false; + } + } -} \ No newline at end of file + +} Modified: trunk/spring-richclient/support/src/test/java/org/springframework/richclient/config/DefaultApplicationLifecycleAdvisorTests.java =================================================================== --- trunk/spring-richclient/support/src/test/java/org/springframework/richclient/config/DefaultApplicationLifecycleAdvisorTests.java 2007-01-16 20:16:54 UTC (rev 1673) +++ trunk/spring-richclient/support/src/test/java/org/springframework/richclient/config/DefaultApplicationLifecycleAdvisorTests.java 2007-01-16 20:22:31 UTC (rev 1674) @@ -17,12 +17,14 @@ import junit.framework.TestCase; +import org.easymock.EasyMock; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.context.event.SimpleApplicationEventMulticaster; import org.springframework.context.support.StaticApplicationContext; import org.springframework.richclient.application.Application; +import org.springframework.richclient.application.ApplicationWindow; import org.springframework.richclient.application.config.DefaultApplicationLifecycleAdvisor; /** @@ -59,6 +61,8 @@ public static class TestAdvisor extends DefaultApplicationLifecycleAdvisor { public TestAdvisor() { setStartingPageId("whatever"); + ApplicationWindow window = (ApplicationWindow) EasyMock.createMock(ApplicationWindow.class); + setOpeningWindow(window); } @@ -69,6 +73,8 @@ public BeanFactory getBeanFactory() { return getCommandBarFactory(); } + + } public static class TestCommand implements ApplicationListener { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys - and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ spring-rich-c-cvs mailing list spring-rich-c-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/spring-rich-c-cvs