Index: src/java/org/apache/commons/chain/CatalogFactory.java
===================================================================
RCS file: /home/cvs/jakarta-commons/chain/src/java/org/apache/commons/chain/CatalogFactory.java,v
retrieving revision 1.5
diff -u -d -b -w -u -r1.5 CatalogFactory.java
--- src/java/org/apache/commons/chain/CatalogFactory.java 30 Nov 2004 05:52:22 -0000 1.5
+++ src/java/org/apache/commons/chain/CatalogFactory.java 30 Dec 2004 19:48:33 -0000
@@ -20,18 +20,37 @@
import java.util.Map;
import org.apache.commons.chain.impl.CatalogFactoryBase;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
/**
*
A {@link CatalogFactory} is a class used to store and retrieve
* {@link Catalog}s. The factory allows for a default {@link Catalog}
* as well as {@link Catalog}s stored with a name key. Follows the
* Factory pattern (see GoF).
*
+ * The base CatalogFactory implementation also implements
+ * a resolution mechanism which allows lookup of a command based on a single string
+ * which encodes both the catalog and command names.
+ *
* @author Sean Schofield
* @version $Revision: 1.5 $ $Date: 2004/11/30 05:52:22 $
*/
public abstract class CatalogFactory {
+ /**
+ * The Log instance for this class.
+ */
+ private static final Log log = LogFactory.getLog(CatalogFactory.class);
+
+ /**
+ * Values passed to the getCommand(String) method should
+ * use ":" as the delimiter between the "catalog" name and the "command" name.
+ *
+ */
+ public static final String DELIMITER = ":";
+
// --------------------------------------------------------- Public Methods
@@ -80,7 +99,64 @@
*/
public abstract Iterator getNames();
+ /**
+ * Return a Command based on the given ID.
+ * At this time, the structure of the ID is relatively simple: If the
+ * ID contains a colon (:) character, treat the segment of the ID
+ * up to (but not including) the colon as the name of a catalog, and the
+ * segment following the colon as a command name within that catalog. If the
+ * given ID contains no colon, treat the ID as the name of a command in
+ * the default catalog.
+ * To preserve the possibility of future extensions to this lookup mechanism,
+ * the colon character should be considered reserved, and should not be used in
+ * command names. commandID values which contain more than one delimiter
+ * will cause an IllegalArgumentException to be thrown.
+ *
+ * @param commandID the identifier of the command to return.
+ * @return the command located with commandID, or null if either the command name
+ * or the catalog name cannot be resolved.
+ * @throws IllegalArgumentException if the commandID contains more than one delimiter.
+ */
+ public Command getCommand(String commandID) throws IllegalArgumentException {
+
+ String commandName = commandID;
+ String catalogName = null;
+ Catalog catalog = null;
+
+ if (commandID != null) {
+ int splitPos = commandID.indexOf(DELIMITER);
+ if (splitPos != -1) {
+ catalogName = commandID.substring(0, splitPos);
+ commandName = commandID.substring(splitPos + 1);
+ if (commandName.indexOf(DELIMITER) != -1) {
+ throw new IllegalArgumentException("ID [" +
+ commandID +
+ "] has too many delimiters (reserved for future use)");
+ }
+
+ }
+ }
+
+ if (catalogName != null) {
+ catalog = this.getCatalog(catalogName);
+
+ if (catalog == null) {
+ log.warn("No catalog found for name: " + catalogName + ".");
+ return null;
+ }
+
+ } else {
+ catalog = this.getCatalog();
+ if (catalog == null) {
+ log.warn("No default catalog found.");
+ return null;
+ }
+
+ }
+
+ return catalog.getCommand(commandName);
+ }
// ------------------------------------------------------- Static Variables
Index: src/test/org/apache/commons/chain/impl/CatalogFactoryBaseTestCase.java
===================================================================
RCS file: /home/cvs/jakarta-commons/chain/src/test/org/apache/commons/chain/impl/CatalogFactoryBaseTestCase.java,v
retrieving revision 1.3
diff -u -d -b -w -u -r1.3 CatalogFactoryBaseTestCase.java
--- src/test/org/apache/commons/chain/impl/CatalogFactoryBaseTestCase.java 9 Dec 2004 05:23:14 -0000 1.3
+++ src/test/org/apache/commons/chain/impl/CatalogFactoryBaseTestCase.java 30 Dec 2004 19:48:33 -0000
@@ -131,6 +131,48 @@
}
+ public void testCatalogIdentifier() {
+
+ Catalog defaultCatalog = new CatalogBase();
+ Command defaultFoo = new NonDelegatingCommand();
+ defaultCatalog.addCommand("foo", defaultFoo);
+ Command fallback = new NonDelegatingCommand();
+ defaultCatalog.addCommand("noSuchCatalog:fallback", fallback);
+
+ factory.setCatalog(defaultCatalog);
+
+ Catalog specificCatalog = new CatalogBase();
+ Command specificFoo = new NonDelegatingCommand();
+ specificCatalog.addCommand("foo", specificFoo);
+ factory.addCatalog("specific", specificCatalog);
+
+ Command command = factory.getCommand("foo");
+ assertSame(defaultFoo, command);
+
+ command = factory.getCommand("specific:foo");
+ assertSame(specificFoo, command);
+
+ command = factory.getCommand("void");
+ assertNull(command);
+
+ command = factory.getCommand("foo:void");
+ assertNull(command);
+
+ command = factory.getCommand("specific:void");
+ assertNull(command);
+
+ command = factory.getCommand("noSuchCatalog:fallback");
+ assertNull(command);
+
+ try {
+ command = factory.getCommand("multiple:delimiters:reserved");
+ fail("A command ID with more than one delimiter should throw an IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected behavior
+ }
+
+ }
// ------------------------------------------------------- Support Methods