View Javadoc
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 public DefaultConfiguration( final String name, 98 final String location, 99 final String path ) 100 { 101 if( null == name ) 102 { 103 throw new NullPointerException( "name" ); 104 } 105 if( null == path ) 106 { 107 throw new NullPointerException( "path" ); 108 } 109 if( null == location ) 110 { 111 throw new NullPointerException( "location" ); 112 } 113 m_name = name; 114 m_path = path; 115 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 public String getName() 124 { 125 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 public final String getPath() 136 { 137 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 public String getLocation() 149 { 150 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 public Configuration[] getChildren() 159 { 160 final List childList = getChildList(); 161 if( null == childList ) 162 { 163 return EMPTY_CONFIG_ARRAY; 164 } 165 else 166 { 167 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 public Configuration[] getChildren( final String name ) 178 { 179 if( null == name ) 180 { 181 throw new NullPointerException( "name" ); 182 } 183 final List children = getChildList(); 184 if( null == children ) 185 { 186 return EMPTY_CONFIG_ARRAY; 187 } 188 else 189 { 190 final ArrayList results = new ArrayList(); 191 final int count = children.size(); 192 for( int i = 0; i < count; i++ ) 193 { 194 final Configuration child = (Configuration)children.get( i ); 195 if( child.getName().equals( name ) ) 196 { 197 results.add( child ); 198 } 199 } 200 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 public Configuration getChild( final String name ) 212 { 213 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 public Configuration getChild( final String name, 226 final boolean createChild ) 227 { 228 if( null == name ) 229 { 230 throw new NullPointerException( "name" ); 231 } 232 final List children = getChildList(); 233 if( null != children ) 234 { 235 final int count = children.size(); 236 for( int i = 0; i < count; i++ ) 237 { 238 final Configuration child = (Configuration)children.get( i ); 239 if( child.getName().equals( name ) ) 240 { 241 return child; 242 } 243 } 244 } 245 if( createChild ) 246 { 247 final String path = getPath() + ConfigurationUtil.PATH_SEPARATOR + getName(); 248 return new DefaultConfiguration( name, generateLocation(), path ); 249 } 250 else 251 { 252 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 public String getValue() 264 throws ConfigurationException 265 { 266 if( null != m_value ) 267 { 268 return m_value; 269 } 270 else 271 { 272 final String message = "No value specified"; 273 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 public String getValue( final String defaultValue ) 285 { 286 if( null != m_value ) 287 { 288 return m_value; 289 } 290 else 291 { 292 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 public boolean getValueAsBoolean() 304 throws ConfigurationException 305 { 306 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 public boolean getValueAsBoolean( final boolean defaultValue ) 318 { 319 if( null == m_value ) 320 { 321 return defaultValue; 322 } 323 else 324 { 325 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 public int getValueAsInteger() 337 throws ConfigurationException 338 { 339 try 340 { 341 return Integer.parseInt( getValue() ); 342 } 343 catch( final NumberFormatException nfe ) 344 { 345 final String message = 346 "Unable to parse " + getValue() + " as an integer"; 347 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 public int getValueAsInteger( final int defaultValue ) 360 { 361 if( null == m_value ) 362 { 363 return defaultValue; 364 } 365 else 366 { 367 try 368 { 369 return Integer.parseInt( m_value ); 370 } 371 catch( final NumberFormatException nfe ) 372 { 373 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 public long getValueAsLong() 386 throws ConfigurationException 387 { 388 try 389 { 390 return Long.parseLong( getValue() ); 391 } 392 catch( final NumberFormatException nfe ) 393 { 394 final String message = 395 "Unable to parse " + getValue() + " as a Long"; 396 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 public long getValueAsLong( final long defaultValue ) 409 { 410 if( null == m_value ) 411 { 412 return defaultValue; 413 } 414 else 415 { 416 try 417 { 418 return Long.parseLong( m_value ); 419 } 420 catch( final NumberFormatException nfe ) 421 { 422 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 public float getValueAsFloat() 435 throws ConfigurationException 436 { 437 try 438 { 439 return Float.parseFloat( getValue() ); 440 } 441 catch( final NumberFormatException nfe ) 442 { 443 final String message = 444 "Unable to parse " + getValue() + " as a Long"; 445 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 public float getValueAsFloat( final float defaultValue ) 458 { 459 if( null == m_value ) 460 { 461 return defaultValue; 462 } 463 else 464 { 465 try 466 { 467 return Float.parseFloat( m_value ); 468 } 469 catch( final NumberFormatException nfe ) 470 { 471 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 public String[] getAttributeNames() 482 { 483 final Map attributeMap = getAttributeMap(); 484 if( null == attributeMap ) 485 { 486 return EMPTY_STRING_ARRAY; 487 } 488 else 489 { 490 final Set keys = attributeMap.keySet(); 491 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 public String getAttribute( final String name ) 504 throws ConfigurationException 505 { 506 final String value = doGetAttribute( name ); 507 if( null != value ) 508 { 509 return value; 510 } 511 else 512 { 513 final String message = 514 "Attribute named " + name + " not specified."; 515 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 public String getAttribute( final String name, 529 final String defaultValue ) 530 { 531 final String value = doGetAttribute( name ); 532 if( null != value ) 533 { 534 return value; 535 } 536 else 537 { 538 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 private String doGetAttribute( final String name ) 550 { 551 if( null == name ) 552 { 553 throw new NullPointerException( "name" ); 554 } 555 final Map attributeMap = getAttributeMap(); 556 if( null != attributeMap ) 557 { 558 final String value = (String)attributeMap.get( name ); 559 if( null != value ) 560 { 561 return value; 562 } 563 } 564 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 public boolean getAttributeAsBoolean( final String name ) 577 throws ConfigurationException 578 { 579 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 public boolean getAttributeAsBoolean( final String name, 593 final boolean defaultValue ) 594 { 595 final String value = getAttribute( name, null ); 596 if( null != value ) 597 { 598 return value.equals( TRUE_STRING ); 599 } 600 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 public int getAttributeAsInteger( final String name ) 613 throws ConfigurationException 614 { 615 final String value = getAttribute( name ); 616 try 617 { 618 return Integer.parseInt( value ); 619 } 620 catch( final NumberFormatException nfe ) 621 { 622 final String message = 623 "Unable to parse " + value + " as an Integer."; 624 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 public int getAttributeAsInteger( final String name, 639 final int defaultValue ) 640 { 641 final String value = getAttribute( name, null ); 642 if( null != value ) 643 { 644 try 645 { 646 return Integer.parseInt( value ); 647 } 648 catch( final NumberFormatException nfe ) 649 { 650 //Fall through to return defaultValue 651 } 652 } 653 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 public long getAttributeAsLong( final String name ) 666 throws ConfigurationException 667 { 668 final String value = getAttribute( name ); 669 try 670 { 671 return Long.parseLong( value ); 672 } 673 catch( final NumberFormatException nfe ) 674 { 675 final String message = 676 "Unable to parse " + value + " as a Long."; 677 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 public long getAttributeAsLong( final String name, 692 final long defaultValue ) 693 { 694 final String value = getAttribute( name, null ); 695 if( null != value ) 696 { 697 try 698 { 699 return Long.parseLong( value ); 700 } 701 catch( final NumberFormatException nfe ) 702 { 703 //Fall through to return defaultValue 704 } 705 } 706 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 public float getAttributeAsFloat( final String name ) 719 throws ConfigurationException 720 { 721 final String value = getAttribute( name ); 722 try 723 { 724 return Float.parseFloat( value ); 725 } 726 catch( final NumberFormatException nfe ) 727 { 728 final String message = 729 "Unable to parse " + value + " as a Float."; 730 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 public float getAttributeAsFloat( final String name, 745 final float defaultValue ) 746 { 747 final String value = getAttribute( name, null ); 748 if( null != value ) 749 { 750 try 751 { 752 return Float.parseFloat( value ); 753 } 754 catch( final NumberFormatException nfe ) 755 { 756 //Fall through to return defaultValue 757 } 758 } 759 return defaultValue; 760 } 761 762 /*** 763 * Mark the configuration and child configurations as read only. 764 */ 765 public void makeReadOnly() 766 { 767 super.makeReadOnly(); 768 final List children = getChildList(); 769 if( null != children ) 770 { 771 final int count = children.size(); 772 for( int i = 0; i < count; i++ ) 773 { 774 final Configuration configuration = (Configuration)children.get( i ); 775 if( configuration instanceof Freezable ) 776 { 777 ( (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 public void setAttribute( final String key, 790 final String value ) 791 { 792 if( null == key ) 793 { 794 throw new NullPointerException( "key" ); 795 } 796 if( null == value ) 797 { 798 throw new NullPointerException( "value" ); 799 } 800 checkWriteable(); 801 if( null == m_attributes ) 802 { 803 m_attributes = new HashMap(); 804 } 805 m_attributes.put( key, value ); 806 } 807 808 /*** 809 * Add a child configuration element. 810 * 811 * @param configuration the child configuration element. 812 */ 813 public void addChild( final Configuration configuration ) 814 { 815 if( null == configuration ) 816 { 817 throw new NullPointerException( "configuration" ); 818 } 819 checkWriteable(); 820 if( null != m_value ) 821 { 822 throwMixedContentException(); 823 } 824 if( null == m_children ) 825 { 826 m_children = new ArrayList(); 827 } 828 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 public void setValue( final String value ) 837 { 838 if( null == value ) 839 { 840 throw new NullPointerException( "value" ); 841 } 842 checkWriteable(); 843 final List children = getChildList(); 844 if( null != children && 0 != children.size() ) 845 { 846 throwMixedContentException(); 847 } 848 m_value = value; 849 } 850 851 /*** 852 * Overide toString to improve ability to debug implementation. 853 * 854 * @return string representation of object 855 */ 856 public String toString() 857 { 858 final StringBuffer sb = new StringBuffer(); 859 sb.append( "[Configuration name='" ); 860 sb.append( getName() ); 861 sb.append( "'" ); 862 if( null != m_attributes ) 863 { 864 sb.append( " attributes=" ); 865 sb.append( m_attributes ); 866 } 867 sb.append( "]" ); 868 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 protected final List getChildList() 877 { 878 return m_children; 879 } 880 881 /*** 882 * Return the backing map for attributes. 883 * 884 * @return the backing map for attributes. 885 */ 886 protected final Map getAttributeMap() 887 { 888 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 protected final String generateLocation() 898 { 899 final String location = getLocation(); 900 if( !location.endsWith( AUTOGEN_POSTFIX ) ) 901 { 902 return location + AUTOGEN_POSTFIX; 903 } 904 else 905 { 906 return location; 907 } 908 } 909 910 /*** 911 * Throw an IllegalStateException warning about 912 * mixed content. 913 */ 914 protected final void throwMixedContentException() 915 { 916 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 throw new IllegalStateException( message ); 921 } 922 }

This page was automatically generated by Maven