You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@avalon.apache.org by pr...@apache.org on 2002/07/26 21:18:44 UTC
cvs commit: jakarta-avalon-excalibur/configuration/src/java/org/apache/excalibur/configuration/merged ConfigurationSplitter.java
proyal 2002/07/26 12:18:44
Added: configuration/src/java/org/apache/excalibur/configuration/merged
ConfigurationSplitter.java
Log:
Class to "split" a configuration. Given a Configuration
and a "base" configuration, generate the "layer" that when
merged with the base yields the original Configuration
Revision Changes Path
1.1 jakarta-avalon-excalibur/configuration/src/java/org/apache/excalibur/configuration/merged/ConfigurationSplitter.java
Index: ConfigurationSplitter.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.excalibur.configuration.merged;
import java.util.HashSet;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.DefaultConfiguration;
import org.apache.excalibur.configuration.ConfigurationUtil;
/**
* The ConfigurationSplitter will take two Configuration objects and calculate the
* differences between them.
*
* The resulting Configuration will contain special attribute that can be used by the
* ConfigurationMerger to reconstruct the original Configuration
*
* @see ConfigurationMerger
* @author <a href="mailto:proyal@apache.org">Peter Royal</a>
*/
public class ConfigurationSplitter
{
/**
* Split a configuration, given a merged configuration and a base configuration.
* Functionally equivalent to producing a <i>diff</i> between the merged and base.
*
* @param merged Configuration that is a combination of the <i>result</i> and
* the <i>base</i> param
* @param base Configuration that when merged with the <i>result</i> will yield the
* <i>merged</i> param
*
* @return a Configuration that when merged with the <i>base</i> will yeild the
* <i>merged</i>
*
* @throws ConfigurationException if unable to split
*/
public static Configuration split( final Configuration merged, final Configuration base )
throws ConfigurationException
{
final DefaultConfiguration layer = doSplit( merged, base, false );
layer.makeReadOnly();
return layer;
}
private static DefaultConfiguration doSplit( final Configuration merged,
final Configuration base,
final boolean isMerged )
throws ConfigurationException
{
final DefaultConfiguration layer =
new DefaultConfiguration( base.getName(),
"Merged [merged: " + merged.getLocation()
+ ", base: " + base.getLocation() + "]" );
copyAttributes( layer, merged, base );
copyValue( layer, merged, base );
copyChildren( layer, merged, base );
if( isMerged )
{
layer.setAttribute( Constants.MERGE_ATTR, "true" );
}
return layer;
}
private static DefaultConfiguration doSplit( final Configuration merged,
final Configuration base,
final String keyAttr )
throws ConfigurationException
{
final DefaultConfiguration layer = doSplit( merged, base, true );
if( null != keyAttr )
{
layer.setAttribute( Constants.KEY_ATTR, keyAttr );
}
return layer;
}
private static void copyChildren( final DefaultConfiguration layer,
final Configuration merged,
final Configuration base )
throws ConfigurationException
{
final Configuration[] kids = merged.getChildren();
for( int i = 0; i < kids.length; i++ )
{
final Configuration mergedChild = kids[i];
final String name = mergedChild.getName();
final Configuration[] mc = merged.getChildren( name );
final Configuration[] bc = base.getChildren( name );
Configuration mergedWith;
String keyAttr = null;
if( bc.length > mc.length )
{
throw new UnsupportedOperationException( "Unable to mask children from base "
+ "in layer" );
}
else if( bc.length == 0 )
{
mergedWith = null;
}
else if( mc.length == 1 && bc.length == 1 )
{
mergedWith = bc[0];
}
else //we know that mc.length > 1 here, so find the "key" attribute
{
keyAttr = findUniqueAttributeName( mc );
final String keyValue = mergedChild.getAttribute( keyAttr );
final Configuration[] matches =
ConfigurationUtil.match( base, name, keyAttr, keyValue );
if( matches.length == 1 )
{
mergedWith = matches[0];
}
else
{
throw new ConfigurationException( "Multiple children in base with name '"
+ name + "' and attr '" + keyAttr
+ " = " + keyValue + "'" );
}
}
if( null == mergedWith )
{
layer.addChild( kids[i] );
}
else if( !ConfigurationUtil.equals( kids[i], mergedWith ) )
{
final DefaultConfiguration layerChild = doSplit( kids[i], mergedWith, keyAttr );
layerChild.makeReadOnly();
layer.addChild( layerChild );
}
}
}
private static String findUniqueAttributeName( final Configuration[] c )
throws ConfigurationException
{
final HashSet testedAttributes = new HashSet();
String uniqueAttr = null;
for( int i = 0; i < c.length; i++ )
{
final String[] attrs = c[i].getAttributeNames();
for( int j = 0; j < attrs.length; j++ )
{
final String attr = attrs[j];
if( !testedAttributes.contains( attr )
&& isUniqueAttribute( attr, c[i].getAttribute( attr ), i, c ) )
{
if( null == uniqueAttr )
{
uniqueAttr = attr;
}
else
{
throw new ConfigurationException( "Multiple unique attributes for child "
+ "[name: " + c[0].getName()
+ ", unique1: " + uniqueAttr
+ ", unique2: " + attr + "]" );
}
}
else
{
testedAttributes.add( attr );
}
}
}
if( null == uniqueAttr )
{
throw new ConfigurationException( "Unable to find unique attribute for "
+ "children of name: " + c[0].getName() );
}
return uniqueAttr;
}
private static boolean isUniqueAttribute( final String attr,
final String value,
final int currentConfig,
final Configuration[] c )
{
for( int i = 0; i < c.length; i++ )
{
if( i != currentConfig )
{
try
{
if( value.equals( c[i].getAttribute( attr ) ) )
{
return false;
}
}
catch( ConfigurationException e )
{
return false;
}
}
}
return true;
}
private static void copyValue( final DefaultConfiguration layer,
final Configuration merged,
final Configuration base )
{
final String value = merged.getValue( null );
if( null != value )
{
try
{
final String baseValue = base.getValue();
if( !value.equals( baseValue ) )
{
layer.setValue( value );
}
}
catch( ConfigurationException e )
{
layer.setValue( value );
}
}
}
private static void copyAttributes( final DefaultConfiguration layer,
final Configuration merged,
final Configuration base )
throws ConfigurationException
{
final String[] mergedAttr = merged.getAttributeNames();
for( int i = 0; i < mergedAttr.length; i++ )
{
final String value = merged.getAttribute( mergedAttr[i] );
try
{
final String baseValue = base.getAttribute( mergedAttr[i] );
if( !value.equals( baseValue ) )
{
layer.setAttribute( mergedAttr[i], value );
}
}
catch( ConfigurationException e )
{
//not in base add to layer
layer.setAttribute( mergedAttr[i], value );
}
}
}
}
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>