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