1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.chain.config; 18 19 import org.apache.commons.chain.Catalog; 20 import org.apache.commons.chain.Chain; 21 import org.apache.commons.chain.Command; 22 import org.apache.commons.chain.Context; 23 import org.apache.commons.digester.Rule; 24 import org.xml.sax.Attributes; 25 26 /** 27 * Digester rule that will cause the top-most element on the Digester 28 * stack (if it is a {@link Command} to be registered with the next-to-top 29 * element on the Digester stack (if it is a {@link Catalog} or {@link Chain}). 30 * To be registered with a {@link Catalog}, the top-most element must contain 31 * a value for the specified attribute that contains the name under which 32 * it should be registered. 33 * 34 * @author Craig R. McClanahan 35 * @version $Revision$ $Date$ 36 */ 37 class ConfigRegisterRule extends Rule { 38 39 // ----------------------------------------------------- Instance Variables 40 41 /** 42 * The name of the attribute under which we can retrieve the name 43 * this command should be registered with. 44 */ 45 private final String nameAttribute; 46 47 // ----------------------------------------------------------- Constructors 48 49 /** 50 * Construct a new instance of this rule that looks for an attribute 51 * with the specified name. 52 * 53 * @param nameAttribute Name of the attribute containing the name under 54 * which this command should be registered 55 */ 56 ConfigRegisterRule(String nameAttribute) { 57 this.nameAttribute = nameAttribute; 58 } 59 60 // --------------------------------------------------------- Public Methods 61 62 /** 63 * Register the top {@link Command} if appropriate. 64 * 65 * @param namespace the namespace URI of the matching element, or an 66 * empty string if the parser is not namespace aware or the 67 * element has no namespace 68 * @param name the local name if the parser is namespace aware, or 69 * just the element name otherwise 70 * @param attributes The attribute list of this element 71 */ 72 @Override 73 public void begin(String namespace, String name, Attributes attributes) 74 throws Exception { 75 76 // Is the top object a Command? 77 Object top = digester.peek(0); 78 if (!(top instanceof Command)) { 79 return; 80 } 81 82 /* All commands can consume a generic context. Here we depend on 83 * the configuration being correct because the rule binding is 84 * dynamic. */ 85 @SuppressWarnings("unchecked") 86 Command<Context> command = (Command<Context>) top; 87 88 // Is the next object a Catalog or a Chain? 89 Object next = digester.peek(1); 90 if (next == null) { 91 return; 92 } 93 94 // Register the top element appropriately 95 if (next instanceof Catalog) { 96 String nameValue = attributes.getValue(nameAttribute); 97 if (nameValue != null) { 98 /* We are dynamically building a catalog and assigning 99 * generics to the most base types possible. */ 100 @SuppressWarnings("unchecked") 101 Catalog<Context> catalog = (Catalog<Context>) next; 102 catalog.addCommand(nameValue, command); 103 } 104 } else if (next instanceof Chain) { 105 /* Like above - the chain is being dynamically generated, 106 * so we can add a generic context signature at compile-time. */ 107 @SuppressWarnings("unchecked") 108 Chain<Context> chain = (Chain<Context>) next; 109 chain.addCommand(command); 110 } 111 } 112 }