Coverage Report - org.apache.commons.configuration.SubsetConfiguration
 
Classes in this File Line Coverage Branch Coverage Complexity
SubsetConfiguration
91%
53/58
100%
13/13
1,462
SubsetConfiguration$1
100%
2/2
N/A
1,462
SubsetConfiguration$2
100%
2/2
N/A
1,462
 
 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.Iterator;
 21  
 
 22  
 import org.apache.commons.collections.Transformer;
 23  
 import org.apache.commons.collections.iterators.TransformIterator;
 24  
 
 25  
 /**
 26  
  * <p>A subset of another configuration. The new Configuration object contains
 27  
  * every key from the parent Configuration that starts with prefix. The prefix
 28  
  * is removed from the keys in the subset.</p>
 29  
  * <p>It is usually not necessary to use this class directly. Instead the
 30  
  * <code>{@link Configuration#subset(String)}</code> method should be used,
 31  
  * which will return a correctly initialized instance.</p>
 32  
  *
 33  
  * @author Emmanuel Bourg
 34  
  * @version $Revision: 501987 $, $Date: 2007-01-31 21:57:04 +0100 (Mi, 31 Jan 2007) $
 35  
  */
 36  
 public class SubsetConfiguration extends AbstractConfiguration
 37  
 {
 38  
     /** The parent configuration. */
 39  
     protected Configuration parent;
 40  
 
 41  
     /** The prefix used to select the properties. */
 42  
     protected String prefix;
 43  
 
 44  
     /** The prefix delimiter */
 45  
     protected String delimiter;
 46  
 
 47  
     /**
 48  
      * Create a subset of the specified configuration
 49  
      *
 50  
      * @param parent The parent configuration
 51  
      * @param prefix The prefix used to select the properties
 52  
      */
 53  
     public SubsetConfiguration(Configuration parent, String prefix)
 54  26
     {
 55  26
         this.parent = parent;
 56  26
         this.prefix = prefix;
 57  26
     }
 58  
 
 59  
     /**
 60  
      * Create a subset of the specified configuration
 61  
      *
 62  
      * @param parent    The parent configuration
 63  
      * @param prefix    The prefix used to select the properties
 64  
      * @param delimiter The prefix delimiter
 65  
      */
 66  
     public SubsetConfiguration(Configuration parent, String prefix, String delimiter)
 67  64
     {
 68  64
         this.parent = parent;
 69  64
         this.prefix = prefix;
 70  64
         this.delimiter = delimiter;
 71  64
     }
 72  
 
 73  
     /**
 74  
      * Return the key in the parent configuration associated to the specified
 75  
      * key in this subset.
 76  
      *
 77  
      * @param key The key in the subset.
 78  
      * @return the key as to be used by the parent
 79  
      */
 80  
     protected String getParentKey(String key)
 81  
     {
 82  72
         if ("".equals(key) || key == null)
 83  
         {
 84  4
             return prefix;
 85  
         }
 86  
         else
 87  
         {
 88  68
             return delimiter == null ? prefix + key : prefix + delimiter + key;
 89  
         }
 90  
     }
 91  
 
 92  
     /**
 93  
      * Return the key in the subset configuration associated to the specified
 94  
      * key in the parent configuration.
 95  
      *
 96  
      * @param key The key in the parent configuration.
 97  
      * @return the key in the context of this subset configuration
 98  
      */
 99  
     protected String getChildKey(String key)
 100  
     {
 101  107
         if (!key.startsWith(prefix))
 102  
         {
 103  0
             throw new IllegalArgumentException("The parent key '" + key + "' is not in the subset.");
 104  
         }
 105  
         else
 106  
         {
 107  107
             String modifiedKey = null;
 108  107
             if (key.length() == prefix.length())
 109  
             {
 110  4
                 modifiedKey = "";
 111  
             }
 112  
             else
 113  
             {
 114  103
                 int i = prefix.length() + (delimiter != null ? delimiter.length() : 0);
 115  103
                 modifiedKey = key.substring(i);
 116  
             }
 117  
 
 118  107
             return modifiedKey;
 119  
         }
 120  
     }
 121  
 
 122  
     /**
 123  
      * Return the parent configuation for this subset.
 124  
      *
 125  
      * @return the parent configuration
 126  
      */
 127  
     public Configuration getParent()
 128  
     {
 129  1
         return parent;
 130  
     }
 131  
 
 132  
     /**
 133  
      * Return the prefix used to select the properties in the parent configuration.
 134  
      *
 135  
      * @return the prefix used by this subset
 136  
      */
 137  
     public String getPrefix()
 138  
     {
 139  2
         return prefix;
 140  
     }
 141  
 
 142  
     /**
 143  
      * Set the prefix used to select the properties in the parent configuration.
 144  
      *
 145  
      * @param prefix the prefix
 146  
      */
 147  
     public void setPrefix(String prefix)
 148  
     {
 149  1
         this.prefix = prefix;
 150  1
     }
 151  
 
 152  
     /**
 153  
      * {@inheritDoc}
 154  
      */
 155  
     public Configuration subset(String prefix)
 156  
     {
 157  1
         return parent.subset(getParentKey(prefix));
 158  
     }
 159  
 
 160  
     /**
 161  
      * {@inheritDoc}
 162  
      */
 163  
     public boolean isEmpty()
 164  
     {
 165  11
         return !getKeys().hasNext();
 166  
     }
 167  
 
 168  
     /**
 169  
      * {@inheritDoc}
 170  
      */
 171  
     public boolean containsKey(String key)
 172  
     {
 173  10
         return parent.containsKey(getParentKey(key));
 174  
     }
 175  
 
 176  
     /**
 177  
      * {@inheritDoc}
 178  
      */
 179  
     public void addPropertyDirect(String key, Object value)
 180  
     {
 181  10
         parent.addProperty(getParentKey(key), value);
 182  10
     }
 183  
 
 184  
     /**
 185  
      * {@inheritDoc}
 186  
      */
 187  
     public void setProperty(String key, Object value)
 188  
     {
 189  7
         parent.setProperty(getParentKey(key), value);
 190  7
     }
 191  
 
 192  
     /**
 193  
      * {@inheritDoc}
 194  
      */
 195  
     public void clearProperty(String key)
 196  
     {
 197  1
         parent.clearProperty(getParentKey(key));
 198  1
     }
 199  
 
 200  
     /**
 201  
      * {@inheritDoc}
 202  
      */
 203  
     public Object getProperty(String key)
 204  
     {
 205  38
         return parent.getProperty(getParentKey(key));
 206  
     }
 207  
 
 208  
     /**
 209  
      * {@inheritDoc}
 210  
      */
 211  
     public Iterator getKeys(String prefix)
 212  
     {
 213  1
         return new TransformIterator(parent.getKeys(getParentKey(prefix)), new Transformer()
 214  
         {
 215  1
             public Object transform(Object obj)
 216  
             {
 217  2
                 return getChildKey((String) obj);
 218  
             }
 219  
         });
 220  
     }
 221  
 
 222  
     /**
 223  
      * {@inheritDoc}
 224  
      */
 225  
     public Iterator getKeys()
 226  
     {
 227  30
         return new TransformIterator(parent.getKeys(prefix), new Transformer()
 228  
         {
 229  30
             public Object transform(Object obj)
 230  
             {
 231  101
                 return getChildKey((String) obj);
 232  
             }
 233  
         });
 234  
     }
 235  
 
 236  
     /**
 237  
      * {@inheritDoc}
 238  
      */
 239  
     protected Object interpolate(Object base)
 240  
     {
 241  50
         if (delimiter == null && "".equals(prefix))
 242  
         {
 243  25
             return super.interpolate(base);
 244  
         }
 245  
         else
 246  
         {
 247  25
             SubsetConfiguration config = new SubsetConfiguration(parent, "");
 248  25
             return config.interpolate(base);
 249  
         }
 250  
     }
 251  
 
 252  
     /**
 253  
      * {@inheritDoc}
 254  
      */
 255  
     protected String interpolate(String base)
 256  
     {
 257  20
         return super.interpolate(base);
 258  
     }
 259  
 
 260  
     /**
 261  
      * {@inheritDoc}
 262  
      *
 263  
      * Change the behaviour of the parent configuration if it supports this feature.
 264  
      */
 265  
     public void setThrowExceptionOnMissing(boolean throwExceptionOnMissing)
 266  
     {
 267  1
         if (parent instanceof AbstractConfiguration)
 268  
         {
 269  1
             ((AbstractConfiguration) parent).setThrowExceptionOnMissing(throwExceptionOnMissing);
 270  
         }
 271  
         else
 272  
         {
 273  0
             super.setThrowExceptionOnMissing(throwExceptionOnMissing);
 274  
         }
 275  1
     }
 276  
 
 277  
     /**
 278  
      * {@inheritDoc}
 279  
      *
 280  
      * The subset inherits this feature from its parent if it supports this feature.
 281  
      */
 282  
     public boolean isThrowExceptionOnMissing()
 283  
     {
 284  2
         if (parent instanceof AbstractConfiguration)
 285  
         {
 286  2
             return ((AbstractConfiguration) parent).isThrowExceptionOnMissing();
 287  
         }
 288  
         else
 289  
         {
 290  0
             return super.isThrowExceptionOnMissing();
 291  
         }
 292  
     }
 293  
 
 294  
     /**
 295  
      * Returns the list delimiter. This property will be fetched from the parent
 296  
      * configuration if supported.
 297  
      *
 298  
      * @return the list delimiter
 299  
      * @since 1.4
 300  
      */
 301  
     public char getListDelimiter()
 302  
     {
 303  4
         return (parent instanceof AbstractConfiguration) ? ((AbstractConfiguration) parent)
 304  
                 .getListDelimiter()
 305  
                 : super.getListDelimiter();
 306  
     }
 307  
 
 308  
     /**
 309  
      * Sets the list delimiter. If the parent configuration supports this
 310  
      * feature, the delimiter will be set at the parent.
 311  
      *
 312  
      * @param delim the new list delimiter
 313  
      * @since 1.4
 314  
      */
 315  
     public void setListDelimiter(char delim)
 316  
     {
 317  2
         if (parent instanceof AbstractConfiguration)
 318  
         {
 319  2
             ((AbstractConfiguration) parent).setListDelimiter(delim);
 320  
         }
 321  
         else
 322  
         {
 323  0
             super.setListDelimiter(delim);
 324  
         }
 325  2
     }
 326  
 
 327  
     /**
 328  
      * Returns a flag whether string properties should be checked for list
 329  
      * delimiter characters. This implementation ensures that this flag is kept
 330  
      * in sync with the parent configuration if this object supports this
 331  
      * feature.
 332  
      *
 333  
      * @return the delimiter parsing disabled flag
 334  
      * @since 1.4
 335  
      */
 336  
     public boolean isDelimiterParsingDisabled()
 337  
     {
 338  5
         return (parent instanceof AbstractConfiguration) ? ((AbstractConfiguration) parent)
 339  
                 .isDelimiterParsingDisabled()
 340  
                 : super.isDelimiterParsingDisabled();
 341  
     }
 342  
 
 343  
     /**
 344  
      * Sets a flag whether list parsing is disabled. This implementation will
 345  
      * also set the flag at the parent configuration if this object supports
 346  
      * this feature.
 347  
      *
 348  
      * @param delimiterParsingDisabled the delimiter parsing disabled flag
 349  
      * @since 1.4
 350  
      */
 351  
     public void setDelimiterParsingDisabled(boolean delimiterParsingDisabled)
 352  
     {
 353  2
         if (parent instanceof AbstractConfiguration)
 354  
         {
 355  2
             ((AbstractConfiguration) parent)
 356  
                     .setDelimiterParsingDisabled(delimiterParsingDisabled);
 357  
         }
 358  
         else
 359  
         {
 360  0
             super.setDelimiterParsingDisabled(delimiterParsingDisabled);
 361  
         }
 362  2
     }
 363  
 }