001 package org.apache.commons.digester3; 002 003 /* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022 import java.util.ArrayList; 023 import java.util.List; 024 025 import org.xml.sax.Attributes; 026 027 /** 028 * <p> 029 * <code>Rules</code> <em>Decorator</em> that returns default rules when no matches are returned by the wrapped 030 * implementation. 031 * </p> 032 * <p> 033 * This allows default <code>Rule</code> instances to be added to any existing <code>Rules</code> implementation. These 034 * default <code>Rule</code> instances will be returned for any match for which the wrapped implementation does not 035 * return any matches. 036 * </p> 037 * <p> 038 * For example, 039 * 040 * <pre> 041 * Rule alpha; 042 * ... 043 * WithDefaultsRulesWrapper rules = new WithDefaultsRulesWrapper(new BaseRules()); 044 * rules.addDefault(alpha); 045 * ... 046 * digester.setRules(rules); 047 * ... 048 * </pre> 049 * 050 * when a pattern does not match any other rule, then rule alpha will be called. 051 * </p> 052 * <p> 053 * <code>WithDefaultsRulesWrapper</code> follows the <em>Decorator</em> pattern. 054 * </p> 055 * 056 * @since 1.6 057 */ 058 public class WithDefaultsRulesWrapper 059 implements Rules 060 { 061 062 // --------------------------------------------------------- Fields 063 064 /** The Rules implementation that this class wraps. */ 065 private Rules wrappedRules; 066 067 /** Rules to be fired when the wrapped implementations returns none. */ 068 private List<Rule> defaultRules = new ArrayList<Rule>(); 069 070 /** All rules (preserves order in which they were originally added) */ 071 private List<Rule> allRules = new ArrayList<Rule>(); 072 073 // --------------------------------------------------------- Constructor 074 075 /** 076 * Base constructor. 077 * 078 * @param wrappedRules the wrapped <code>Rules</code> implementation, not null 079 */ 080 public WithDefaultsRulesWrapper( Rules wrappedRules ) 081 { 082 if ( wrappedRules == null ) 083 { 084 throw new IllegalArgumentException( "Wrapped rules must not be null" ); 085 } 086 this.wrappedRules = wrappedRules; 087 } 088 089 // --------------------------------------------------------- Properties 090 091 /** 092 * {@inheritDoc} 093 */ 094 public Digester getDigester() 095 { 096 return wrappedRules.getDigester(); 097 } 098 099 /** 100 * {@inheritDoc} 101 */ 102 public void setDigester( Digester digester ) 103 { 104 wrappedRules.setDigester( digester ); 105 for ( Rule rule : defaultRules ) 106 { 107 rule.setDigester( digester ); 108 } 109 } 110 111 /** 112 * {@inheritDoc} 113 */ 114 public String getNamespaceURI() 115 { 116 return wrappedRules.getNamespaceURI(); 117 } 118 119 /** 120 * {@inheritDoc} 121 */ 122 public void setNamespaceURI( String namespaceURI ) 123 { 124 wrappedRules.setNamespaceURI( namespaceURI ); 125 } 126 127 /** 128 * Gets Rule's which will be fired when the wrapped implementation returns no matches 129 * 130 * @return Rule's which will be fired when the wrapped implementation returns no matches 131 **/ 132 public List<Rule> getDefaults() 133 { 134 return defaultRules; 135 } 136 137 // --------------------------------------------------------- Public Methods 138 139 /** 140 * {@inheritDoc} 141 */ 142 public List<Rule> match( String namespaceURI, String pattern, String name, Attributes attributes ) 143 { 144 List<Rule> matches = wrappedRules.match( namespaceURI, pattern, name, attributes ); 145 if ( matches == null || matches.isEmpty() ) 146 { 147 // a little bit of defensive programming 148 return new ArrayList<Rule>( defaultRules ); 149 } 150 // otherwise 151 return matches; 152 } 153 154 /** 155 * Adds a rule to be fired when wrapped implementation returns no matches 156 * 157 * @param rule a Rule to be fired when wrapped implementation returns no matches 158 **/ 159 public void addDefault( Rule rule ) 160 { 161 // set up rule 162 if ( wrappedRules.getDigester() != null ) 163 { 164 rule.setDigester( wrappedRules.getDigester() ); 165 } 166 167 if ( wrappedRules.getNamespaceURI() != null ) 168 { 169 rule.setNamespaceURI( wrappedRules.getNamespaceURI() ); 170 } 171 172 defaultRules.add( rule ); 173 allRules.add( rule ); 174 } 175 176 /** 177 * {@inheritDoc} 178 */ 179 public List<Rule> rules() 180 { 181 return allRules; 182 } 183 184 /** 185 * {@inheritDoc} 186 */ 187 public void clear() 188 { 189 wrappedRules.clear(); 190 allRules.clear(); 191 defaultRules.clear(); 192 } 193 194 /** 195 * {@inheritDoc} 196 */ 197 public void add( String pattern, Rule rule ) 198 { 199 wrappedRules.add( pattern, rule ); 200 allRules.add( rule ); 201 } 202 203 }