/* $Id$
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.commons.digester;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * <p><code>Rules</code> <em>Decorator</em> that returns default rules 
 * when no matches are returned by the wrapped implementation.</p>
 *
 * <p>This allows default <code>Rule</code> instances to be added to any 
 * existing <code>Rules</code> implementation. These default <code>Rule</code> 
 * instances will be returned for any match for which the wrapped 
 * implementation does not return any matches.</p>
 * <p> For example,
 * <pre>
 *   Rule alpha;
 *   ...
 *   WithDefaultsRulesWrapper rules = new WithDefaultsRulesWrapper(new BaseRules());
 *   rules.addDefault(alpha);
 *   ...
 *   digester.setRules(rules);
 *   ...
 * </pre>
 * when a pattern does not match any other rule, then rule alpha will be called.
 * </p>
 * <p><code>WithDefaultsRulesWrapper</code> follows the <em>Decorator</em> pattern.</p>
 *
 * @since 1.6
 */

public class WithDefaultsRulesWrapper implements Rules {

    // --------------------------------------------------------- Fields
    
    /** The Rules implementation that this class wraps. */
    private Rules wrappedRules;
    /** Rules to be fired when the wrapped implementations returns none. */
    private List defaultRules = new ArrayList();
    /** All rules (preserves order in which they were originally added) */
    private List allRules = new ArrayList();
    
    // --------------------------------------------------------- Constructor
    
    /** 
     * Base constructor.
     *
     * @param wrappedRules the wrapped <code>Rules</code> implementation, not null
     * @throws IllegalArgumentException when <code>wrappedRules</code> is null
     */
    public WithDefaultsRulesWrapper(Rules wrappedRules) {
        if (wrappedRules == null) {
            throw new IllegalArgumentException("Wrapped rules must not be null");
        }
        this.wrappedRules = wrappedRules;
    }

    // --------------------------------------------------------- Properties
    
    /** Gets digester using these Rules */
    public Digester getDigester() {
        return wrappedRules.getDigester();
    }
    
    /** Sets digeseter using these Rules */
    public void setDigester(Digester digester) {
        wrappedRules.setDigester(digester);
        Iterator it = defaultRules.iterator();
        while (it.hasNext()) {
            Rule rule = (Rule) it.next();
            rule.setDigester(digester);
        }
    }
    
    /** Gets namespace to apply to Rule's added */
    public String getNamespaceURI() {
        return wrappedRules.getNamespaceURI();
    }
    
    /** Sets namespace to apply to Rule's added subsequently */
    public void setNamespaceURI(String namespaceURI) {
        wrappedRules.setNamespaceURI(namespaceURI);
    }
    
    /** Gets Rule's which will be fired when the wrapped implementation returns no matches */
    public List getDefaults() {
        return defaultRules;
    }
    
    // --------------------------------------------------------- Public Methods
    
    public List match(String pattern) {
        return match("", pattern);
    }
    
    /**
     * Return list of rules matching given pattern.
     * If wrapped implementation returns any matches return those.
     * Otherwise, return default matches.
     */
    public List match(String namespaceURI, String pattern) {
        List matches = wrappedRules.match(namespaceURI, pattern);
        if (matches ==  null || matches.isEmpty()) {
            // a little bit of defensive programming
            return new ArrayList(defaultRules);
        }
        // otherwise
        return matches;
    }
    
    /** Adds a rule to be fired when wrapped implementation returns no matches */
    public void addDefault(Rule rule) {
        // set up rule
        if (wrappedRules.getDigester() != null) {
            rule.setDigester(wrappedRules.getDigester());
        }
        
        if (wrappedRules.getNamespaceURI() != null) {
            rule.setNamespaceURI(wrappedRules.getNamespaceURI());
        }
        
        defaultRules.add(rule);
        allRules.add(rule);
    }
    
    /** Gets all rules */
    public List rules() {
        return allRules;
    }
    
    /** Clears all Rule's */
    public void clear() {
        wrappedRules.clear();
        allRules.clear();
        defaultRules.clear();
    }
    
    /** 
     * Adds a Rule to be fired on given pattern.
     * Pattern matching is delegated to wrapped implementation.
     */
    public void add(String pattern, Rule rule) {
        wrappedRules.add(pattern, rule);
        allRules.add(rule);
    }
}

@@ -878,35 +878,8 @@
 st;%0A
-import java.util.Iterator;%0A
 impo
@@ -897,16 +897,16 @@
 l.List;%0A
+
 %0A/**%0A * 
@@ -2062,16 +2062,22 @@
 ate List
+%3CRule%3E
  default
@@ -2089,32 +2089,38 @@
  = new ArrayList
+%3CRule%3E
 ();%0A    /** All 
@@ -2198,16 +2198,22 @@
 ate List
+%3CRule%3E
  allRule
@@ -2229,16 +2229,22 @@
 rrayList
+%3CRule%3E
 ();%0A    
@@ -3135,90 +3135,13 @@
     
-Iterator it = defaultRules.iterator();%0A        while (it.hasNext()) %7B%0A            
+for (
 Rule
@@ -3150,27 +3150,25 @@
 ule 
-= (
+: default
 Rule
+s
 ) 
-it.next();
+%7B
 %0A   
@@ -3663,16 +3663,22 @@
 lic List
+%3CRule%3E
  getDefa
@@ -3818,32 +3818,38 @@
 %0A    public List
+%3CRule%3E
  match(String pa
@@ -4091,24 +4091,30 @@
  public List
+%3CRule%3E
  match(Strin
@@ -4159,16 +4159,22 @@
     List
+%3CRule%3E
  matches
@@ -4357,16 +4357,22 @@
 rrayList
+%3CRule%3E
 (default
@@ -4945,32 +4945,32 @@
 ts all rules */%0A
-
     public List 
@@ -4968,16 +4968,22 @@
 lic List
+%3CRule%3E
  rules()

Use generics and for-each.