KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > loom > components > configuration > merger > ConfigurationSplitter


1 /* ====================================================================
2  * Loom Software License, version 1.1
3  *
4  * Copyright (c) 2003, Loom Group. All rights reserved.
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in
14  * the documentation and/or other materials provided with the
15  * distribution.
16  *
17  * 3. Neither the name of the Loom Group nor the name "Loom" nor
18  * the names of its contributors may be used to endorse or promote
19  * products derived from this software without specific prior
20  * written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  * ====================================================================
36  *
37  * Loom includes code from the Apache Software Foundation
38  *
39  * ====================================================================
40  * The Apache Software License, Version 1.1
41  *
42  * Copyright (c) 1997-2003 The Apache Software Foundation. All rights
43  * reserved.
44  *
45  * Redistribution and use in source and binary forms, with or without
46  * modification, are permitted provided that the following conditions
47  * are met:
48  *
49  * 1. Redistributions of source code must retain the above copyright
50  * notice, this list of conditions and the following disclaimer.
51  *
52  * 2. Redistributions in binary form must reproduce the above copyright
53  * notice, this list of conditions and the following disclaimer in
54  * the documentation and/or other materials provided with the
55  * distribution.
56  *
57  * 3. The end-user documentation included with the redistribution,
58  * if any, must include the following acknowledgment:
59  * "This product includes software developed by the
60  * Apache Software Foundation (http://www.apache.org/)."
61  * Alternately, this acknowledgment may appear in the software
62  * itself, if and wherever such third-party acknowledgments
63  * normally appear.
64  *
65  * 4. The names "Jakarta", "Avalon", and "Apache Software Foundation"
66  * must not be used to endorse or promote products derived from this
67  * software without prior written permission. For written
68  * permission, please contact apache@apache.org.
69  *
70  * 5. Products derived from this software may not be called "Apache",
71  * nor may "Apache" appear in their name, without prior written
72  * permission of the Apache Software Foundation.
73  *
74  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
75  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
76  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
77  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
78  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
79  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
80  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
81  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
82  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
83  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
84  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
85  * SUCH DAMAGE.
86  */

87 package org.codehaus.loom.components.configuration.merger;
88
89 import java.util.HashSet JavaDoc;
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 /**
96  * The ConfigurationSplitter will take two Configuration objects and calculate
97  * the differences between them.
98  *
99  * The resulting Configuration will contain special attribute that can be used
100  * by the ConfigurationMerger to reconstruct the original Configuration
101  *
102  * @author <a HREF="mailto:proyal@apache.org">Peter Royal</a>
103  * @see ConfigurationMerger
104  */

105 public class ConfigurationSplitter
106 {
107     /**
108      * Split a configuration, given a merged configuration and a base
109      * configuration. Functionally equivalent to producing a <i>diff</i> between
110      * the merged and base.
111      *
112      * @param merged Configuration that is a combination of the <i>result</i>
113      * and the <i>base</i> param
114      * @param base Configuration that when merged with the <i>result</i> will
115      * yield the <i>merged</i> param
116      * @return a Configuration that when merged with the <i>base</i> will yeild
117      * the <i>merged</i>
118      * @throws ConfigurationException if unable to split
119      */

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 JavaDoc 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 JavaDoc name = mergedChild.getName();
181             final Configuration[] mc = merged.getChildren( name );
182             final Configuration[] bc = base.getChildren( name );
183
184             Configuration mergedWith;
185             String JavaDoc keyAttr = null;
186
187             if( bc.length > mc.length )
188             {
189                 throw new UnsupportedOperationException JavaDoc( "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 //we know that mc.length > 1 here, so find the "key" attribute
201
{
202                 keyAttr = findUniqueAttributeName( mc );
203
204                 final String JavaDoc 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 JavaDoc findUniqueAttributeName( final Configuration[] c )
243         throws ConfigurationException
244     {
245         final HashSet JavaDoc testedAttributes = new HashSet JavaDoc();
246         String JavaDoc uniqueAttr = null;
247
248         for( int i = 0; i < c.length; i++ )
249         {
250             final String JavaDoc[] attrs = c[ i ].getAttributeNames();
251
252             for( int j = 0; j < attrs.length; j++ )
253             {
254                 final String JavaDoc 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 JavaDoc attr,
307                                               final String JavaDoc 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 JavaDoc value = merged.getValue( null );
337
338         if( null != value )
339         {
340             try
341             {
342                 final String JavaDoc 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 JavaDoc[] mergedAttr = merged.getAttributeNames();
362
363         for( int i = 0; i < mergedAttr.length; i++ )
364         {
365             final String JavaDoc value = merged.getAttribute( mergedAttr[ i ] );
366
367             try
368             {
369                 final String JavaDoc 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                 //not in base add to layer
379
layer.setAttribute( mergedAttr[ i ], value );
380             }
381         }
382     }
383
384 }
385
Popular Tags