1 7 package org.jboss.xb.binding.metadata.unmarshalling.impl; 8 9 import org.jboss.xb.binding.metadata.unmarshalling.DocumentBindingFactory; 10 import org.jboss.xb.binding.metadata.unmarshalling.NamespaceBinding; 11 import org.jboss.xb.binding.metadata.unmarshalling.DocumentBinding; 12 import org.jboss.xb.binding.metadata.unmarshalling.TopElementBinding; 13 import org.jboss.xb.binding.metadata.unmarshalling.ElementBinding; 14 import org.jboss.xb.binding.metadata.unmarshalling.BasicElementBinding; 15 import org.jboss.xb.binding.metadata.unmarshalling.AttributeBinding; 16 import org.jboss.xb.binding.metadata.unmarshalling.DocumentBindingStack; 17 import org.jboss.xb.binding.metadata.unmarshalling.DocumentBinder; 18 import org.jboss.xb.binding.metadata.unmarshalling.XmlValueBinding; 19 import org.jboss.xb.binding.metadata.unmarshalling.XmlValueContainer; 20 import org.jboss.xb.binding.JBossXBRuntimeException; 21 22 import javax.xml.namespace.QName ; 23 import java.util.ArrayList ; 24 import java.util.Collection ; 25 import java.util.List ; 26 import java.util.Map ; 27 import java.util.HashMap ; 28 import java.lang.reflect.Field ; 29 import java.lang.reflect.Method ; 30 import java.lang.reflect.Modifier ; 31 import java.lang.reflect.Constructor ; 32 33 37 public class DocumentBindingFactoryImpl 38 extends DocumentBindingFactory 39 { 40 public DocumentBindingStack newDocumentBindingStack() 41 { 42 return new DocumentBindingStackImpl(); 43 } 44 45 public NamespaceBinding bindNamespace(DocumentBinding doc, String namespaceUri, String javaPackage) 46 { 47 DocumentBindingStackImpl docStack = (DocumentBindingStackImpl)doc; 48 return docStack.bindNamespace(new DefaultNamespaceBinding(docStack, namespaceUri, javaPackage)); 49 } 50 51 public TopElementBinding bindTopElement(NamespaceBinding ns, String elementName, Class javaClass) 52 { 53 NamespaceBindingStack nsStack = (NamespaceBindingStack)ns; 54 return nsStack.bindTopElement(new DefaultTopElementBinding(nsStack, elementName, javaClass)); 55 } 56 57 public ElementBinding bindElement(BasicElementBinding parent, 58 String namespaceUri, 59 String elementName, 60 String fieldName, 61 Class javaType) 62 { 63 BasicElementBindingStack basicStack = (BasicElementBindingStack)parent; 64 return basicStack.bindChild( 65 new DefaultElementBinding(parent, new QName (namespaceUri, elementName), fieldName, javaType) 66 ); 67 } 68 69 public XmlValueBinding bindValue(BasicElementBinding element, String fieldName, Class javaType) 70 { 71 ElementBindingStack basicStack = (ElementBindingStack)element; 72 return basicStack.bindValue(new DefaultXmlValueBinding(element, fieldName, javaType)); 73 } 74 75 public XmlValueBinding bindValue(XmlValueContainer container, String fieldName, Class javaType) 76 { 77 XmlValueContainerStack stack = (XmlValueContainerStack)container; 78 return stack.bindValue(new DefaultXmlValueBinding(container, fieldName, javaType)); 79 } 80 81 public AttributeBinding bindAttribute(BasicElementBinding parent, 82 String namespaceUri, 83 String attributeName, 84 String fieldName, 85 Class javaType) 86 { 87 BasicElementBindingStack stack = (BasicElementBindingStack)parent; 88 AttributeBinding attr = new AttributeBindingImpl(new QName (namespaceUri, attributeName), 89 javaType, 90 parent.getJavaType(), 91 fieldName 92 ); 93 stack.bindAttribute(attr); 94 return attr; 95 } 96 97 public DocumentBinding newDocumentBinding() 98 { 99 return new DocumentBindingStackImpl(); 100 } 101 102 106 108 public static abstract class AbstractDocumentBinding 109 implements DocumentBinding 110 { 111 protected final DocumentBinding doc; 112 113 protected AbstractDocumentBinding(DocumentBinding doc) 114 { 115 if(doc == null) 116 { 117 doc = DocumentBindingFactory.newInstance().newDocumentBindingStack(); 119 ((DocumentBindingStackImpl)doc).push(this); 120 } 121 this.doc = doc; 122 } 123 124 public NamespaceBinding getNamespace(String namespaceUri) 125 { 126 return doc.getNamespace(namespaceUri); 127 } 128 129 protected abstract NamespaceBinding getNamespaceLocal(String namespaceUri); 130 } 131 132 public static abstract class AbstractNamespaceBinding 133 implements NamespaceBinding 134 { 135 protected final String namespaceUri; 136 private final DocumentBinding doc; 137 138 protected AbstractNamespaceBinding(DocumentBinding doc, String namespaceUri) 139 { 140 this.namespaceUri = namespaceUri; 141 this.doc = doc; 142 } 143 144 public DocumentBinding getDocument() 145 { 146 return doc; 147 } 148 149 public String getNamespaceUri() 150 { 151 return namespaceUri; 152 } 153 154 public String getJavaPackage() 155 { 156 return doc.getNamespace(namespaceUri).getJavaPackage(); 157 } 158 159 public TopElementBinding getTopElement(String elementName) 160 { 161 return doc.getNamespace(namespaceUri).getTopElement(elementName); 162 } 163 164 protected abstract String getJavaPackageLocal(); 165 166 protected abstract TopElementBinding getTopElementLocal(String elementName); 167 } 168 169 public static abstract class AbstractXmlValueContainer 170 implements XmlValueContainer 171 { 172 protected final QName name; 173 174 public AbstractXmlValueContainer(QName name) 175 { 176 this.name = name; 177 } 178 179 public QName getName() 180 { 181 return name; 182 } 183 184 public XmlValueBinding getValue() 185 { 186 return getValueStackReference().getValue(); 187 } 188 189 public Class getJavaType() 190 { 191 return getValueStackReference().getJavaType(); 192 } 193 194 protected abstract XmlValueContainer getValueStackReference(); 195 196 protected abstract XmlValueBinding getValueLocal(); 197 198 protected abstract Class getJavaTypeLocal(); 199 } 200 201 public static abstract class AbstractBasicElementBinding 202 extends AbstractXmlValueContainer 203 implements BasicElementBinding 204 { 205 protected AbstractBasicElementBinding(QName elementName) 206 { 207 super(elementName); 208 } 209 210 public DocumentBinding getDocument() 211 { 212 return getStackReference().getDocument(); 213 } 214 215 public ElementBinding getElement(QName elementName) 216 { 217 return getStackReference().getElement(elementName); 218 } 219 220 public AttributeBinding getAttribute(QName attributeName) 221 { 222 return getStackReference().getAttribute(attributeName); 223 } 224 225 public XmlValueBinding getValue() 226 { 227 return getStackReference().getValue(); 228 } 229 230 protected XmlValueContainer getValueStackReference() 231 { 232 return getStackReference(); 233 } 234 235 protected abstract Class getJavaTypeLocal(); 236 237 protected abstract ElementBinding getElementLocal(QName elementName); 238 239 protected abstract AttributeBinding getAttributeLocal(QName attributeName); 240 241 protected abstract XmlValueBinding getValueLocal(); 242 243 protected abstract BasicElementBinding getStackReference(); 244 } 245 246 public static abstract class AbstractTopElementBinding 247 extends AbstractBasicElementBinding 248 implements TopElementBinding 249 { 250 protected final NamespaceBinding ns; 251 252 protected AbstractTopElementBinding(NamespaceBinding ns, String elementName) 253 { 254 super(new QName (ns.getNamespaceUri(), elementName)); 255 this.ns = ns; 256 } 257 258 protected BasicElementBinding getStackReference() 259 { 260 return ns.getTopElement(name.getLocalPart()); 261 } 262 } 263 264 public static abstract class AbstractElementBinding 265 extends AbstractBasicElementBinding 266 implements ElementBinding 267 { 268 protected final BasicElementBinding parent; 269 270 protected AbstractElementBinding(BasicElementBinding parent, QName elementName) 271 { 272 super(elementName); 273 this.parent = parent; 274 } 275 276 public Field getField() 277 { 278 return ((ElementBinding)getStackReference()).getField(); 279 } 280 281 public Method getGetter() 282 { 283 return ((ElementBinding)getStackReference()).getGetter(); 284 } 285 286 public Method getSetter() 287 { 288 return ((ElementBinding)getStackReference()).getSetter(); 289 } 290 291 public Class getFieldType() 292 { 293 return ((ElementBinding)getStackReference()).getFieldType(); 294 } 295 296 protected BasicElementBinding getStackReference() 297 { 298 return parent.getElement(name); 299 } 300 301 protected abstract Field getFieldLocal(); 302 303 protected abstract Method getGetterLocal(); 304 305 protected abstract Method getSetterLocal(); 306 307 protected abstract Class getFieldTypeLocal(); 308 } 309 310 public static abstract class AbstractXmlValueBinding 311 extends AbstractXmlValueContainer 312 implements XmlValueBinding 313 { 314 private final XmlValueContainer container; 315 316 protected AbstractXmlValueBinding(XmlValueContainer container) 317 { 318 super(container.getName()); 319 this.container = container; 320 } 321 322 public Field getField() 323 { 324 return container.getValue().getField(); 325 } 326 327 public Method getGetter() 328 { 329 return container.getValue().getGetter(); 330 } 331 332 public Method getSetter() 333 { 334 return container.getValue().getSetter(); 335 } 336 337 public Class getFieldType() 338 { 339 return container.getValue().getFieldType(); 340 } 341 342 public XmlValueBinding getValue() 343 { 344 return container.getValue().getValue(); 345 } 346 347 protected XmlValueContainer getValueStackReference() 348 { 349 return container.getValue(); 350 } 351 352 protected abstract Field getFieldLocal(); 353 354 protected abstract Method getGetterLocal(); 355 356 protected abstract Method getSetterLocal(); 357 358 protected abstract Class getFieldTypeLocal(); 359 } 360 361 363 private static class DefaultNamespaceBinding 364 extends AbstractNamespaceBinding 365 { 366 private final String javaPackage; 367 368 public DefaultNamespaceBinding(DocumentBinding doc, String namespaceUri, String javaPackage) 369 { 370 super(doc, namespaceUri); 371 this.javaPackage = javaPackage; 372 } 373 374 protected String getJavaPackageLocal() 375 { 376 return javaPackage; 377 } 378 379 protected TopElementBinding getTopElementLocal(String elementName) 380 { 381 return null; 382 } 383 } 384 385 private static class DefaultTopElementBinding 386 extends AbstractTopElementBinding 387 { 388 private final Class javaType; 389 390 DefaultTopElementBinding(NamespaceBinding ns, String elementName, Class javaType) 391 { 392 super(ns, elementName); 393 this.javaType = javaType; 394 } 395 396 protected Class getJavaTypeLocal() 397 { 398 return javaType; 399 } 400 401 protected ElementBinding getElementLocal(QName elementName) 402 { 403 return null; 404 } 405 406 protected AttributeBinding getAttributeLocal(QName attributeName) 407 { 408 return null; 409 } 410 411 protected XmlValueBinding getValueLocal() 412 { 413 return null; 414 } 415 } 416 417 private static class DefaultElementBinding 418 extends AbstractElementBinding 419 { 420 private final Field field; 421 private final Method getter; 422 private final Method setter; 423 private final Class fieldType; 424 private final Class javaType; 425 426 public DefaultElementBinding(BasicElementBinding parent, QName elementName, String fieldName, Class javaType) 427 { 428 super(parent, elementName); 429 430 Class parentType = parent.getJavaType(); 431 if(Collection .class.isAssignableFrom(parentType)) 432 { 433 field = null; 434 getter = null; 435 setter = null; 436 fieldType = null; 437 } 438 else 439 { 440 Field tmpField = null; 441 Method tmpGetter = null; 442 Method tmpSetter = null; 443 Class tmpFieldType; 444 try 445 { 446 tmpField = parentType.getField(fieldName); 447 tmpFieldType = tmpField.getType(); 448 } 449 catch(NoSuchFieldException e) 450 { 451 String baseMethodName = Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1); 452 try 453 { 454 tmpGetter = parentType.getMethod("get" + baseMethodName, null); 455 tmpFieldType = tmpGetter.getReturnType(); 456 try 457 { 458 tmpSetter = parentType.getMethod("set" + baseMethodName, new Class []{tmpGetter.getReturnType()}); 459 } 460 catch(NoSuchMethodException nosetter) 461 { 462 } 464 } 465 catch(NoSuchMethodException e1) 466 { 467 throw new JBossXBRuntimeException("Failed to bind " + 468 elementName + 469 " to field " + 470 fieldName + 471 " in " + 472 parentType + 473 ": neither field nor getter/setter were found." 474 ); 475 } 476 } 477 478 field = tmpField; 479 getter = tmpGetter; 480 setter = tmpSetter; 481 fieldType = tmpFieldType; 482 } 483 484 if(fieldType == null) 485 { 486 this.javaType = javaType == null ? String .class : javaType; 487 } 488 else 489 { 490 if(javaType == null) 491 { 492 this.javaType = fieldType; 493 } 494 else if(Collection .class == fieldType || 495 Collection .class.isAssignableFrom(fieldType) || 496 fieldType.isAssignableFrom(javaType)) 497 { 498 this.javaType = javaType; 499 } 500 else 501 { 502 throw new JBossXBRuntimeException("Failed to bind " + 503 elementName + 504 " to field " + 505 fieldName + 506 " in " + 507 parentType + 508 ": field type " + fieldType + " is not assignable from the specified Java type " + javaType 509 ); 510 } 511 512 if(this.javaType.isInterface() || Modifier.isAbstract(this.javaType.getModifiers())) 513 { 514 throw new JBossXBRuntimeException("Failed to bind " + 515 elementName + 516 " to field " + 517 fieldName + 518 " in " + 519 parentType + 520 ": Java type is abstract class or interface." 521 ); 522 } 523 } 524 } 525 526 protected Field getFieldLocal() 527 { 528 return field; 529 } 530 531 protected Method getGetterLocal() 532 { 533 return getter; 534 } 535 536 protected Method getSetterLocal() 537 { 538 return setter; 539 } 540 541 protected Class getFieldTypeLocal() 542 { 543 return fieldType; 544 } 545 546 protected Class getJavaTypeLocal() 547 { 548 return javaType; 549 } 550 551 protected ElementBinding getElementLocal(QName elementName) 552 { 553 return null; 554 } 555 556 protected AttributeBinding getAttributeLocal(QName attributeName) 557 { 558 return null; 559 } 560 561 protected XmlValueBinding getValueLocal() 562 { 563 return null; 564 } 565 } 566 567 private static class DefaultXmlValueBinding 568 extends AbstractXmlValueBinding 569 { 570 private final Field field; 571 private final Method getter; 572 private final Method setter; 573 private final Class fieldType; 574 private final Class javaType; 575 576 public DefaultXmlValueBinding(XmlValueContainer container, String fieldName, Class javaType) 577 { 578 super(container); 579 580 Class parentType = container.getJavaType(); 581 if(Collection .class.isAssignableFrom(parentType)) 582 { 583 field = null; 584 getter = null; 585 setter = null; 586 fieldType = null; 587 } 588 else 589 { 590 Field tmpField = null; 591 Method tmpGetter = null; 592 Method tmpSetter = null; 593 Class tmpFieldType = null; 594 try 595 { 596 tmpField = parentType.getField(fieldName); 597 tmpFieldType = tmpField.getType(); 598 } 599 catch(NoSuchFieldException e) 600 { 601 String baseMethodName = Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1); 602 try 603 { 604 tmpGetter = parentType.getMethod("get" + baseMethodName, null); 605 tmpFieldType = tmpGetter.getReturnType(); 606 try 607 { 608 tmpSetter = parentType.getMethod("set" + baseMethodName, new Class []{tmpGetter.getReturnType()}); 609 } 610 catch(NoSuchMethodException nosetter) 611 { 612 } 614 } 615 catch(NoSuchMethodException e1) 616 { 617 throw new JBossXBRuntimeException("Failed to bind value of " + 618 container.getName() + 619 " to field " + 620 fieldName + 621 " in " + 622 parentType + 623 ": neither field nor getter/setter were found." 624 ); 625 } 626 } 627 628 field = tmpField; 629 getter = tmpGetter; 630 setter = tmpSetter; 631 fieldType = tmpFieldType; 632 } 633 634 if(fieldType == null) 635 { 636 this.javaType = javaType == null ? String .class : javaType; 637 } 638 else 639 { 640 if(javaType == null) 641 { 642 this.javaType = fieldType; 643 } 644 else if(Collection .class == fieldType || 645 Collection .class.isAssignableFrom(fieldType) || 646 fieldType.isAssignableFrom(javaType)) 647 { 648 this.javaType = javaType; 649 } 650 else 651 { 652 throw new JBossXBRuntimeException("Failed to bind value of " + 653 container.getName() + 654 " to field " + 655 fieldName + 656 " in " + 657 parentType + 658 ": field type " + fieldType + " is not assignable from the specified Java type " + javaType 659 ); 660 } 661 662 if(this.javaType.isInterface() || Modifier.isAbstract(this.javaType.getModifiers())) 663 { 664 throw new JBossXBRuntimeException("Failed to bind value of " + 665 container.getName() + 666 " to field " + 667 fieldName + 668 " in " + 669 parentType + 670 ": Java type is abstract class or interface." 671 ); 672 } 673 } 674 } 675 676 protected Field getFieldLocal() 677 { 678 return field; 679 } 680 681 protected Method getGetterLocal() 682 { 683 return getter; 684 } 685 686 protected Method getSetterLocal() 687 { 688 return setter; 689 } 690 691 protected Class getFieldTypeLocal() 692 { 693 return fieldType; 694 } 695 696 protected XmlValueBinding getValueLocal() 697 { 698 return null; 699 } 700 701 protected Class getJavaTypeLocal() 702 { 703 return javaType; 704 } 705 } 706 707 709 class DocumentBindingStackImpl 710 implements DocumentBindingStack 711 { 712 private final List stack = new ArrayList (); 713 private final Map namespaces = new HashMap (); 714 715 public DocumentBindingStackImpl() 716 { 717 } 718 719 public DocumentBindingStackImpl(DocumentBinding doc) 720 { 721 if(doc != null) 722 { 723 push(doc); 724 } 725 } 726 727 void push(DocumentBinding doc) 728 { 729 stack.add(doc); 730 } 731 732 NamespaceBindingStack bindNamespace(NamespaceBinding ns) 733 { 734 NamespaceBindingStack stack = (NamespaceBindingStack)getNamespace(ns.getNamespaceUri()); 735 if(stack == null) 736 { 737 stack = new NamespaceBindingStack(this, ns.getNamespaceUri()); 738 namespaces.put(ns.getNamespaceUri(), stack); 739 } 740 stack.push(ns); 741 return stack; 742 } 743 744 public NamespaceBinding getNamespace(String namespaceUri) 745 { 746 NamespaceBindingStack nsStack = (NamespaceBindingStack)namespaces.get(namespaceUri); 747 if(nsStack == null) 748 { 749 nsStack = new NamespaceBindingStack(this, namespaceUri); 750 for(int i = 0; i < stack.size(); ++i) 751 { 752 AbstractDocumentBinding doc = (AbstractDocumentBinding)stack.get(i); 753 NamespaceBinding local = doc.getNamespaceLocal(namespaceUri); 754 if(local != null) 755 { 756 nsStack.push(local); 757 } 758 } 759 760 if(nsStack.delegates.size() > 0) 761 { 762 namespaces.put(namespaceUri, nsStack); 763 } 764 else 765 { 766 nsStack = null; 767 } 768 } 769 return nsStack; 770 } 771 772 public DocumentBindingStack push(Class documentBindingClass) 773 { 774 pushNewDocumentBinding(documentBindingClass); 775 return this; 776 } 777 778 public DocumentBindingStack push(Class documentBindingClass, DocumentBinder binder) 779 { 780 DocumentBinding newDoc = pushNewDocumentBinding(documentBindingClass); 781 binder.bind(newDoc); 782 return this; 783 } 784 785 787 private DocumentBinding pushNewDocumentBinding(Class documentBindingClass) 788 { 789 if(!DocumentBinding.class.isAssignableFrom(documentBindingClass)) 790 { 791 throw new JBossXBRuntimeException("The class must implement " + DocumentBinding.class); 792 } 793 794 DocumentBinding doc; 795 try 796 { 797 Constructor ctor = documentBindingClass.getConstructor(new Class []{DocumentBinding.class}); 798 doc = (DocumentBinding)ctor.newInstance(new Object []{this}); 799 push(doc); 800 } 801 catch(NoSuchMethodException e) 802 { 803 throw new JBossXBRuntimeException( 804 "The class must have a constructor with one parameter of type " + DocumentBinding.class 805 ); 806 } 807 catch(Exception e) 808 { 809 throw new JBossXBRuntimeException("Failed to create an instance of " + 810 documentBindingClass + 811 " using constructor which takes one parameter of type " + 812 DocumentBinding.class + 813 ": " + 814 e.getMessage() 815 ); 816 } 817 return doc; 818 } 819 } 820 821 class NamespaceBindingStack 822 implements NamespaceBinding 823 { 824 private final DocumentBinding doc; 825 private final String namespaceUri; 826 private final List delegates = new ArrayList (); 827 private final Map tops = new HashMap (); 828 829 public NamespaceBindingStack(DocumentBinding doc, String namespaceUri) 830 { 831 this.doc = doc; 832 this.namespaceUri = namespaceUri; 833 } 834 835 TopElementBinding bindTopElement(TopElementBinding top) 836 { 837 TopElementBindingStack stack = (TopElementBindingStack)getTopElement(top.getName().getLocalPart()); 838 if(stack == null) 839 { 840 stack = new TopElementBindingStack(doc, top.getName()); 841 tops.put(stack.getName().getLocalPart(), stack); 842 } 843 stack.push(top); 844 return stack; 845 } 846 847 void push(NamespaceBinding ns) 848 { 849 delegates.add(ns); 850 } 851 852 public String getNamespaceUri() 853 { 854 return namespaceUri; 855 } 856 857 public String getJavaPackage() 858 { 859 return ((AbstractNamespaceBinding)delegates.get(delegates.size() - 1)).getJavaPackageLocal(); 860 } 861 862 public DocumentBinding getDocument() 863 { 864 return doc; 865 } 866 867 public TopElementBinding getTopElement(String elementName) 868 { 869 TopElementBindingStack stack = (TopElementBindingStack)tops.get(elementName); 870 if(stack == null) 871 { 872 stack = new TopElementBindingStack(doc, new QName (namespaceUri, elementName)); 873 for(int i = 0; i < delegates.size(); ++i) 874 { 875 AbstractNamespaceBinding ns = (AbstractNamespaceBinding)delegates.get(i); 876 TopElementBinding local = ns.getTopElementLocal(elementName); 877 if(local != null) 878 { 879 stack.push(local); 880 } 881 } 882 883 if(stack.delegates.size() > 0) 884 { 885 tops.put(elementName, stack); 886 } 887 else 888 { 889 stack = null; 890 } 891 } 892 return stack; 893 } 894 } 895 896 class XmlValueContainerStack 897 implements XmlValueContainer 898 { 899 protected final QName name; 900 final List delegates = new ArrayList (); 901 private XmlValueBindingStack value; 902 903 public XmlValueContainerStack(QName name) 904 { 905 this.name = name; 906 } 907 908 void push(XmlValueContainer container) 909 { 910 delegates.add(container); 911 } 912 913 XmlValueBinding bindValue(XmlValueBinding value) 914 { 915 getValue(); 916 if(this.value == null) 917 { 918 this.value = new XmlValueBindingStack(this); 919 } 920 this.value.push(value); 921 return this.value; 922 } 923 924 public QName getName() 925 { 926 return name; 927 } 928 929 public XmlValueBinding getValue() 930 { 931 if(value == null) 932 { 933 for(int i = 0; i < delegates.size(); ++i) 934 { 935 AbstractXmlValueContainer basic = (AbstractXmlValueContainer)delegates.get(i); 936 XmlValueBinding localValue = basic.getValueLocal(); 937 if(localValue != null) 938 { 939 if(value == null) 940 { 941 value = new XmlValueBindingStack(this); 942 } 943 value.push(localValue); 944 } 945 } 946 } 947 return value; 948 } 949 950 public Class getJavaType() 951 { 952 return ((AbstractXmlValueContainer)delegates.get(delegates.size() - 1)).getJavaTypeLocal(); 953 } 954 } 955 956 class BasicElementBindingStack 957 extends XmlValueContainerStack 958 implements BasicElementBinding 959 { 960 private final DocumentBinding doc; 961 private final Map children = new HashMap (); 962 private final Map attributes = new HashMap (); 963 964 public BasicElementBindingStack(DocumentBinding doc, QName elementName) 965 { 966 super(elementName); 967 this.doc = doc; 968 } 969 970 ElementBinding bindChild(ElementBinding element) 971 { 972 ElementBindingStack stack = (ElementBindingStack)getElement(element.getName()); 973 if(stack == null) 974 { 975 stack = new ElementBindingStack(doc, element.getName()); 976 children.put(stack.getName(), stack); 977 } 978 stack.push(element); 979 return stack; 980 } 981 982 void bindAttribute(AttributeBinding attr) 983 { 984 attributes.put(attr.getAttributeName(), attr); 985 } 986 987 public DocumentBinding getDocument() 988 { 989 return doc; 990 } 991 992 public ElementBinding getElement(QName elementName) 993 { 994 ElementBindingStack stack = (ElementBindingStack)children.get(elementName); 995 if(stack == null) 996 { 997 stack = new ElementBindingStack(doc, elementName); 998 for(int i = 0; i < delegates.size(); ++i) 999 { 1000 AbstractBasicElementBinding el = (AbstractBasicElementBinding)delegates.get(i); 1001 ElementBinding local = el.getElementLocal(elementName); 1002 if(local != null) 1003 { 1004 stack.push(local); 1005 } 1006 } 1007 1008 if(stack.delegates.size() > 0) 1009 { 1010 children.put(elementName, stack); 1011 } 1012 else 1013 { 1014 stack = null; 1015 } 1016 } 1017 return stack; 1018 } 1019 1020 public AttributeBinding getAttribute(QName attributeName) 1021 { 1022 AttributeBinding attr = (AttributeBinding)attributes.get(attributeName); 1023 if(attr == null) 1024 { 1025 for(int i = delegates.size() - 1; i >= 0; --i) 1026 { 1027 AbstractBasicElementBinding basic = (AbstractBasicElementBinding)delegates.get(i); 1028 attr = basic.getAttributeLocal(attributeName); 1029 if(attr != null) 1030 { 1031 break; 1032 } 1033 } 1034 } 1035 return attr; 1036 } 1037 } 1038 1039 class TopElementBindingStack 1040 extends BasicElementBindingStack 1041 implements TopElementBinding 1042 { 1043 public TopElementBindingStack(DocumentBinding doc, QName elementName) 1044 { 1045 super(doc, elementName); 1046 } 1047 } 1048 1049 class ElementBindingStack 1050 extends BasicElementBindingStack 1051 implements ElementBinding 1052 { 1053 public ElementBindingStack(DocumentBinding doc, QName elementName) 1054 { 1055 super(doc, elementName); 1056 } 1057 1058 public Field getField() 1059 { 1060 return getLatestBinding().getFieldLocal(); 1061 } 1062 1063 public Method getGetter() 1064 { 1065 return getLatestBinding().getGetterLocal(); 1066 } 1067 1068 public Method getSetter() 1069 { 1070 return getLatestBinding().getSetterLocal(); 1071 } 1072 1073 public Class getFieldType() 1074 { 1075 return getLatestBinding().getFieldTypeLocal(); 1076 } 1077 1078 1080 protected AbstractElementBinding getLatestBinding() 1081 { 1082 return (AbstractElementBinding)delegates.get(delegates.size() - 1); 1083 } 1084 } 1085 1086 class XmlValueBindingStack 1087 extends XmlValueContainerStack 1088 implements XmlValueBinding 1089 { 1090 public XmlValueBindingStack(XmlValueContainer container) 1091 { 1092 super(container.getName()); 1093 } 1094 1095 public Field getField() 1096 { 1097 return getLatestBinding().getFieldLocal(); 1098 } 1099 1100 public Method getGetter() 1101 { 1102 return getLatestBinding().getGetterLocal(); 1103 } 1104 1105 public Method getSetter() 1106 { 1107 return getLatestBinding().getSetterLocal(); 1108 } 1109 1110 public Class getFieldType() 1111 { 1112 return getLatestBinding().getFieldTypeLocal(); 1113 } 1114 1115 private AbstractXmlValueBinding getLatestBinding() 1116 { 1117 return (AbstractXmlValueBinding)delegates.get(delegates.size() - 1); 1118 } 1119 } 1120} 1121 | Popular Tags |