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