View Javadoc

    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: 439648 $, $Date: 2006-09-02 22:42:10 +0200 (Sa, 02 Sep 2006) $
    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      {
    55          this.parent = parent;
    56          this.prefix = prefix;
    57      }
    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      {
    68          this.parent = parent;
    69          this.prefix = prefix;
    70          this.delimiter = delimiter;
    71      }
    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          if ("".equals(key) || key == null)
    83          {
    84              return prefix;
    85          }
    86          else
    87          {
    88              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         if (!key.startsWith(prefix))
    102         {
    103             throw new IllegalArgumentException("The parent key '" + key + "' is not in the subset.");
    104         }
    105         else
    106         {
    107             String modifiedKey = null;
    108             if (key.length() == prefix.length())
    109             {
    110                 modifiedKey = "";
    111             }
    112             else
    113             {
    114                 int i = prefix.length() + (delimiter != null ? delimiter.length() : 0);
    115                 modifiedKey = key.substring(i);
    116             }
    117
    118             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         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         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         this.prefix = prefix;
    150     }
    151
    152     /***
    153      * {@inheritDoc}
    154      */
    155     public Configuration subset(String prefix)
    156     {
    157         return parent.subset(getParentKey(prefix));
    158     }
    159
    160     /***
    161      * {@inheritDoc}
    162      */
    163     public boolean isEmpty()
    164     {
    165         return !getKeys().hasNext();
    166     }
    167
    168     /***
    169      * {@inheritDoc}
    170      */
    171     public boolean containsKey(String key)
    172     {
    173         return parent.containsKey(getParentKey(key));
    174     }
    175
    176     /***
    177      * {@inheritDoc}
    178      */
    179     public void addPropertyDirect(String key, Object value)
    180     {
    181         parent.addProperty(getParentKey(key), value);
    182     }
    183
    184     /***
    185      * {@inheritDoc}
    186      */
    187     public void setProperty(String key, Object value)
    188     {
    189         parent.setProperty(getParentKey(key), value);
    190     }
    191
    192     /***
    193      * {@inheritDoc}
    194      */
    195     public void clearProperty(String key)
    196     {
    197         parent.clearProperty(getParentKey(key));
    198     }
    199
    200     /***
    201      * {@inheritDoc}
    202      */
    203     public Object getProperty(String key)
    204     {
    205         return parent.getProperty(getParentKey(key));
    206     }
    207
    208     /***
    209      * {@inheritDoc}
    210      */
    211     public Iterator getKeys(String prefix)
    212     {
    213         return new TransformIterator(parent.getKeys(getParentKey(prefix)), new Transformer()
    214         {
    215             public Object transform(Object obj)
    216             {
    217                 return getChildKey((String) obj);
    218             }
    219         });
    220     }
    221
    222     /***
    223      * {@inheritDoc}
    224      */
    225     public Iterator getKeys()
    226     {
    227         return new TransformIterator(parent.getKeys(prefix), new Transformer()
    228         {
    229             public Object transform(Object obj)
    230             {
    231                 return getChildKey((String) obj);
    232             }
    233         });
    234     }
    235
    236     /***
    237      * {@inheritDoc}
    238      */
    239     protected String interpolate(String base)
    240     {
    241         if (delimiter == null && "".equals(prefix))
    242         {
    243             return super.interpolate(base);
    244         }
    245         else
    246         {
    247             SubsetConfiguration config = new SubsetConfiguration(parent, "");
    248             return config.interpolate(base);
    249         }
    250     }
    251
    252     /***
    253      * {@inheritDoc}
    254      *
    255      * Change the behaviour of the parent configuration if it supports this feature.
    256      */
    257     public void setThrowExceptionOnMissing(boolean throwExceptionOnMissing)
    258     {
    259         if (parent instanceof AbstractConfiguration)
    260         {
    261             ((AbstractConfiguration) parent).setThrowExceptionOnMissing(throwExceptionOnMissing);
    262         }
    263         else
    264         {
    265             super.setThrowExceptionOnMissing(throwExceptionOnMissing);
    266         }
    267     }
    268
    269     /***
    270      * {@inheritDoc}
    271      *
    272      * The subset inherits this feature from its parent if it supports this feature.
    273      */
    274     public boolean isThrowExceptionOnMissing()
    275     {
    276         if (parent instanceof AbstractConfiguration)
    277         {
    278             return ((AbstractConfiguration) parent).isThrowExceptionOnMissing();
    279         }
    280         else
    281         {
    282             return super.isThrowExceptionOnMissing();
    283         }
    284     }
    285 }