Clover coverage report - DNA - 1.0
Coverage timestamp: Sun Oct 12 2003 11:23:26 BST
file stats: LOC: 923   Methods: 39
NCLOC: 537   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
DefaultConfiguration.java 100% 100% 100% 100%
coverage
 1   
 /*
 2   
  * Copyright (C) The JContainer Group. All rights reserved.
 3   
  *
 4   
  * This software is published under the terms of the JContainer
 5   
  * Software License version 1.1, a copy of which has been included
 6   
  * with this distribution in the LICENSE.txt file.
 7   
  */
 8   
 package org.jcontainer.dna.impl;
 9   
 
 10   
 import java.util.ArrayList;
 11   
 import java.util.HashMap;
 12   
 import java.util.List;
 13   
 import java.util.Map;
 14   
 import java.util.Set;
 15   
 import org.jcontainer.dna.Configuration;
 16   
 import org.jcontainer.dna.ConfigurationException;
 17   
 
 18   
 /**
 19   
  * In memory Configuration implementation.
 20   
  * The developer should create the DefaultConfiguration,
 21   
  * associate value, attributes and/or child elements configuration
 22   
  * and then invoke {@link #makeReadOnly()} before passing the
 23   
  * Configuration to the client component.
 24   
  *
 25   
  * @version $Revision: 1.23 $ $Date: 2003/09/23 10:57:28 $
 26   
  */
 27   
 public class DefaultConfiguration
 28   
     extends AbstractFreezable
 29   
     implements Configuration
 30   
 {
 31   
     /**
 32   
      * Postfix indicating that location is generated.
 33   
      */
 34   
     private static final String AUTOGEN_POSTFIX = "<autogen>";
 35   
 
 36   
     /**
 37   
      * The constant that boolean values must equal to be "true".
 38   
      */
 39   
     private static final String TRUE_STRING = "true";
 40   
 
 41   
     /**
 42   
      * Constant for empty String array to reduce
 43   
      * creation cost for empty array.
 44   
      */
 45   
     private static final String[] EMPTY_STRING_ARRAY = new String[ 0 ];
 46   
 
 47   
     /**
 48   
      * Constant for empty configuration array to reduce
 49   
      * creation cost for empty array.
 50   
      */
 51   
     private static final Configuration[] EMPTY_CONFIG_ARRAY = new Configuration[ 0 ];
 52   
 
 53   
     /**
 54   
      * The name of configuration element.
 55   
      */
 56   
     private final String m_name;
 57   
 
 58   
     /**
 59   
      * The location of configuration element in source.
 60   
      * May be empty string if unknown.
 61   
      */
 62   
     private final String m_location;
 63   
 
 64   
     /**
 65   
      * The path of configuration element in document.
 66   
      * May be empty string if unknown.
 67   
      */
 68   
     private final String m_path;
 69   
 
 70   
     /**
 71   
      * The attributes defined by configuration (May be null).
 72   
      */
 73   
     private Map m_attributes;
 74   
 
 75   
     /**
 76   
      * The child elements defined by
 77   
      * configuration (May be null). If
 78   
      * {@link #m_value} not null then
 79   
      * m_children must be null.
 80   
      */
 81   
     private List m_children;
 82   
 
 83   
     /**
 84   
      * The value contained in configuration
 85   
      * (May be null). If {@link #m_children} not
 86   
      * null then m_value must be null.
 87   
      */
 88   
     private String m_value;
 89   
 
 90   
     /**
 91   
      * Create a DefaultConfiguration instance.
 92   
      *
 93   
      * @param name the name of configuration element
 94   
      * @param location the location of configuration element in source
 95   
      * @param path the path of configuration element in document
 96   
      */
 97  278
     public DefaultConfiguration( final String name,
 98   
                                  final String location,
 99   
                                  final String path )
 100   
     {
 101  278
         if( null == name )
 102   
         {
 103  2
             throw new NullPointerException( "name" );
 104   
         }
 105  276
         if( null == path )
 106   
         {
 107  2
             throw new NullPointerException( "path" );
 108   
         }
 109  274
         if( null == location )
 110   
         {
 111  2
             throw new NullPointerException( "location" );
 112   
         }
 113  272
         m_name = name;
 114  272
         m_path = path;
 115  272
         m_location = location;
 116   
     }
 117   
 
 118   
     /**
 119   
      * Return the name of the configuration element.
 120   
      *
 121   
      * @return the name of the configuration element.
 122   
      */
 123  174
     public String getName()
 124   
     {
 125  174
         return m_name;
 126   
     }
 127   
 
 128   
     /**
 129   
      * Return the path to the configuration element.
 130   
      * The path should be in the xpath form but may
 131   
      * be the empty string if unabel to determine path.
 132   
      *
 133   
      * @return the path to the configuration element.
 134   
      */
 135  96
     public final String getPath()
 136   
     {
 137  96
         return m_path;
 138   
     }
 139   
 
 140   
     /**
 141   
      * Return the location of configuration element.
 142   
      * Usually of the form "uri[:line number[:column number]]"
 143   
      * if possible. ie "file:myFile.xml:80:2". However the line
 144   
      * number and column number may be elided if unavailable.
 145   
      *
 146   
      * @return the location of configuration element.
 147   
      */
 148  84
     public String getLocation()
 149   
     {
 150  84
         return m_location;
 151   
     }
 152   
 
 153   
     /**
 154   
      * Return an array of all the child elements.
 155   
      *
 156   
      * @return an array of all the child elements.
 157   
      */
 158  96
     public Configuration[] getChildren()
 159   
     {
 160  96
         final List childList = getChildList();
 161  96
         if( null == childList )
 162   
         {
 163  64
             return EMPTY_CONFIG_ARRAY;
 164   
         }
 165   
         else
 166   
         {
 167  32
             return (Configuration[])childList.toArray( new Configuration[ childList.size() ] );
 168   
         }
 169   
     }
 170   
 
 171   
     /**
 172   
      * Return an array of all the child elements with specified name.
 173   
      *
 174   
      * @param name the name of child configuration objects
 175   
      * @return an array of all the child elements with specified name.
 176   
      */
 177  6
     public Configuration[] getChildren( final String name )
 178   
     {
 179  6
         if( null == name )
 180   
         {
 181  2
             throw new NullPointerException( "name" );
 182   
         }
 183  4
         final List children = getChildList();
 184  4
         if( null == children )
 185   
         {
 186  2
             return EMPTY_CONFIG_ARRAY;
 187   
         }
 188   
         else
 189   
         {
 190  2
             final ArrayList results = new ArrayList();
 191  2
             final int count = children.size();
 192  2
             for( int i = 0; i < count; i++ )
 193   
             {
 194  6
                 final Configuration child = (Configuration)children.get( i );
 195  6
                 if( child.getName().equals( name ) )
 196   
                 {
 197  2
                     results.add( child );
 198   
                 }
 199   
             }
 200  2
             return (Configuration[])results.toArray( new Configuration[ results.size() ] );
 201   
         }
 202   
     }
 203   
 
 204   
     /**
 205   
      * Return a child Configuration element with specified name.
 206   
      * If no such element exists an element will be autocreated.
 207   
      *
 208   
      * @param name the name of child configuration object
 209   
      * @return a child Configuration element with specified name.
 210   
      */
 211  6
     public Configuration getChild( final String name )
 212   
     {
 213  6
         return getChild( name, true );
 214   
     }
 215   
 
 216   
     /**
 217   
      * Return a child Configuration element with specified name.
 218   
      * If no such element exists and createChild is true then an
 219   
      * element will be autocreated otherwise null will be returned.
 220   
      *
 221   
      * @param name the name of child configuration object
 222   
      * @param createChild true if child should be created if it does not exist
 223   
      * @return a child Configuration element with specified name.
 224   
      */
 225  14
     public Configuration getChild( final String name,
 226   
                                    final boolean createChild )
 227   
     {
 228  14
         if( null == name )
 229   
         {
 230  2
             throw new NullPointerException( "name" );
 231   
         }
 232  12
         final List children = getChildList();
 233  12
         if( null != children )
 234   
         {
 235  4
             final int count = children.size();
 236  4
             for( int i = 0; i < count; i++ )
 237   
             {
 238  4
                 final Configuration child = (Configuration)children.get( i );
 239  4
                 if( child.getName().equals( name ) )
 240   
                 {
 241  2
                     return child;
 242   
                 }
 243   
             }
 244   
         }
 245  10
         if( createChild )
 246   
         {
 247  6
             final String path = getPath() + ConfigurationUtil.PATH_SEPARATOR + getName();
 248  6
             return new DefaultConfiguration( name, generateLocation(), path );
 249   
         }
 250   
         else
 251   
         {
 252  4
             return null;
 253   
         }
 254   
 
 255   
     }
 256   
 
 257   
     /**
 258   
      * Return text value of element.
 259   
      *
 260   
      * @return the value
 261   
      * @throws ConfigurationException if no value in element
 262   
      */
 263  44
     public String getValue()
 264   
         throws ConfigurationException
 265   
     {
 266  44
         if( null != m_value )
 267   
         {
 268  34
             return m_value;
 269   
         }
 270   
         else
 271   
         {
 272  10
             final String message = "No value specified";
 273  10
             throw new ConfigurationException( message, getPath(), getLocation() );
 274   
         }
 275   
     }
 276   
 
 277   
     /**
 278   
      * Return text value of element.
 279   
      * Use specified default if no value in element.
 280   
      *
 281   
      * @param defaultValue the default value
 282   
      * @return the value
 283   
      */
 284  62
     public String getValue( final String defaultValue )
 285   
     {
 286  62
         if( null != m_value )
 287   
         {
 288  18
             return m_value;
 289   
         }
 290   
         else
 291   
         {
 292  44
             return defaultValue;
 293   
         }
 294   
     }
 295   
 
 296   
     /**
 297   
      * Return text value of element as a boolean.
 298   
      *
 299   
      * @return the value
 300   
      * @throws ConfigurationException if no value in element
 301   
      *         or value can not be converted to correct type
 302   
      */
 303  4
     public boolean getValueAsBoolean()
 304   
         throws ConfigurationException
 305   
     {
 306  4
         return getValue().equals( "true" );
 307   
     }
 308   
 
 309   
     /**
 310   
      * Return text value of element as a boolean.
 311   
      * Use specified default if no value in element or
 312   
      * value can not be converted to correct type.
 313   
      *
 314   
      * @param defaultValue the default value
 315   
      * @return the value
 316   
      */
 317  4
     public boolean getValueAsBoolean( final boolean defaultValue )
 318   
     {
 319  4
         if( null == m_value )
 320   
         {
 321  2
             return defaultValue;
 322   
         }
 323   
         else
 324   
         {
 325  2
             return m_value.equals( TRUE_STRING );
 326   
         }
 327   
     }
 328   
 
 329   
     /**
 330   
      * Return text value of element as an integer.
 331   
      *
 332   
      * @return the value
 333   
      * @throws ConfigurationException if no value in element
 334   
      *         or value can not be converted to correct type
 335   
      */
 336  6
     public int getValueAsInteger()
 337   
         throws ConfigurationException
 338   
     {
 339  6
         try
 340   
         {
 341  6
             return Integer.parseInt( getValue() );
 342   
         }
 343   
         catch( final NumberFormatException nfe )
 344   
         {
 345  2
             final String message =
 346   
                 "Unable to parse " + getValue() + " as an integer";
 347  2
             throw new ConfigurationException( message, getPath(), getLocation(), nfe );
 348   
         }
 349   
     }
 350   
 
 351   
     /**
 352   
      * Return text value of element as an integer.
 353   
      * Use specified default if no value in element or
 354   
      * value can not be converted to correct type.
 355   
      *
 356   
      * @param defaultValue the default value
 357   
      * @return the value
 358   
      */
 359  6
     public int getValueAsInteger( final int defaultValue )
 360   
     {
 361  6
         if( null == m_value )
 362   
         {
 363  2
             return defaultValue;
 364   
         }
 365   
         else
 366   
         {
 367  4
             try
 368   
             {
 369  4
                 return Integer.parseInt( m_value );
 370   
             }
 371   
             catch( final NumberFormatException nfe )
 372   
             {
 373  2
                 return defaultValue;
 374   
             }
 375   
         }
 376   
     }
 377   
 
 378   
     /**
 379   
      * Return text value of element as a long.
 380   
      *
 381   
      * @return the value
 382   
      * @throws ConfigurationException if no value in element
 383   
      *         or value can not be converted to correct type
 384   
      */
 385  6
     public long getValueAsLong()
 386   
         throws ConfigurationException
 387   
     {
 388  6
         try
 389   
         {
 390  6
             return Long.parseLong( getValue() );
 391   
         }
 392   
         catch( final NumberFormatException nfe )
 393   
         {
 394  2
             final String message =
 395   
                 "Unable to parse " + getValue() + " as a Long";
 396  2
             throw new ConfigurationException( message, getPath(), getLocation(), nfe );
 397   
         }
 398   
     }
 399   
 
 400   
     /**
 401   
      * Return text value of element as a long.
 402   
      * Use specified default if no value in element or
 403   
      * value can not be converted to correct type.
 404   
      *
 405   
      * @param defaultValue the default value
 406   
      * @return the value
 407   
      */
 408  6
     public long getValueAsLong( final long defaultValue )
 409   
     {
 410  6
         if( null == m_value )
 411   
         {
 412  2
             return defaultValue;
 413   
         }
 414   
         else
 415   
         {
 416  4
             try
 417   
             {
 418  4
                 return Long.parseLong( m_value );
 419   
             }
 420   
             catch( final NumberFormatException nfe )
 421   
             {
 422  2
                 return defaultValue;
 423   
             }
 424   
         }
 425   
     }
 426   
 
 427   
     /**
 428   
      * Return text value of element as a float.
 429   
      *
 430   
      * @return the value
 431   
      * @throws ConfigurationException if no value in element
 432   
      *         or value can not be converted to correct type
 433   
      */
 434  6
     public float getValueAsFloat()
 435   
         throws ConfigurationException
 436   
     {
 437  6
         try
 438   
         {
 439  6
             return Float.parseFloat( getValue() );
 440   
         }
 441   
         catch( final NumberFormatException nfe )
 442   
         {
 443  2
             final String message =
 444   
                 "Unable to parse " + getValue() + " as a Long";
 445  2
             throw new ConfigurationException( message, getPath(), getLocation(), nfe );
 446   
         }
 447   
     }
 448   
 
 449   
     /**
 450   
      * Return text value of element as a float.
 451   
      * Use specified default if no value in element or
 452   
      * value can not be converted to correct type.
 453   
      *
 454   
      * @param defaultValue the default value
 455   
      * @return the value
 456   
      */
 457  6
     public float getValueAsFloat( final float defaultValue )
 458   
     {
 459  6
         if( null == m_value )
 460   
         {
 461  2
             return defaultValue;
 462   
         }
 463   
         else
 464   
         {
 465  4
             try
 466   
             {
 467  4
                 return Float.parseFloat( m_value );
 468   
             }
 469   
             catch( final NumberFormatException nfe )
 470   
             {
 471  2
                 return defaultValue;
 472   
             }
 473   
         }
 474   
     }
 475   
 
 476   
     /**
 477   
      * Return an array of all the attribute names.
 478   
      *
 479   
      * @return an array of all the attribute names.
 480   
      */
 481  68
     public String[] getAttributeNames()
 482   
     {
 483  68
         final Map attributeMap = getAttributeMap();
 484  68
         if( null == attributeMap )
 485   
         {
 486  40
             return EMPTY_STRING_ARRAY;
 487   
         }
 488   
         else
 489   
         {
 490  28
             final Set keys = attributeMap.keySet();
 491  28
             return (String[])attributeMap.keySet().toArray( new String[ keys.size() ] );
 492   
         }
 493   
     }
 494   
 
 495   
     /**
 496   
      * Return attribute value with specified name.
 497   
      *
 498   
      * @param name the attribute name
 499   
      * @return the attribute value
 500   
      * @throws ConfigurationException if no attribute with
 501   
      *         specified name
 502   
      */
 503  34
     public String getAttribute( final String name )
 504   
         throws ConfigurationException
 505   
     {
 506  34
         final String value = doGetAttribute( name );
 507  32
         if( null != value )
 508   
         {
 509  22
             return value;
 510   
         }
 511   
         else
 512   
         {
 513  10
             final String message =
 514   
                 "Attribute named " + name + " not specified.";
 515  10
             throw new ConfigurationException( message, getPath(), getLocation() );
 516   
         }
 517   
     }
 518   
 
 519   
     /**
 520   
      * Return attribute value with specified name.
 521   
      * If no attribute with specified name then return
 522   
      * default value.
 523   
      *
 524   
      * @param name the attribute name
 525   
      * @param defaultValue the default value
 526   
      * @return the attribute value
 527   
      */
 528  42
     public String getAttribute( final String name,
 529   
                                 final String defaultValue )
 530   
     {
 531  42
         final String value = doGetAttribute( name );
 532  42
         if( null != value )
 533   
         {
 534  30
             return value;
 535   
         }
 536   
         else
 537   
         {
 538  12
             return defaultValue;
 539   
         }
 540   
     }
 541   
 
 542   
     /**
 543   
      * Return attribute value with specified name or null
 544   
      * if no such attribute.
 545   
      *
 546   
      * @param name the attribute name
 547   
      * @return the attribute value
 548   
      */
 549  76
     private String doGetAttribute( final String name )
 550   
     {
 551  76
         if( null == name )
 552   
         {
 553  2
             throw new NullPointerException( "name" );
 554   
         }
 555  74
         final Map attributeMap = getAttributeMap();
 556  74
         if( null != attributeMap )
 557   
         {
 558  58
             final String value = (String)attributeMap.get( name );
 559  58
             if( null != value )
 560   
             {
 561  52
                 return value;
 562   
             }
 563   
         }
 564  22
         return null;
 565   
     }
 566   
 
 567   
     /**
 568   
      * Return attribute value with specified name as a boolean.
 569   
      *
 570   
      * @param name the attribute name
 571   
      * @return the attribute value
 572   
      * @throws ConfigurationException if no attribute with
 573   
      *         specified name or attribute can not be converted
 574   
      *         to correct type
 575   
      */
 576  2
     public boolean getAttributeAsBoolean( final String name )
 577   
         throws ConfigurationException
 578   
     {
 579  2
         return getAttribute( name ).equals( TRUE_STRING );
 580   
     }
 581   
 
 582   
     /**
 583   
      * Return attribute value with specified name as a boolean.
 584   
      * If no attribute with specified name or attribute can
 585   
      * not be converted to correct type then return
 586   
      * default value.
 587   
      *
 588   
      * @param name the attribute name
 589   
      * @param defaultValue the default value
 590   
      * @return the attribute value
 591   
      */
 592  4
     public boolean getAttributeAsBoolean( final String name,
 593   
                                           final boolean defaultValue )
 594   
     {
 595  4
         final String value = getAttribute( name, null );
 596  4
         if( null != value )
 597   
         {
 598  2
             return value.equals( TRUE_STRING );
 599   
         }
 600  2
         return defaultValue;
 601   
     }
 602   
 
 603   
     /**
 604   
      * Return attribute value with specified name as an integer.
 605   
      *
 606   
      * @param name the attribute name
 607   
      * @return the attribute value
 608   
      * @throws ConfigurationException if no attribute with
 609   
      *         specified name or attribute can not be converted
 610   
      *         to correct type
 611   
      */
 612  6
     public int getAttributeAsInteger( final String name )
 613   
         throws ConfigurationException
 614   
     {
 615  6
         final String value = getAttribute( name );
 616  4
         try
 617   
         {
 618  4
             return Integer.parseInt( value );
 619   
         }
 620   
         catch( final NumberFormatException nfe )
 621   
         {
 622  2
             final String message =
 623   
                 "Unable to parse " + value + " as an Integer.";
 624  2
             throw new ConfigurationException( message, getPath(), getLocation() );
 625   
         }
 626   
     }
 627   
 
 628   
     /**
 629   
      * Return attribute value with specified name as an integer.
 630   
      * If no attribute with specified name or attribute can
 631   
      * not be converted to correct type then return
 632   
      * default value.
 633   
      *
 634   
      * @param name the attribute name
 635   
      * @param defaultValue the default value
 636   
      * @return the attribute value
 637   
      */
 638  6
     public int getAttributeAsInteger( final String name,
 639   
                                       final int defaultValue )
 640   
     {
 641  6
         final String value = getAttribute( name, null );
 642  6
         if( null != value )
 643   
         {
 644  4
             try
 645   
             {
 646  4
                 return Integer.parseInt( value );
 647   
             }
 648   
             catch( final NumberFormatException nfe )
 649   
             {
 650   
                 //Fall through to return defaultValue
 651   
             }
 652   
         }
 653  4
         return defaultValue;
 654   
     }
 655   
 
 656   
     /**
 657   
      * Return attribute value with specified name as a long.
 658   
      *
 659   
      * @param name the attribute name
 660   
      * @return the attribute value
 661   
      * @throws ConfigurationException if no attribute with
 662   
      *         specified name or attribute can not be converted
 663   
      *         to correct type
 664   
      */
 665  6
     public long getAttributeAsLong( final String name )
 666   
         throws ConfigurationException
 667   
     {
 668  6
         final String value = getAttribute( name );
 669  4
         try
 670   
         {
 671  4
             return Long.parseLong( value );
 672   
         }
 673   
         catch( final NumberFormatException nfe )
 674   
         {
 675  2
             final String message =
 676   
                 "Unable to parse " + value + " as a Long.";
 677  2
             throw new ConfigurationException( message, getPath(), getLocation() );
 678   
         }
 679   
     }
 680   
 
 681   
     /**
 682   
      * Return attribute value with specified name as a long.
 683   
      * If no attribute with specified name or attribute can
 684   
      * not be converted to correct type then return
 685   
      * default value.
 686   
      *
 687   
      * @param name the attribute name
 688   
      * @param defaultValue the default value
 689   
      * @return the attribute value
 690   
      */
 691  6
     public long getAttributeAsLong( final String name,
 692   
                                     final long defaultValue )
 693   
     {
 694  6
         final String value = getAttribute( name, null );
 695  6
         if( null != value )
 696   
         {
 697  4
             try
 698   
             {
 699  4
                 return Long.parseLong( value );
 700   
             }
 701   
             catch( final NumberFormatException nfe )
 702   
             {
 703   
                 //Fall through to return defaultValue
 704   
             }
 705   
         }
 706  4
         return defaultValue;
 707   
     }
 708   
 
 709   
     /**
 710   
      * Return attribute value with specified name as afloat.
 711   
      *
 712   
      * @param name the attribute name
 713   
      * @return the attribute value
 714   
      * @throws ConfigurationException if no attribute with
 715   
      *         specified name or attribute can not be converted
 716   
      *         to correct type
 717   
      */
 718  6
     public float getAttributeAsFloat( final String name )
 719   
         throws ConfigurationException
 720   
     {
 721  6
         final String value = getAttribute( name );
 722  4
         try
 723   
         {
 724  4
             return Float.parseFloat( value );
 725   
         }
 726   
         catch( final NumberFormatException nfe )
 727   
         {
 728  2
             final String message =
 729   
                 "Unable to parse " + value + " as a Float.";
 730  2
             throw new ConfigurationException( message, getPath(), getLocation() );
 731   
         }
 732   
     }
 733   
 
 734   
     /**
 735   
      * Return attribute value with specified name as a float.
 736   
      * If no attribute with specified name or attribute can
 737   
      * not be converted to correct type then return
 738   
      * default value.
 739   
      *
 740   
      * @param name the attribute name
 741   
      * @param defaultValue the default value
 742   
      * @return the attribute value
 743   
      */
 744  6
     public float getAttributeAsFloat( final String name,
 745   
                                       final float defaultValue )
 746   
     {
 747  6
         final String value = getAttribute( name, null );
 748  6
         if( null != value )
 749   
         {
 750  4
             try
 751   
             {
 752  4
                 return Float.parseFloat( value );
 753   
             }
 754   
             catch( final NumberFormatException nfe )
 755   
             {
 756   
                 //Fall through to return defaultValue
 757   
             }
 758   
         }
 759  4
         return defaultValue;
 760   
     }
 761   
 
 762   
     /**
 763   
      * Mark the configuration and child configurations as read only.
 764   
      */
 765  8
     public void makeReadOnly()
 766   
     {
 767  8
         super.makeReadOnly();
 768  8
         final List children = getChildList();
 769  8
         if( null != children )
 770   
         {
 771  4
             final int count = children.size();
 772  4
             for( int i = 0; i < count; i++ )
 773   
             {
 774  4
                 final Configuration configuration = (Configuration)children.get( i );
 775  4
                 if( configuration instanceof Freezable )
 776   
                 {
 777  2
                     ( (Freezable)configuration ).makeReadOnly();
 778   
                 }
 779   
             }
 780   
         }
 781   
     }
 782   
 
 783   
     /**
 784   
      * Set an attribute of configuration.
 785   
      *
 786   
      * @param key the attribute key
 787   
      * @param value the attribute value
 788   
      */
 789  56
     public void setAttribute( final String key,
 790   
                               final String value )
 791   
     {
 792  56
         if( null == key )
 793   
         {
 794  2
             throw new NullPointerException( "key" );
 795   
         }
 796  54
         if( null == value )
 797   
         {
 798  2
             throw new NullPointerException( "value" );
 799   
         }
 800  52
         checkWriteable();
 801  52
         if( null == m_attributes )
 802   
         {
 803  48
             m_attributes = new HashMap();
 804   
         }
 805  52
         m_attributes.put( key, value );
 806   
     }
 807   
 
 808   
     /**
 809   
      * Add a child configuration element.
 810   
      *
 811   
      * @param configuration the child configuration element.
 812   
      */
 813  50
     public void addChild( final Configuration configuration )
 814   
     {
 815  50
         if( null == configuration )
 816   
         {
 817  2
             throw new NullPointerException( "configuration" );
 818   
         }
 819  48
         checkWriteable();
 820  48
         if( null != m_value )
 821   
         {
 822  2
             throwMixedContentException();
 823   
         }
 824  46
         if( null == m_children )
 825   
         {
 826  42
             m_children = new ArrayList();
 827   
         }
 828  46
         m_children.add( configuration );
 829   
     }
 830   
 
 831   
     /**
 832   
      * Set the value of the configuration element.
 833   
      *
 834   
      * @param value the value of the configuration element.
 835   
      */
 836  50
     public void setValue( final String value )
 837   
     {
 838  50
         if( null == value )
 839   
         {
 840  2
             throw new NullPointerException( "value" );
 841   
         }
 842  48
         checkWriteable();
 843  48
         final List children = getChildList();
 844  48
         if( null != children && 0 != children.size() )
 845   
         {
 846  2
             throwMixedContentException();
 847   
         }
 848  46
         m_value = value;
 849   
     }
 850   
 
 851   
     /**
 852   
      * Overide toString to improve ability to debug implementation.
 853   
      *
 854   
      * @return string representation of object
 855   
      */
 856  4
     public String toString()
 857   
     {
 858  4
         final StringBuffer sb = new StringBuffer();
 859  4
         sb.append( "[Configuration name='" );
 860  4
         sb.append( getName() );
 861  4
         sb.append( "'" );
 862  4
         if( null != m_attributes )
 863   
         {
 864  2
             sb.append( " attributes=" );
 865  2
             sb.append( m_attributes );
 866   
         }
 867  4
         sb.append( "]" );
 868  4
         return sb.toString();
 869   
     }
 870   
 
 871   
     /**
 872   
      * Return the list of child configuration objects.
 873   
      *
 874   
      * @return the list of child configuration objects.
 875   
      */
 876  168
     protected final List getChildList()
 877   
     {
 878  168
         return m_children;
 879   
     }
 880   
 
 881   
     /**
 882   
      * Return the backing map for attributes.
 883   
      *
 884   
      * @return the backing map for attributes.
 885   
      */
 886  144
     protected final Map getAttributeMap()
 887   
     {
 888  144
         return m_attributes;
 889   
     }
 890   
 
 891   
     /**
 892   
      * Generate a location string that postfixes
 893   
      * autogenerated marker.
 894   
      *
 895   
      * @return a autogenerated location string
 896   
      */
 897  6
     protected final String generateLocation()
 898   
     {
 899  6
         final String location = getLocation();
 900  6
         if( !location.endsWith( AUTOGEN_POSTFIX ) )
 901   
         {
 902  4
             return location + AUTOGEN_POSTFIX;
 903   
         }
 904   
         else
 905   
         {
 906  2
             return location;
 907   
         }
 908   
     }
 909   
 
 910   
     /**
 911   
      * Throw an IllegalStateException warning about
 912   
      * mixed content.
 913   
      */
 914  4
     protected final void throwMixedContentException()
 915   
     {
 916  4
         final String message =
 917   
             "Configuration objects do not support Mixed content. " +
 918   
             "Configuration elements should not have both a value and " +
 919   
             "child elements.";
 920  4
         throw new IllegalStateException( message );
 921   
     }
 922   
 }
 923