1 50 51 package org.apache.excalibur.configuration.merged; 52 53 import java.util.HashSet ; 54 55 import org.apache.avalon.framework.configuration.Configuration; 56 import org.apache.avalon.framework.configuration.ConfigurationException; 57 import org.apache.avalon.framework.configuration.DefaultConfiguration; 58 import org.apache.excalibur.configuration.ConfigurationUtil; 59 60 70 public class ConfigurationSplitter 71 { 72 86 public static Configuration split( final Configuration merged, final Configuration base ) 87 throws ConfigurationException 88 { 89 final DefaultConfiguration layer = doSplit( merged, base, false ); 90 91 layer.makeReadOnly(); 92 93 return layer; 94 } 95 96 private static DefaultConfiguration doSplit( final Configuration merged, 97 final Configuration base, 98 final boolean isMerged ) 99 throws ConfigurationException 100 { 101 final DefaultConfiguration layer = 102 new DefaultConfiguration( base.getName(), 103 "Merged [merged: " + merged.getLocation() 104 + ", base: " + base.getLocation() + "]" ); 105 106 copyAttributes( layer, merged, base ); 107 copyValue( layer, merged, base ); 108 copyChildren( layer, merged, base ); 109 110 if( isMerged ) 111 { 112 layer.setAttribute( Constants.MERGE_ATTR, "true" ); 113 } 114 115 return layer; 116 } 117 118 private static DefaultConfiguration doSplit( final Configuration merged, 119 final Configuration base, 120 final String keyAttr ) 121 throws ConfigurationException 122 { 123 final DefaultConfiguration layer = doSplit( merged, base, true ); 124 125 if( null != keyAttr ) 126 { 127 layer.setAttribute( Constants.KEY_ATTR, keyAttr ); 128 } 129 130 return layer; 131 } 132 133 private static void copyChildren( final DefaultConfiguration layer, 134 final Configuration merged, 135 final Configuration base ) 136 throws ConfigurationException 137 { 138 final Configuration[] kids = merged.getChildren(); 139 140 for( int i = 0; i < kids.length; i++ ) 141 { 142 final Configuration mergedChild = kids[ i ]; 143 final String name = mergedChild.getName(); 144 final Configuration[] mc = merged.getChildren( name ); 145 final Configuration[] bc = base.getChildren( name ); 146 147 Configuration mergedWith; 148 String keyAttr = null; 149 150 if( bc.length > mc.length ) 151 { 152 throw new UnsupportedOperationException ( "Unable to mask children from base " 153 + "in layer" ); 154 } 155 else if( bc.length == 0 ) 156 { 157 mergedWith = null; 158 } 159 else if( mc.length == 1 && bc.length == 1 ) 160 { 161 mergedWith = bc[ 0 ]; 162 } 163 else { 165 keyAttr = findUniqueAttributeName( mc ); 166 167 final String keyValue = mergedChild.getAttribute( keyAttr ); 168 final Configuration[] matches = 169 ConfigurationUtil.match( base, name, keyAttr, keyValue ); 170 171 if( matches.length == 1 ) 172 { 173 mergedWith = matches[ 0 ]; 174 } 175 else 176 { 177 throw new ConfigurationException( "Multiple children in base with name '" 178 + name + "' and attr '" + keyAttr 179 + " = " + keyValue + "'" ); 180 } 181 } 182 183 if( null == mergedWith ) 184 { 185 layer.addChild( kids[ i ] ); 186 } 187 else if( !ConfigurationUtil.equals( kids[ i ], mergedWith ) ) 188 { 189 final DefaultConfiguration layerChild = doSplit( kids[ i ], mergedWith, keyAttr ); 190 191 layerChild.makeReadOnly(); 192 193 layer.addChild( layerChild ); 194 } 195 } 196 } 197 198 private static String findUniqueAttributeName( final Configuration[] c ) 199 throws ConfigurationException 200 { 201 final HashSet testedAttributes = new HashSet (); 202 String uniqueAttr = null; 203 204 for( int i = 0; i < c.length; i++ ) 205 { 206 final String [] attrs = c[ i ].getAttributeNames(); 207 208 for( int j = 0; j < attrs.length; j++ ) 209 { 210 final String attr = attrs[ j ]; 211 212 if( !testedAttributes.contains( attr ) 213 && isUniqueAttribute( attr, c[ i ].getAttribute( attr ), i, c ) ) 214 { 215 if( null == uniqueAttr ) 216 { 217 uniqueAttr = attr; 218 } 219 else 220 { 221 throw new ConfigurationException( "Multiple unique attributes for child " 222 + "[name: " + c[ 0 ].getName() 223 + ", unique1: " + uniqueAttr 224 + ", unique2: " + attr + "]" ); 225 } 226 } 227 else 228 { 229 testedAttributes.add( attr ); 230 } 231 } 232 } 233 234 if( null == uniqueAttr ) 235 { 236 throw new ConfigurationException( "Unable to find unique attribute for " 237 + "children of name: " + c[ 0 ].getName() ); 238 } 239 240 return uniqueAttr; 241 } 242 243 private static boolean isUniqueAttribute( final String attr, 244 final String value, 245 final int currentConfig, 246 final Configuration[] c ) 247 { 248 for( int i = 0; i < c.length; i++ ) 249 { 250 if( i != currentConfig ) 251 { 252 try 253 { 254 if( value.equals( c[ i ].getAttribute( attr ) ) ) 255 { 256 return false; 257 } 258 } 259 catch( ConfigurationException e ) 260 { 261 return false; 262 } 263 } 264 } 265 266 return true; 267 } 268 269 private static void copyValue( final DefaultConfiguration layer, 270 final Configuration merged, 271 final Configuration base ) 272 { 273 final String value = merged.getValue( null ); 274 275 if( null != value ) 276 { 277 try 278 { 279 final String baseValue = base.getValue(); 280 281 if( !value.equals( baseValue ) ) 282 { 283 layer.setValue( value ); 284 } 285 } 286 catch( ConfigurationException e ) 287 { 288 layer.setValue( value ); 289 } 290 } 291 } 292 293 private static void copyAttributes( final DefaultConfiguration layer, 294 final Configuration merged, 295 final Configuration base ) 296 throws ConfigurationException 297 { 298 final String [] mergedAttr = merged.getAttributeNames(); 299 300 for( int i = 0; i < mergedAttr.length; i++ ) 301 { 302 final String value = merged.getAttribute( mergedAttr[ i ] ); 303 304 try 305 { 306 final String baseValue = base.getAttribute( mergedAttr[ i ] ); 307 308 if( !value.equals( baseValue ) ) 309 { 310 layer.setAttribute( mergedAttr[ i ], value ); 311 } 312 } 313 catch( ConfigurationException e ) 314 { 315 layer.setAttribute( mergedAttr[ i ], value ); 317 } 318 } 319 } 320 321 } 322 | Popular Tags |