Coverage report

  %line %branch
org.apache.commons.configuration.AbstractConfiguration$1
100% 
100% 

 1  
 /*
 2  
  * Copyright 2001-2004 The Apache Software Foundation.
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License")
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *     http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 
 17  
 package org.apache.commons.configuration;
 18  
 
 19  
 import java.math.BigDecimal;
 20  
 import java.math.BigInteger;
 21  
 import java.util.ArrayList;
 22  
 import java.util.Iterator;
 23  
 import java.util.List;
 24  
 import java.util.NoSuchElementException;
 25  
 import java.util.Properties;
 26  
 
 27  
 import org.apache.commons.collections.Predicate;
 28  
 import org.apache.commons.collections.iterators.FilterIterator;
 29  
 import org.apache.commons.lang.BooleanUtils;
 30  
 
 31  
 /**
 32  
  * Abstract configuration class. Provide basic functionality but does not store
 33  
  * any data. If you want to write your own Configuration class then you should
 34  
  * implement only abstract methods from this class.
 35  
  * 
 36  
  * @author <a href="mailto:ksh@scand.com">Konstantin Shaposhnikov </a>
 37  
  * @author <a href="mailto:oliver.heger@t-online.de">Oliver Heger </a>
 38  
  * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen </a>
 39  
  * @version $Id: AbstractConfiguration.java,v 1.29 2004/12/02 22:05:52 ebourg
 40  
  * Exp $
 41  
  */
 42  
 public abstract class AbstractConfiguration implements Configuration
 43  
 {
 44  
     /** start token */
 45  
     protected static final String START_TOKEN = "${";
 46  
 
 47  
     /** end token */
 48  
     protected static final String END_TOKEN = "}";
 49  
 
 50  
     /** The property delimiter used while parsing (a comma). */
 51  
     private static char DELIMITER = ',';
 52  
 
 53  
     /**
 54  
      * Whether the configuration should throw NoSuchElementExceptions or simply
 55  
      * return null when a property does not exist. Defaults to return null.
 56  
      */
 57  
     private boolean throwExceptionOnMissing = false;
 58  
 
 59  
     /**
 60  
      * For configurations extending AbstractConfiguration, allow them to change
 61  
      * the delimiter from the default comma (",").
 62  
      * 
 63  
      * @param delimiter The new delimiter
 64  
      */
 65  
     public static void setDelimiter(char delimiter)
 66  
     {
 67  
         AbstractConfiguration.DELIMITER = delimiter;
 68  
     }
 69  
 
 70  
     /**
 71  
      * Retrieve the current delimiter. By default this is a comma (",").
 72  
      * 
 73  
      * @return The delimiter in use
 74  
      */
 75  
     public static char getDelimiter()
 76  
     {
 77  
         return AbstractConfiguration.DELIMITER;
 78  
     }
 79  
 
 80  
     /**
 81  
      * If set to false, missing elements return null if possible (for objects).
 82  
      * 
 83  
      * @param throwExceptionOnMissing The new value for the property
 84  
      */
 85  
     public void setThrowExceptionOnMissing(boolean throwExceptionOnMissing)
 86  
     {
 87  
         this.throwExceptionOnMissing = throwExceptionOnMissing;
 88  
     }
 89  
 
 90  
     /**
 91  
      * Returns true if missing values throw Exceptions.
 92  
      * 
 93  
      * @return true if missing values throw Exceptions
 94  
      */
 95  
     public boolean isThrowExceptionOnMissing()
 96  
     {
 97  
         return throwExceptionOnMissing;
 98  
     }
 99  
 
 100  
     /**
 101  
      * {@inheritDoc}
 102  
      */
 103  
     public void addProperty(String key, Object value)
 104  
     {
 105  
         Iterator it = PropertyConverter.toIterator(value, DELIMITER);
 106  
         while (it.hasNext())
 107  
         {
 108  
             addPropertyDirect(key, it.next());
 109  
         }
 110  
     }
 111  
 
 112  
     /**
 113  
      * Adds a key/value pair to the Configuration. Override this method to
 114  
      * provide write acces to underlying Configuration store.
 115  
      * 
 116  
      * @param key key to use for mapping
 117  
      * @param obj object to store
 118  
      */
 119  
     protected abstract void addPropertyDirect(String key, Object obj);
 120  
 
 121  
     /**
 122  
      * interpolate key names to handle ${key} stuff
 123  
      * 
 124  
      * @param base string to interpolate
 125  
      * 
 126  
      * @return returns the key name with the ${key} substituted
 127  
      */
 128  
     protected String interpolate(String base)
 129  
     {
 130  
         return interpolateHelper(base, null);
 131  
     }
 132  
 
 133  
     /**
 134  
      * Recursive handler for multple levels of interpolation.
 135  
      * 
 136  
      * When called the first time, priorVariables should be null.
 137  
      * 
 138  
      * @param base string with the ${key} variables
 139  
      * @param priorVariables serves two purposes: to allow checking for loops,
 140  
      * and creating a meaningful exception message should a loop occur. It's
 141  
      * 0'th element will be set to the value of base from the first call. All
 142  
      * subsequent interpolated variables are added afterward.
 143  
      * 
 144  
      * @return the string with the interpolation taken care of
 145  
      */
 146  
     protected String interpolateHelper(String base, List priorVariables)
 147  
     {
 148  
         if (base == null)
 149  
         {
 150  
             return null;
 151  
         }
 152  
 
 153  
         // on the first call initialize priorVariables
 154  
         // and add base as the first element
 155  
         if (priorVariables == null)
 156  
         {
 157  
             priorVariables = new ArrayList();
 158  
             priorVariables.add(base);
 159  
         }
 160  
 
 161  
         int begin = -1;
 162  
         int end = -1;
 163  
         int prec = 0 - END_TOKEN.length();
 164  
         String variable = null;
 165  
         StringBuffer result = new StringBuffer();
 166  
 
 167  
         // FIXME: we should probably allow the escaping of the start token
 168  
         while (((begin = base.indexOf(START_TOKEN, prec + END_TOKEN.length())) > -1)
 169  
                 && ((end = base.indexOf(END_TOKEN, begin)) > -1))
 170  
         {
 171  
             result.append(base.substring(prec + END_TOKEN.length(), begin));
 172  
             variable = base.substring(begin + START_TOKEN.length(), end);
 173  
 
 174  
             // if we've got a loop, create a useful exception message and throw
 175  
             if (priorVariables.contains(variable))
 176  
             {
 177  
                 String initialBase = priorVariables.remove(0).toString();
 178  
                 priorVariables.add(variable);
 179  
                 StringBuffer priorVariableSb = new StringBuffer();
 180  
 
 181  
                 // create a nice trace of interpolated variables like so:
 182  
                 // var1->var2->var3
 183  
                 for (Iterator it = priorVariables.iterator(); it.hasNext();)
 184  
                 {
 185  
                     priorVariableSb.append(it.next());
 186  
                     if (it.hasNext())
 187  
                     {
 188  
                         priorVariableSb.append("->");
 189  
                     }
 190  
                 }
 191  
 
 192  
                 throw new IllegalStateException("infinite loop in property interpolation of " + initialBase + ": "
 193  
                         + priorVariableSb.toString());
 194  
             }
 195  
             // otherwise, add this variable to the interpolation list.
 196  
             else
 197  
             {
 198  
                 priorVariables.add(variable);
 199  
             }
 200  
 
 201  
             Object value = getProperty(variable);
 202  
             if (value != null)
 203  
             {
 204  
                 result.append(interpolateHelper(value.toString(), priorVariables));
 205  
 
 206  
                 // pop the interpolated variable off the stack
 207  
                 // this maintains priorVariables correctness for
 208  
                 // properties with multiple interpolations, e.g.
 209  
                 // prop.name=${some.other.prop1}/blahblah/${some.other.prop2}
 210  
                 priorVariables.remove(priorVariables.size() - 1);
 211  
             }
 212  
             else
 213  
             {
 214  
                 //variable not defined - so put it back in the value
 215  
                 result.append(START_TOKEN).append(variable).append(END_TOKEN);
 216  
             }
 217  
 
 218  
             prec = end;
 219  
         }
 220  
         result.append(base.substring(prec + END_TOKEN.length(), base.length()));
 221  
         return result.toString();
 222  
     }
 223  
 
 224  
     /**
 225  
      * {@inheritDoc}
 226  
      */
 227  
     public Configuration subset(String prefix)
 228  
     {
 229  
         return new SubsetConfiguration(this, prefix, ".");
 230  
     }
 231  
 
 232  
     /**
 233  
      * {@inheritDoc}
 234  
      */
 235  
     public abstract boolean isEmpty();
 236  
 
 237  
     /**
 238  
      * {@inheritDoc}
 239  
      */
 240  
     public abstract boolean containsKey(String key);
 241  
 
 242  
     /**
 243  
      * {@inheritDoc}
 244  
      */
 245  
     public void setProperty(String key, Object value)
 246  
     {
 247  
         clearProperty(key);
 248  
         addProperty(key, value);
 249  
     }
 250  
 
 251  
     /**
 252  
      * {@inheritDoc}
 253  
      */
 254  
     public abstract void clearProperty(String key);
 255  
 
 256  
     /**
 257  
      * {@inheritDoc}
 258  
      */
 259  
     public void clear()
 260  
     {
 261  
         Iterator it = getKeys();
 262  
         while (it.hasNext())
 263  
         {
 264  
             String key = (String) it.next();
 265  
             it.remove();
 266  
 
 267  
             if (containsKey(key))
 268  
             {
 269  
                 // workaround for Iterators that do not remove the property on calling remove()
 270  
                 clearProperty(key);
 271  
             }
 272  
         }
 273  
     }
 274  
 
 275  
     /**
 276  
      * {@inheritDoc}
 277  
      */
 278  
     public abstract Iterator getKeys();
 279  
 
 280  396
     /**
 281  
      * {@inheritDoc}
 282  4116
      */
 283  4116
     public Iterator getKeys(final String prefix)
 284  
     {
 285  
         return new FilterIterator(getKeys(), class="keyword">new Predicate()
 286  
         {
 287  407
             public boolean evaluate(Object obj)
 288  
             {
 289  3839
                 String key = (String) obj;
 290  3839
                 return key.startsWith(prefix + ".") || key.equals(prefix);
 291  
             }
 292  
         });
 293  
     }
 294  
 
 295  
     /**
 296  
      * {@inheritDoc}
 297  
      */
 298  
     public Properties getProperties(String key)
 299  
     {
 300  
         return getProperties(key, null);
 301  
     }
 302  
 
 303  
     /**
 304  
      * Get a list of properties associated with the given configuration key.
 305  
      * 
 306  
      * @param key The configuration key.
 307  
      * @param defaults Any default values for the returned
 308  
      * <code>Properties</code> object. Ignored if <code>null</code>.
 309  
      * 
 310  
      * @return The associated properties if key is found.
 311  
      * 
 312  
      * @throws ConversionException is thrown if the key maps to an object that
 313  
      * is not a String/List of Strings.
 314  
      * 
 315  
      * @throws IllegalArgumentException if one of the tokens is malformed (does
 316  
      * not contain an equals sign).
 317  
      */
 318  
     public Properties getProperties(String key, Properties defaults)
 319  
     {
 320  
         /*
 321  
          * Grab an array of the tokens for this key.
 322  
          */
 323  
         String[] tokens = getStringArray(key);
 324  
 
 325  
         /*
 326  
          * Each token is of the form 'key=value'.
 327  
          */
 328  
         Properties props = defaults == null ? new Properties() : class="keyword">new Properties(defaults);
 329  
         for (int i = 0; i < tokens.length; i++)
 330  
         {
 331  
             String token = tokens[i];
 332  
             int equalSign = token.indexOf('=');
 333  
             if (equalSign > 0)
 334  
             {
 335  
                 String pkey = token.substring(0, equalSign).trim();
 336  
                 String pvalue = token.substring(equalSign + 1).trim();
 337  
                 props.put(pkey, pvalue);
 338  
             }
 339  
             else if (tokens.length == 1 && "".equals(token))
 340  
             {
 341  
                 // Semantically equivalent to an empty Properties
 342  
                 // object.
 343  
                 break;
 344  
             }
 345  
             else
 346  
             {
 347  
                 throw new IllegalArgumentException('\'' + token + "' does not contain an equals sign");
 348  
             }
 349  
         }
 350  
         return props;
 351  
     }
 352  
 
 353  
     /**
 354  
      * {@inheritDoc}
 355  
      */
 356  
     public boolean getBoolean(String key)
 357  
     {
 358  
         Boolean b = getBoolean(key, null);
 359  
         if (b != null)
 360  
         {
 361  
             return b.booleanValue();
 362  
         }
 363  
         else
 364  
         {
 365  
             throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");
 366  
         }
 367  
     }
 368  
 
 369  
     /**
 370  
      * {@inheritDoc}
 371  
      */
 372  
     public boolean getBoolean(String key, class="keyword">boolean defaultValue)
 373  
     {
 374  
         return getBoolean(key, BooleanUtils.toBooleanObject(defaultValue)).booleanValue();
 375  
     }
 376  
 
 377  
     /**
 378  
      * {@inheritDoc}
 379  
      */
 380  
     public Boolean getBoolean(String key, Boolean defaultValue)
 381  
     {
 382  
         Object value = resolveContainerStore(key);
 383  
 
 384  
         if (value == null)
 385  
         {
 386  
             return defaultValue;
 387  
         }
 388  
         else
 389  
         {
 390  
             try
 391  
             {
 392  
                 return PropertyConverter.toBoolean(value);
 393  
             }
 394  
             catch (ConversionException e)
 395  
             {
 396  
                 throw new ConversionException('\'' + key + "' doesn't map to a Boolean object", e);
 397  
             }
 398  
         }
 399  
     }
 400  
 
 401  
     /**
 402  
      * {@inheritDoc}
 403  
      */
 404  
     public byte getByte(String key)
 405  
     {
 406  
         Byte b = getByte(key, null);
 407  
         if (b != null)
 408  
         {
 409  
             return b.byteValue();
 410  
         }
 411  
         else
 412  
         {
 413  
             throw new NoSuchElementException('\'' + key + " doesn't map to an existing object");
 414  
         }
 415  
     }
 416  
 
 417  
     /**
 418  
      * {@inheritDoc}
 419  
      */
 420  
     public byte getByte(String key, byte defaultValue)
 421  
     {
 422  
         return getByte(key, new Byte(defaultValue)).byteValue();
 423  
     }
 424  
 
 425  
     /**
 426  
      * {@inheritDoc}
 427  
      */
 428  
     public Byte getByte(String key, Byte defaultValue)
 429  
     {
 430  
         Object value = resolveContainerStore(key);
 431  
 
 432  
         if (value == null)
 433  
         {
 434  
             return defaultValue;
 435  
         }
 436  
         else
 437  
         {
 438  
             try
 439  
             {
 440  
                 return PropertyConverter.toByte(value);
 441  
             }
 442  
             catch (ConversionException e)
 443  
             {
 444  
                 throw new ConversionException('\'' + key + "' doesn't map to a Byte object", e);
 445  
             }
 446  
         }
 447  
     }
 448  
 
 449  
     /**
 450  
      * {@inheritDoc}
 451  
      */
 452  
     public double getDouble(String key)
 453  
     {
 454  
         Double d = getDouble(key, null);
 455  
         if (d != null)
 456  
         {
 457  
             return d.doubleValue();
 458  
         }
 459  
         else
 460  
         {
 461  
             throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");
 462  
         }
 463  
     }
 464  
 
 465  
     /**
 466  
      * {@inheritDoc}
 467  
      */
 468  
     public double getDouble(String key, class="keyword">double defaultValue)
 469  
     {
 470  
         return getDouble(key, new Double(defaultValue)).doubleValue();
 471  
     }
 472  
 
 473  
     /**
 474  
      * {@inheritDoc}
 475  
      */
 476  
     public Double getDouble(String key, Double defaultValue)
 477  
     {
 478  
         Object value = resolveContainerStore(key);
 479  
 
 480  
         if (value == null)
 481  
         {
 482  
             return defaultValue;
 483  
         }
 484  
         else
 485  
         {
 486  
             try
 487  
             {
 488  
                 return PropertyConverter.toDouble(value);
 489  
             }
 490  
             catch (ConversionException e)
 491  
             {
 492  
                 throw new ConversionException('\'' + key + "' doesn't map to a Double object", e);
 493  
             }
 494  
         }
 495  
     }
 496  
 
 497  
     /**
 498  
      * {@inheritDoc}
 499  
      */
 500  
     public float getFloat(String key)
 501  
     {
 502  
         Float f = getFloat(key, null);
 503  
         if (f != null)
 504  
         {
 505  
             return f.floatValue();
 506  
         }
 507  
         else
 508  
         {
 509  
             throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");
 510  
         }
 511  
     }
 512  
 
 513  
     /**
 514  
      * {@inheritDoc}
 515  
      */
 516  
     public float getFloat(String key, class="keyword">float defaultValue)
 517  
     {
 518  
         return getFloat(key, new Float(defaultValue)).floatValue();
 519  
     }
 520  
 
 521  
     /**
 522  
      * {@inheritDoc}
 523  
      */
 524  
     public Float getFloat(String key, Float defaultValue)
 525  
     {
 526  
         Object value = resolveContainerStore(key);
 527  
 
 528  
         if (value == null)
 529  
         {
 530  
             return defaultValue;
 531  
         }
 532  
         else
 533  
         {
 534  
             try
 535  
             {
 536  
                 return PropertyConverter.toFloat(value);
 537  
             }
 538  
             catch (ConversionException e)
 539  
             {
 540  
                 throw new ConversionException('\'' + key + "' doesn't map to a Float object", e);
 541  
             }
 542  
         }
 543  
     }
 544  
 
 545  
     /**
 546  
      * {@inheritDoc}
 547  
      */
 548  
     public int getInt(String key)
 549  
     {
 550  
         Integer i = getInteger(key, null);
 551  
         if (i != null)
 552  
         {
 553  
             return i.intValue();
 554  
         }
 555  
         else
 556  
         {
 557  
             throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");
 558  
         }
 559  
     }
 560  
 
 561  
     /**
 562  
      * {@inheritDoc}
 563  
      */
 564  
     public int getInt(String key, class="keyword">int defaultValue)
 565  
     {
 566  
         Integer i = getInteger(key, null);
 567  
 
 568  
         if (i == null)
 569  
         {
 570  
             return defaultValue;
 571  
         }
 572  
 
 573  
         return i.intValue();
 574  
     }
 575  
 
 576  
     /**
 577  
      * {@inheritDoc}
 578  
      */
 579  
     public Integer getInteger(String key, Integer defaultValue)
 580  
     {
 581  
         Object value = resolveContainerStore(key);
 582  
 
 583  
         if (value == null)
 584  
         {
 585  
             return defaultValue;
 586  
         }
 587  
         else
 588  
         {
 589  
             try
 590  
             {
 591  
                 return PropertyConverter.toInteger(value);
 592  
             }
 593  
             catch (ConversionException e)
 594  
             {
 595  
                 throw new ConversionException('\'' + key + "' doesn't map to an Integer object", e);
 596  
             }
 597  
         }
 598  
     }
 599  
 
 600  
     /**
 601  
      * {@inheritDoc}
 602  
      */
 603  
     public long getLong(String key)
 604  
     {
 605  
         Long l = getLong(key, null);
 606  
         if (l != null)
 607  
         {
 608  
             return l.longValue();
 609  
         }
 610  
         else
 611  
         {
 612  
             throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");
 613  
         }
 614  
     }
 615  
 
 616  
     /**
 617  
      * {@inheritDoc}
 618  
      */
 619  
     public long getLong(String key, class="keyword">long defaultValue)
 620  
     {
 621  
         return getLong(key, new Long(defaultValue)).longValue();
 622  
     }
 623  
 
 624  
     /**
 625  
      * {@inheritDoc}
 626  
      */
 627  
     public Long getLong(String key, Long defaultValue)
 628  
     {
 629  
         Object value = resolveContainerStore(key);
 630  
 
 631  
         if (value == null)
 632  
         {
 633  
             return defaultValue;
 634  
         }
 635  
         else
 636  
         {
 637  
             try
 638  
             {
 639  
                 return PropertyConverter.toLong(value);
 640  
             }
 641  
             catch (ConversionException e)
 642  
             {
 643  
                 throw new ConversionException('\'' + key + "' doesn't map to a Long object", e);
 644  
             }
 645  
         }
 646  
     }
 647  
 
 648  
     /**
 649  
      * {@inheritDoc}
 650  
      */
 651  
     public short getShort(String key)
 652  
     {
 653  
         Short s = getShort(key, null);
 654  
         if (s != null)
 655  
         {
 656  
             return s.shortValue();
 657  
         }
 658  
         else
 659  
         {
 660  
             throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");
 661  
         }
 662  
     }
 663  
 
 664  
     /**
 665  
      * {@inheritDoc}
 666  
      */
 667  
     public short getShort(String key, class="keyword">short defaultValue)
 668  
     {
 669  
         return getShort(key, new Short(defaultValue)).shortValue();
 670  
     }
 671  
 
 672  
     /**
 673  
      * {@inheritDoc}
 674  
      */
 675  
     public Short getShort(String key, Short defaultValue)
 676  
     {
 677  
         Object value = resolveContainerStore(key);
 678  
 
 679  
         if (value == null)
 680  
         {
 681  
             return defaultValue;
 682  
         }
 683  
         else
 684  
         {
 685  
             try
 686  
             {
 687  
                 return PropertyConverter.toShort(value);
 688  
             }
 689  
             catch (ConversionException e)
 690  
             {
 691  
                 throw new ConversionException('\'' + key + "' doesn't map to a Short object", e);
 692  
             }
 693  
         }
 694  
     }
 695  
 
 696  
     /**
 697  
      * {@inheritDoc}
 698  
      */
 699  
     public BigDecimal getBigDecimal(String key)
 700  
     {
 701  
         BigDecimal number = getBigDecimal(key, null);
 702  
         if (number != null)
 703  
         {
 704  
             return number;
 705  
         }
 706  
         else if (isThrowExceptionOnMissing())
 707  
         {
 708  
             throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");
 709  
         }
 710  
         else
 711  
         {
 712  
             return null;
 713  
         }
 714  
     }
 715  
 
 716  
     /**
 717  
      * {@inheritDoc}
 718  
      */
 719  
     public BigDecimal getBigDecimal(String key, BigDecimal defaultValue)
 720  
     {
 721  
         Object value = resolveContainerStore(key);
 722  
 
 723  
         if (value == null)
 724  
         {
 725  
             return defaultValue;
 726  
         }
 727  
         else
 728  
         {
 729  
             try
 730  
             {
 731  
                 return PropertyConverter.toBigDecimal(value);
 732  
             }
 733  
             catch (ConversionException e)
 734  
             {
 735  
                 throw new ConversionException('\'' + key + "' doesn't map to a BigDecimal object", e);
 736  
             }
 737  
         }
 738  
     }
 739  
 
 740  
     /**
 741  
      * {@inheritDoc}
 742  
      */
 743  
     public BigInteger getBigInteger(String key)
 744  
     {
 745  
         BigInteger number = getBigInteger(key, null);
 746  
         if (number != null)
 747  
         {
 748  
             return number;
 749  
         }
 750  
         else if (isThrowExceptionOnMissing())
 751  
         {
 752  
             throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");
 753  
         }
 754  
         else
 755  
         {
 756  
             return null;
 757  
         }
 758  
     }
 759  
 
 760  
     /**
 761  
      * {@inheritDoc}
 762  
      */
 763  
     public BigInteger getBigInteger(String key, BigInteger defaultValue)
 764  
     {
 765  
         Object value = resolveContainerStore(key);
 766  
 
 767  
         if (value == null)
 768  
         {
 769  
             return defaultValue;
 770  
         }
 771  
         else
 772  
         {
 773  
             try
 774  
             {
 775  
                 return PropertyConverter.toBigInteger(value);
 776  
             }
 777  
             catch (ConversionException e)
 778  
             {
 779  
                 throw new ConversionException('\'' + key + "' doesn't map to a BigDecimal object", e);
 780  
             }
 781  
         }
 782  
     }
 783  
 
 784  
     /**
 785  
      * {@inheritDoc}
 786  
      */
 787  
     public String getString(String key)
 788  
     {
 789  
         String s = getString(key, null);
 790  
         if (s != null)
 791  
         {
 792  
             return s;
 793  
         }
 794  
         else if (isThrowExceptionOnMissing())
 795  
         {
 796  
             throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");
 797  
         }
 798  
         else
 799  
         {
 800  
             return null;
 801  
         }
 802  
     }
 803  
 
 804  
     /**
 805  
      * {@inheritDoc}
 806  
      */
 807  
     public String getString(String key, String defaultValue)
 808  
     {
 809  
         Object value = resolveContainerStore(key);
 810  
 
 811  
         if (value instanceof String)
 812  
         {
 813  
             return interpolate((String) value);
 814  
         }
 815  
         else if (value == null)
 816  
         {
 817  
             return interpolate(defaultValue);
 818  
         }
 819  
         else
 820  
         {
 821  
             throw new ConversionException('\'' + key + "' doesn't map to a String object");
 822  
         }
 823  
     }
 824  
 
 825  
     /**
 826  
      * {@inheritDoc}
 827  
      */
 828  
     public String[] getStringArray(String key)
 829  
     {
 830  
         Object value = getProperty(key);
 831  
 
 832  
         String[] array;
 833  
 
 834  
         if (value instanceof String)
 835  
         {
 836  
             array = new String[1];
 837  
 
 838  
             array[0] = interpolate((String) value);
 839  
         }
 840  
         else if (value instanceof List)
 841  
         {
 842  
             List list = (List) value;
 843  
             array = new String[list.size()];
 844  
 
 845  
             for (int i = 0; i < array.length; i++)
 846  
             {
 847  
                 array[i] = interpolate((String) list.get(i));
 848  
             }
 849  
         }
 850  
         else if (value == null)
 851  
         {
 852  
             array = new String[0];
 853  
         }
 854  
         else
 855  
         {
 856  
             throw new ConversionException('\'' + key + "' doesn't map to a String/List object");
 857  
         }
 858  
         return array;
 859  
     }
 860  
 
 861  
     /**
 862  
      * {@inheritDoc}
 863  
      */
 864  
     public List getList(String key)
 865  
     {
 866  
         return getList(key, new ArrayList());
 867  
     }
 868  
 
 869  
     /**
 870  
      * {@inheritDoc}
 871  
      */
 872  
     public List getList(String key, List defaultValue)
 873  
     {
 874  
         Object value = getProperty(key);
 875  
         List list = null;
 876  
 
 877  
         if (value instanceof String)
 878  
         {
 879  
             list = new ArrayList(1);
 880  
             list.add(value);
 881  
         }
 882  
         else if (value instanceof List)
 883  
         {
 884  
             list = (List) value;
 885  
         }
 886  
         else if (value == null)
 887  
         {
 888  
             list = defaultValue;
 889  
         }
 890  
         else
 891  
         {
 892  
             throw new ConversionException('\'' + key + "' doesn't map to a List object: " + value + ", a "
 893  
                     + value.getClass().getName());
 894  
         }
 895  
         return list;
 896  
     }
 897  
 
 898  
     /**
 899  
      * Returns an object from the store described by the key. If the value is a
 900  
      * List object, replace it with the first object in the list.
 901  
      * 
 902  
      * @param key The property key.
 903  
      * 
 904  
      * @return value Value, transparently resolving a possible List dependency.
 905  
      */
 906  
     protected Object resolveContainerStore(String key)
 907  
     {
 908  
         Object value = getProperty(key);
 909  
         if (value != null)
 910  
         {
 911  
             if (value instanceof List)
 912  
             {
 913  
                 List list = (List) value;
 914  
                 value = list.isEmpty() ? null : list.get(0);
 915  
             }
 916  
             else if (value instanceof Object[])
 917  
             {
 918  
                 Object[] array = (Object[]) value;
 919  
                 value = array.length == 0 ? null : array[0];
 920  
             }
 921  
             else if (value instanceof boolean[])
 922  
             {
 923  
                 boolean[] array = (class="keyword">boolean[]) value;
 924  
                 value = array.length == 0 ? null : new Boolean(array[0]);
 925  
             }
 926  
             else if (value instanceof byte[])
 927  
             {
 928  
                 byte[] array = (byte[]) value;
 929  
                 value = array.length == 0 ? null : new Byte(array[0]);
 930  
             }
 931  
             else if (value instanceof short[])
 932  
             {
 933  
                 short[] array = (class="keyword">short[]) value;
 934  
                 value = array.length == 0 ? null : new Short(array[0]);
 935  
             }
 936  
             else if (value instanceof int[])
 937  
             {
 938  
                 int[] array = (class="keyword">int[]) value;
 939  
                 value = array.length == 0 ? null : new Integer(array[0]);
 940  
             }
 941  
             else if (value instanceof long[])
 942  
             {
 943  
                 long[] array = (class="keyword">long[]) value;
 944  
                 value = array.length == 0 ? null : new Long(array[0]);
 945  
             }
 946  
             else if (value instanceof float[])
 947  
             {
 948  
                 float[] array = (class="keyword">float[]) value;
 949  
                 value = array.length == 0 ? null : new Float(array[0]);
 950  
             }
 951  
             else if (value instanceof double[])
 952  
             {
 953  
                 double[] array = (class="keyword">double[]) value;
 954  
                 value = array.length == 0 ? null : new Double(array[0]);
 955  
             }
 956  
         }
 957  
 
 958  
         return value;
 959  
     }
 960  
 
 961  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.