1 87 package org.codehaus.loom.components.configuration.merger; 88 89 import java.util.HashSet ; 90 import org.codehaus.dna.Configuration; 91 import org.codehaus.dna.ConfigurationException; 92 import org.codehaus.dna.impl.ConfigurationUtil; 93 import org.codehaus.dna.impl.DefaultConfiguration; 94 95 105 public class ConfigurationSplitter 106 { 107 120 public static Configuration split( final Configuration merged, 121 final Configuration base ) 122 throws ConfigurationException 123 { 124 final DefaultConfiguration layer = doSplit( merged, base, false ); 125 126 layer.makeReadOnly(); 127 128 return layer; 129 } 130 131 private static DefaultConfiguration doSplit( final Configuration merged, 132 final Configuration base, 133 final boolean isMerged ) 134 throws ConfigurationException 135 { 136 final DefaultConfiguration layer = 137 new DefaultConfiguration( base.getName(), 138 merged.getPath(), 139 "Merged [merged: " + 140 merged.getLocation() 141 + ", base: " + base.getLocation() + "]" ); 142 143 copyAttributes( layer, merged, base ); 144 copyValue( layer, merged, base ); 145 copyChildren( layer, merged, base ); 146 147 if( isMerged ) 148 { 149 layer.setAttribute( Constants.MERGE_ATTR, "true" ); 150 } 151 152 return layer; 153 } 154 155 private static DefaultConfiguration doSplit( final Configuration merged, 156 final Configuration base, 157 final String keyAttr ) 158 throws ConfigurationException 159 { 160 final DefaultConfiguration layer = doSplit( merged, base, true ); 161 162 if( null != keyAttr ) 163 { 164 layer.setAttribute( Constants.KEY_ATTR, keyAttr ); 165 } 166 167 return layer; 168 } 169 170 private static void copyChildren( final DefaultConfiguration layer, 171 final Configuration merged, 172 final Configuration base ) 173 throws ConfigurationException 174 { 175 final Configuration[] kids = merged.getChildren(); 176 177 for( int i = 0; i < kids.length; i++ ) 178 { 179 final Configuration mergedChild = kids[ i ]; 180 final String name = mergedChild.getName(); 181 final Configuration[] mc = merged.getChildren( name ); 182 final Configuration[] bc = base.getChildren( name ); 183 184 Configuration mergedWith; 185 String keyAttr = null; 186 187 if( bc.length > mc.length ) 188 { 189 throw new UnsupportedOperationException ( "Unable to mask children from base " 190 + "in layer" ); 191 } 192 else if( bc.length == 0 ) 193 { 194 mergedWith = null; 195 } 196 else if( mc.length == 1 && bc.length == 1 ) 197 { 198 mergedWith = bc[ 0 ]; 199 } 200 else { 202 keyAttr = findUniqueAttributeName( mc ); 203 204 final String keyValue = mergedChild.getAttribute( keyAttr ); 205 final Configuration[] matches = 206 ConfigurationMerger.match( base, name, keyAttr, keyValue ); 207 208 if( matches.length == 1 ) 209 { 210 mergedWith = matches[ 0 ]; 211 } 212 else 213 { 214 throw new ConfigurationException( "Multiple children in base with name '" 215 + 216 name + 217 "' and attr '" + 218 keyAttr 219 + " = " + keyValue + "'", 220 merged.getPath(), 221 merged.getLocation() ); 222 } 223 } 224 225 if( null == mergedWith ) 226 { 227 layer.addChild( kids[ i ] ); 228 } 229 else if( !ConfigurationUtil.equals( kids[ i ], mergedWith ) ) 230 { 231 final DefaultConfiguration layerChild = doSplit( kids[ i ], 232 mergedWith, 233 keyAttr ); 234 235 layerChild.makeReadOnly(); 236 237 layer.addChild( layerChild ); 238 } 239 } 240 } 241 242 private static String findUniqueAttributeName( final Configuration[] c ) 243 throws ConfigurationException 244 { 245 final HashSet testedAttributes = new HashSet (); 246 String uniqueAttr = null; 247 248 for( int i = 0; i < c.length; i++ ) 249 { 250 final String [] attrs = c[ i ].getAttributeNames(); 251 252 for( int j = 0; j < attrs.length; j++ ) 253 { 254 final String attr = attrs[ j ]; 255 256 if( !testedAttributes.contains( attr ) 257 && 258 isUniqueAttribute( attr, 259 c[ i ].getAttribute( attr ), 260 i, 261 c ) ) 262 { 263 if( null == uniqueAttr ) 264 { 265 uniqueAttr = attr; 266 } 267 else 268 { 269 throw new ConfigurationException( 270 "Multiple unique attributes for child " 271 + 272 "[name: " + 273 c[ 0 ].getName() 274 + 275 ", unique1: " + 276 uniqueAttr 277 + 278 ", unique2: " + 279 attr + 280 "]", 281 "", 282 "" ); 283 } 284 } 285 else 286 { 287 testedAttributes.add( attr ); 288 } 289 } 290 } 291 292 if( null == uniqueAttr ) 293 { 294 throw new ConfigurationException( 295 "Unable to find unique attribute for " 296 + 297 "children of name: " + 298 c[ 0 ].getName(), 299 c[ 0 ].getPath(), 300 c[ 0 ].getLocation() ); 301 } 302 303 return uniqueAttr; 304 } 305 306 private static boolean isUniqueAttribute( final String attr, 307 final String value, 308 final int currentConfig, 309 final Configuration[] c ) 310 { 311 for( int i = 0; i < c.length; i++ ) 312 { 313 if( i != currentConfig ) 314 { 315 try 316 { 317 if( value.equals( c[ i ].getAttribute( attr ) ) ) 318 { 319 return false; 320 } 321 } 322 catch( ConfigurationException e ) 323 { 324 return false; 325 } 326 } 327 } 328 329 return true; 330 } 331 332 private static void copyValue( final DefaultConfiguration layer, 333 final Configuration merged, 334 final Configuration base ) 335 { 336 final String value = merged.getValue( null ); 337 338 if( null != value ) 339 { 340 try 341 { 342 final String baseValue = base.getValue(); 343 344 if( !value.equals( baseValue ) ) 345 { 346 layer.setValue( value ); 347 } 348 } 349 catch( ConfigurationException e ) 350 { 351 layer.setValue( value ); 352 } 353 } 354 } 355 356 private static void copyAttributes( final DefaultConfiguration layer, 357 final Configuration merged, 358 final Configuration base ) 359 throws ConfigurationException 360 { 361 final String [] mergedAttr = merged.getAttributeNames(); 362 363 for( int i = 0; i < mergedAttr.length; i++ ) 364 { 365 final String value = merged.getAttribute( mergedAttr[ i ] ); 366 367 try 368 { 369 final String baseValue = base.getAttribute( mergedAttr[ i ] ); 370 371 if( !value.equals( baseValue ) ) 372 { 373 layer.setAttribute( mergedAttr[ i ], value ); 374 } 375 } 376 catch( ConfigurationException e ) 377 { 378 layer.setAttribute( mergedAttr[ i ], value ); 380 } 381 } 382 } 383 384 } 385 | Popular Tags |