Coverage Report - org.apache.commons.configuration.CompositeConfiguration
 
Classes in this File Line Coverage Branch Coverage Complexity
CompositeConfiguration
98%
101/103
100%
25/25
2,6
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *     http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 package org.apache.commons.configuration;
 19  
 
 20  
 import java.util.ArrayList;
 21  
 import java.util.Collection;
 22  
 import java.util.Iterator;
 23  
 import java.util.LinkedList;
 24  
 import java.util.List;
 25  
 
 26  
 /**
 27  
  * This Configuration class allows you to add multiple different types of Configuration
 28  
  * to this CompositeConfiguration.  If you add Configuration1, and then Configuration2,
 29  
  * any properties shared will mean that Configuration1 will be returned.
 30  
  * You can add multiple different types or the same type of properties file.
 31  
  * If Configuration1 doesn't have the property, then Configuration2 will be checked.
 32  
  *
 33  
  * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
 34  
  * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
 35  
  * @version $Id: CompositeConfiguration.java 439648 2006-09-02 20:42:10Z oheger $
 36  
  */
 37  
 public class CompositeConfiguration extends AbstractConfiguration
 38  
 implements Cloneable
 39  
 {
 40  
     /** List holding all the configuration */
 41  109
     private List configList = new LinkedList();
 42  
 
 43  
     /**
 44  
      * Configuration that holds in memory stuff.  Inserted as first so any
 45  
      * setProperty() override anything else added.
 46  
      */
 47  
     private Configuration inMemoryConfiguration;
 48  
 
 49  
     /**
 50  
      * Creates an empty CompositeConfiguration object which can then
 51  
      * be added some other Configuration files
 52  
      */
 53  
     public CompositeConfiguration()
 54  104
     {
 55  104
         clear();
 56  104
     }
 57  
 
 58  
     /**
 59  
      * Creates a CompositeConfiguration object with a specified in memory
 60  
      * configuration. This configuration will store any changes made to
 61  
      * the CompositeConfiguration.
 62  
      *
 63  
      * @param inMemoryConfiguration the in memory configuration to use
 64  
      */
 65  
     public CompositeConfiguration(Configuration inMemoryConfiguration)
 66  5
     {
 67  5
         configList.clear();
 68  5
         this.inMemoryConfiguration = inMemoryConfiguration;
 69  5
         configList.add(inMemoryConfiguration);
 70  5
     }
 71  
 
 72  
     /**
 73  
      * Create a CompositeConfiguration with an empty in memory configuration
 74  
      * and adds the collection of configurations specified.
 75  
      *
 76  
      * @param configurations the collection of configurations to add
 77  
      */
 78  
     public CompositeConfiguration(Collection configurations)
 79  
     {
 80  1
         this(new BaseConfiguration(), configurations);
 81  1
     }
 82  
 
 83  
     /**
 84  
      * Creates a CompositeConfiguration with a specified in memory
 85  
      * configuration, and then adds the given collection of configurations.
 86  
      *
 87  
      * @param inMemoryConfiguration the in memory configuration to use
 88  
      * @param configurations        the collection of configurations to add
 89  
      */
 90  
     public CompositeConfiguration(Configuration inMemoryConfiguration, Collection configurations)
 91  
     {
 92  1
         this(inMemoryConfiguration);
 93  
 
 94  1
         if (configurations != null)
 95  
         {
 96  1
             Iterator it = configurations.iterator();
 97  5
             while (it.hasNext())
 98  
             {
 99  3
                 addConfiguration((Configuration) it.next());
 100  
             }
 101  
         }
 102  1
     }
 103  
 
 104  
     /**
 105  
      * Add a configuration.
 106  
      *
 107  
      * @param config the configuration to add
 108  
      */
 109  
     public void addConfiguration(Configuration config)
 110  
     {
 111  149
         if (!configList.contains(config))
 112  
         {
 113  
             // As the inMemoryConfiguration contains all manually added keys,
 114  
             // we must make sure that it is always last. "Normal", non composed
 115  
             // configuration add their keys at the end of the configuration and
 116  
             // we want to mimic this behaviour.
 117  147
             configList.add(configList.indexOf(inMemoryConfiguration), config);
 118  
 
 119  147
             if (config instanceof AbstractConfiguration)
 120  
             {
 121  147
                 ((AbstractConfiguration) config).setThrowExceptionOnMissing(isThrowExceptionOnMissing());
 122  
             }
 123  
         }
 124  149
     }
 125  
 
 126  
     /**
 127  
      * Remove a configuration. The in memory configuration cannot be removed.
 128  
      *
 129  
      * @param config The configuration to remove
 130  
      */
 131  
     public void removeConfiguration(Configuration config)
 132  
     {
 133  
         // Make sure that you can't remove the inMemoryConfiguration from
 134  
         // the CompositeConfiguration object
 135  4
         if (!config.equals(inMemoryConfiguration))
 136  
         {
 137  2
             configList.remove(config);
 138  
         }
 139  4
     }
 140  
 
 141  
     /**
 142  
      * Return the number of configurations.
 143  
      *
 144  
      * @return the number of configuration
 145  
      */
 146  
     public int getNumberOfConfigurations()
 147  
     {
 148  31
         return configList.size();
 149  
     }
 150  
 
 151  
     /**
 152  
      * Remove all configuration reinitialize the in memory configuration.
 153  
      */
 154  
     public void clear()
 155  
     {
 156  112
         configList.clear();
 157  
         // recreate the in memory configuration
 158  112
         inMemoryConfiguration = new BaseConfiguration();
 159  112
         ((BaseConfiguration) inMemoryConfiguration).setThrowExceptionOnMissing(isThrowExceptionOnMissing());
 160  112
         configList.add(inMemoryConfiguration);
 161  112
     }
 162  
 
 163  
     /**
 164  
      * Add this property to the inmemory Configuration.
 165  
      *
 166  
      * @param key The Key to add the property to.
 167  
      * @param token The Value to add.
 168  
      */
 169  
     protected void addPropertyDirect(String key, Object token)
 170  
     {
 171  21
         inMemoryConfiguration.addProperty(key, token);
 172  21
     }
 173  
 
 174  
     /**
 175  
      * Read property from underlying composite
 176  
      *
 177  
      * @param key key to use for mapping
 178  
      *
 179  
      * @return object associated with the given configuration key.
 180  
      */
 181  
     public Object getProperty(String key)
 182  
     {
 183  122
         Configuration firstMatchingConfiguration = null;
 184  334
         for (Iterator i = configList.iterator(); i.hasNext();)
 185  
         {
 186  187
             Configuration config = (Configuration) i.next();
 187  187
             if (config.containsKey(key))
 188  
             {
 189  97
                 firstMatchingConfiguration = config;
 190  97
                 break;
 191  
             }
 192  
         }
 193  
 
 194  122
         if (firstMatchingConfiguration != null)
 195  
         {
 196  97
             return firstMatchingConfiguration.getProperty(key);
 197  
         }
 198  
         else
 199  
         {
 200  25
             return null;
 201  
         }
 202  
     }
 203  
 
 204  
     /**
 205  
      * {@inheritDoc}
 206  
      */
 207  
     public Iterator getKeys()
 208  
     {
 209  14
         List keys = new ArrayList();
 210  52
         for (Iterator i = configList.iterator(); i.hasNext();)
 211  
         {
 212  24
             Configuration config = (Configuration) i.next();
 213  
 
 214  24
             Iterator j = config.getKeys();
 215  174
             while (j.hasNext())
 216  
             {
 217  126
                 String key = (String) j.next();
 218  126
                 if (!keys.contains(key))
 219  
                 {
 220  125
                     keys.add(key);
 221  
                 }
 222  
             }
 223  
         }
 224  
 
 225  14
         return keys.iterator();
 226  
     }
 227  
 
 228  
     /**
 229  
      * {@inheritDoc}
 230  
      */
 231  
     public Iterator getKeys(String key)
 232  
     {
 233  9
         List keys = new ArrayList();
 234  40
         for (Iterator i = configList.iterator(); i.hasNext();)
 235  
         {
 236  22
             Configuration config = (Configuration) i.next();
 237  
 
 238  22
             Iterator j = config.getKeys(key);
 239  240
             while (j.hasNext())
 240  
             {
 241  196
                 String newKey = (String) j.next();
 242  196
                 if (!keys.contains(newKey))
 243  
                 {
 244  194
                     keys.add(newKey);
 245  
                 }
 246  
             }
 247  
         }
 248  
 
 249  9
         return keys.iterator();
 250  
     }
 251  
 
 252  
     /**
 253  
      * {@inheritDoc}
 254  
      */
 255  
     public boolean isEmpty()
 256  
     {
 257  4
         boolean isEmpty = true;
 258  8
         for (Iterator i = configList.iterator(); i.hasNext();)
 259  
         {
 260  4
             Configuration config = (Configuration) i.next();
 261  4
             if (!config.isEmpty())
 262  
             {
 263  4
                 return false;
 264  
             }
 265  
         }
 266  
 
 267  0
         return isEmpty;
 268  
     }
 269  
 
 270  
     /**
 271  
      * {@inheritDoc}
 272  
      */
 273  
     public void clearProperty(String key)
 274  
     {
 275  60
         for (Iterator i = configList.iterator(); i.hasNext();)
 276  
         {
 277  32
             Configuration config = (Configuration) i.next();
 278  32
             config.clearProperty(key);
 279  
         }
 280  14
     }
 281  
 
 282  
     /**
 283  
      * {@inheritDoc}
 284  
      */
 285  
     public boolean containsKey(String key)
 286  
     {
 287  134
         for (Iterator i = configList.iterator(); i.hasNext();)
 288  
         {
 289  70
             Configuration config = (Configuration) i.next();
 290  70
             if (config.containsKey(key))
 291  
             {
 292  44
                 return true;
 293  
             }
 294  
         }
 295  10
         return false;
 296  
     }
 297  
 
 298  
     /**
 299  
      * {@inheritDoc}
 300  
      */
 301  
     public List getList(String key, List defaultValue)
 302  
     {
 303  43
         List list = new ArrayList();
 304  
 
 305  
         // add all elements from the first configuration containing the requested key
 306  43
         Iterator it = configList.iterator();
 307  144
         while (it.hasNext() && list.isEmpty())
 308  
         {
 309  58
             Configuration config = (Configuration) it.next();
 310  58
             if (config != inMemoryConfiguration && config.containsKey(key))
 311  
             {
 312  31
                 list.addAll(config.getList(key));
 313  
             }
 314  
         }
 315  
 
 316  
         // add all elements from the in memory configuration
 317  43
         list.addAll(inMemoryConfiguration.getList(key));
 318  
 
 319  43
         if (list.isEmpty())
 320  
         {
 321  5
             return defaultValue;
 322  
         }
 323  
 
 324  38
         return list;
 325  
     }
 326  
 
 327  
     /**
 328  
      * {@inheritDoc}
 329  
      */
 330  
     public String[] getStringArray(String key)
 331  
     {
 332  13
         List list = getList(key);
 333  
 
 334  
         // interpolate the strings
 335  13
         String[] tokens = new String[list.size()];
 336  
 
 337  33
         for (int i = 0; i < tokens.length; i++)
 338  
         {
 339  20
             tokens[i] = interpolate(String.valueOf(list.get(i)));
 340  
         }
 341  
 
 342  13
         return tokens;
 343  
     }
 344  
 
 345  
     /**
 346  
      * Return the configuration at the specified index.
 347  
      *
 348  
      * @param index The index of the configuration to retrieve
 349  
      * @return the configuration at this index
 350  
      */
 351  
     public Configuration getConfiguration(int index)
 352  
     {
 353  28
         return (Configuration) configList.get(index);
 354  
     }
 355  
 
 356  
     /**
 357  
      * Returns the &quot;in memory configuration&quot;. In this configuration
 358  
      * changes are stored.
 359  
      *
 360  
      * @return the in memory configuration
 361  
      */
 362  
     public Configuration getInMemoryConfiguration()
 363  
     {
 364  7
         return inMemoryConfiguration;
 365  
     }
 366  
 
 367  
     /**
 368  
      * Returns a copy of this object. This implementation will create a deep
 369  
      * clone, i.e. all configurations contained in this composite will also be
 370  
      * cloned. This only works if all contained configurations support cloning;
 371  
      * otherwise a runtime exception will be thrown. Registered event handlers
 372  
      * won't get cloned.
 373  
      *
 374  
      * @return the copy
 375  
      * @since 1.3
 376  
      */
 377  
     public Object clone()
 378  
     {
 379  
         try
 380  
         {
 381  3
             CompositeConfiguration copy = (CompositeConfiguration) super
 382  
                     .clone();
 383  3
             copy.clearConfigurationListeners();
 384  3
             copy.configList = new LinkedList();
 385  3
             copy.inMemoryConfiguration = ConfigurationUtils
 386  
                     .cloneConfiguration(getInMemoryConfiguration());
 387  3
             copy.configList.add(copy.inMemoryConfiguration);
 388  
 
 389  5
             for (int i = 0; i < getNumberOfConfigurations(); i++)
 390  
             {
 391  3
                 Configuration config = getConfiguration(i);
 392  3
                 if (config != getInMemoryConfiguration())
 393  
                 {
 394  1
                     copy.addConfiguration(ConfigurationUtils
 395  
                             .cloneConfiguration(config));
 396  
                 }
 397  
             }
 398  
 
 399  2
             return copy;
 400  
         }
 401  
         catch (CloneNotSupportedException cnex)
 402  
         {
 403  
             // cannot happen
 404  0
             throw new ConfigurationRuntimeException(cnex);
 405  
         }
 406  
     }
 407  
 }