1 22 package org.jboss.xb.binding.sunday.unmarshalling; 23 24 import java.util.ArrayList ; 25 import java.util.Collection ; 26 import java.util.List ; 27 import java.util.ListIterator ; 28 import javax.xml.namespace.QName ; 29 import org.apache.xerces.xs.XSTypeDefinition; 30 import org.jboss.logging.Logger; 31 import org.jboss.util.StringPropertyReplacer; 32 import org.jboss.xb.binding.Constants; 33 import org.jboss.xb.binding.GenericValueContainer; 34 import org.jboss.xb.binding.JBossXBRuntimeException; 35 import org.jboss.xb.binding.NamespaceRegistry; 36 import org.jboss.xb.binding.Util; 37 import org.jboss.xb.binding.group.ValueList; 38 import org.jboss.xb.binding.group.ValueListHandler; 39 import org.jboss.xb.binding.group.ValueListInitializer; 40 import org.jboss.xb.binding.introspection.FieldInfo; 41 import org.jboss.xb.binding.metadata.CharactersMetaData; 42 import org.jboss.xb.binding.metadata.PropertyMetaData; 43 import org.jboss.xb.binding.metadata.ValueMetaData; 44 import org.jboss.xb.binding.parser.JBossXBParser; 45 import org.jboss.xb.binding.sunday.xop.XOPIncludeHandler; 46 import org.xml.sax.Attributes ; 47 48 54 public class SundayContentHandler 55 implements JBossXBParser.ContentHandler 56 { 57 private final static Logger log = Logger.getLogger(SundayContentHandler.class); 58 59 private final static Object NIL = new Object (); 60 61 private final SchemaBinding schema; 62 private final SchemaBindingResolver schemaResolver; 63 64 private final StackImpl stack = new StackImpl(); 65 66 private Object root; 67 private NamespaceRegistry nsRegistry = new NamespaceRegistry(); 68 69 private ParticleHandler defParticleHandler = DefaultHandlers.ELEMENT_HANDLER; 70 71 private UnmarshallingContextImpl ctx = new UnmarshallingContextImpl(); 72 73 private final boolean trace = log.isTraceEnabled(); 74 75 public SundayContentHandler(SchemaBinding schema) 76 { 77 this.schema = schema; 78 this.schemaResolver = null; 79 } 80 81 public SundayContentHandler(SchemaBindingResolver schemaResolver) 82 { 83 this.schemaResolver = schemaResolver; 84 this.schema = null; 85 } 86 87 public void characters(char[] ch, int start, int length) 88 { 89 StackItem stackItem = stack.peek(); 90 if(stackItem.cursor == null) 91 { 92 if(stackItem.textContent == null) 93 { 94 stackItem.textContent = new StringBuffer (); 95 } 96 stackItem.textContent.append(ch, start, length); 97 } 98 } 99 100 public void endElement(String namespaceURI, String localName, String qName) 101 { 102 ElementBinding elementBinding = null; 103 QName endName = localName.length() == 0 ? new QName (qName) : new QName (namespaceURI, localName); 104 StackItem item; 105 while(true) 106 { 107 item = stack.peek(); 108 if(item.cursor == null) 109 { 110 if(item.ended) 111 { 112 pop(); 113 if(item.particle.isRepeatable()) 114 { 115 endRepeatableParticle(item.particle); 116 } 117 } 118 else 119 { 120 elementBinding = (ElementBinding)item.particle.getTerm(); 121 item.ended = true; 122 break; 123 } 124 } 125 else 126 { 127 if(!item.ended) { 129 endParticle(item, endName, 1); 130 } 131 132 ParticleBinding currentParticle = item.cursor.getCurrentParticle(); 133 TermBinding term = currentParticle.getTerm(); 134 if(term.isWildcard() && currentParticle.isRepeatable()) 135 { 136 endRepeatableParticle(currentParticle); 137 } 138 139 pop(); 140 if(item.particle.isRepeatable()) 141 { 142 endRepeatableParticle(item.particle); 143 } 144 } 145 } 146 147 if(elementBinding == null) 148 { 149 throw new JBossXBRuntimeException("Failed to endElement " + qName + ": binding not found"); 150 } 151 152 if(!elementBinding.getQName().equals(endName)) 153 { 154 throw new JBossXBRuntimeException("Failed to end element " + 155 new QName (namespaceURI, localName) + 156 ": element on the stack is " + elementBinding.getQName() 157 ); 158 } 159 160 endElement(); 161 } 162 163 public void startElement(String namespaceURI, 164 String localName, 165 String qName, 166 Attributes atts, 167 XSTypeDefinition xercesType) 168 { 169 QName startName = localName.length() == 0 ? new QName (qName) : new QName (namespaceURI, localName); 170 ParticleBinding particle = null; 171 ParticleHandler handler = null; 172 boolean repeated = false; 173 boolean repeatedParticle = false; 174 StackItem item = null; 175 ModelGroupBinding.Cursor cursor = null; SchemaBinding schemaBinding = schema; 177 178 if(stack.isEmpty()) 179 { 180 if(schemaBinding != null) 181 { 182 particle = schemaBinding.getElementParticle(startName); 183 } 184 else if(schemaResolver != null) 185 { 186 String schemaLocation = atts == null ? null : Util.getSchemaLocation(atts, namespaceURI); 187 schemaBinding = schemaResolver.resolve(namespaceURI, null, schemaLocation); 188 if(schemaBinding != null) 189 { 190 particle = schemaBinding.getElementParticle(startName); 191 } 192 else 193 { 194 throw new JBossXBRuntimeException("Failed to resolve schema nsURI=" + namespaceURI + " location=" + schemaLocation); 195 } 196 } 197 else 198 { 199 throw new JBossXBRuntimeException("Neither schema binding nor schema binding resolver is available!"); 200 } 201 } 202 else 203 { 204 while(!stack.isEmpty()) 205 { 206 item = stack.peek(); 207 if(item.cursor == null) 208 { 209 TermBinding term = item.particle.getTerm(); 210 ElementBinding element = (ElementBinding)term; 211 if(item.ended) 212 { 213 if(element.getQName().equals(startName)) 214 { 215 particle = item.particle; 216 repeated = true; 217 item.reset(); 218 219 if(!particle.isRepeatable()) 220 { 221 endRepeatableParent(startName); 222 } 223 } 224 else 225 { 226 pop(); 227 if(item.particle.isRepeatable()) 228 { 229 endRepeatableParticle(item.particle); 230 } 231 continue; 232 } 233 } 234 else 235 { 236 ParticleBinding typeParticle = element.getType().getParticle(); 237 ModelGroupBinding modelGroup = typeParticle == null ? 238 null : 239 (ModelGroupBinding)typeParticle.getTerm(); 240 if(modelGroup == null) 241 { 242 if(startName.equals(Constants.QNAME_XOP_INCLUDE)) 243 { 244 TypeBinding anyUriType = schema.getType(Constants.QNAME_ANYURI); 245 if(anyUriType == null) 246 { 247 log.warn("Type " + Constants.QNAME_ANYURI + " not bound."); 248 } 249 250 TypeBinding xopIncludeType = new TypeBinding(new QName (Constants.NS_XOP_INCLUDE, "Include")); 251 xopIncludeType.setSchemaBinding(schema); 252 xopIncludeType.addAttribute(new QName ("href"), anyUriType, DefaultHandlers.ATTRIBUTE_HANDLER); 253 xopIncludeType.setHandler(new XOPIncludeHandler(element.getType(), schema.getXopUnmarshaller())); 254 255 ElementBinding xopInclude = new ElementBinding(schema, Constants.QNAME_XOP_INCLUDE, xopIncludeType); 256 257 particle = new ParticleBinding(xopInclude); 258 259 ElementBinding parentElement = (ElementBinding) item.particle.getTerm(); 260 parentElement.setXopUnmarshaller(schema.getXopUnmarshaller()); 261 262 item.handler = DefaultHandlers.XOP_HANDLER; 263 item.ignoreCharacters = true; 264 item.o = item.handler.startParticle(stack.peek().o, startName, stack.peek().particle, null, nsRegistry); 265 break; 266 } 267 268 QName typeName = element.getType().getQName(); 269 throw new JBossXBRuntimeException((typeName == null ? "Anonymous" : typeName.toString()) + 270 " type of element " + 271 element.getQName() + 272 " should be complex and contain " + startName + " as a child element." 273 ); 274 } 275 276 cursor = modelGroup.newCursor(typeParticle); 277 List newCursors = cursor.startElement(startName, atts); 278 if(newCursors.isEmpty()) 279 { 280 throw new JBossXBRuntimeException(startName + 281 " not found as a child of " + 282 ((ElementBinding)term).getQName() 283 ); 284 } 285 else 286 { 287 Object o = item.o; 288 for(int i = newCursors.size() - 1; i >= 0; --i) 290 { 291 cursor = (ModelGroupBinding.Cursor)newCursors.get(i); 292 293 ParticleBinding modelGroupParticle = cursor.getParticle(); 294 if(modelGroupParticle.isRepeatable()) 295 { 296 startRepeatableParticle(startName, modelGroupParticle); 297 } 298 299 handler = getHandler(modelGroupParticle); 300 o = handler.startParticle(o, startName, modelGroupParticle, atts, nsRegistry); 301 push(cursor, o, handler); 302 } 303 particle = cursor.getCurrentParticle(); 304 } 305 } 306 break; 307 } 308 else 309 { 310 cursor = item.cursor; 311 if(cursor == null) 312 { 313 throw new JBossXBRuntimeException("No cursor for " + startName); 314 } 315 316 if(!item.ended && cursor.isPositioned() && cursor.getParticle().getTerm() instanceof ChoiceBinding) 318 { 319 endParticle(item, startName, 1); 320 if(!item.particle.isRepeatable()) { 322 pop(); 323 } 324 continue; 325 } 326 327 ParticleBinding prevParticle = cursor.isPositioned() ? cursor.getCurrentParticle() : null; 329 List newCursors = cursor.startElement(startName, atts); 330 if(newCursors.isEmpty()) 331 { 332 if(!item.ended) { 334 endParticle(item, startName, 1); 335 } 336 pop(); 337 } 338 else 339 { 340 if(item.ended) { 342 if(!item.particle.isRepeatable()) 343 { 344 throw new JBossXBRuntimeException("The particle expected to be repeatable but it's not: " + item.particle.getTerm()); 345 } 346 item.reset(); 347 348 handler = getHandler(item.particle); 349 item.o = handler.startParticle(stack.peek(1).o, startName, item.particle, atts, nsRegistry); 350 } 351 352 ParticleBinding curParticle = cursor.getCurrentParticle(); 353 if(curParticle != prevParticle) 354 { 355 if(prevParticle != null && prevParticle.isRepeatable() && prevParticle.getTerm().isModelGroup()) 356 { 357 endRepeatableParticle(prevParticle); 358 } 359 360 if(newCursors.size() > 1 && curParticle.isRepeatable()) 361 { 362 startRepeatableParticle(startName, curParticle); 363 } 364 } 365 else 366 { 367 repeatedParticle = true; 368 } 369 370 Object o = item.o; 372 for(int i = newCursors.size() - 2; i >= 0; --i) 373 { 374 cursor = (ModelGroupBinding.Cursor)newCursors.get(i); 375 376 ParticleBinding modelGroupParticle = cursor.getParticle(); 377 handler = getHandler(modelGroupParticle); 378 o = handler.startParticle(o, startName, modelGroupParticle, atts, nsRegistry); 379 push(cursor, o, handler); 380 } 381 cursor = (ModelGroupBinding.Cursor)newCursors.get(0); 382 particle = cursor.getCurrentParticle(); 383 break; 384 } 385 } 386 } 387 } 388 389 Object o = null; 390 if(particle != null) 391 { 392 Object parent = stack.isEmpty() ? null : 393 (repeated ? stack.peek(1).o : stack.peek().o); 394 if(particle.getTerm() instanceof WildcardBinding) 395 { 396 400 ElementBinding element = cursor.getElement(); 401 if(element == null) 402 { 403 throw new JBossXBRuntimeException("Failed to resolve element " + 404 startName + " for wildcard." 405 ); 406 } 407 408 if(!repeatedParticle && particle.isRepeatable()) 409 { 410 startRepeatableParticle(startName, particle); 411 } 412 particle = new ParticleBinding(element); 413 } 414 415 ElementBinding element = (ElementBinding)particle.getTerm(); 416 417 String xsiType = atts.getValue("xsi:type"); 419 if(xsiType != null) 420 { 421 if(trace) 422 { 423 log.trace(element.getQName() + " uses xsi:type " + xsiType); 424 } 425 426 String xsiTypePrefix; 427 String xsiTypeLocal; 428 int colon = xsiType.indexOf(':'); 429 if(colon == -1) 430 { 431 xsiTypePrefix = ""; 432 xsiTypeLocal = xsiType; 433 } 434 else 435 { 436 xsiTypePrefix = xsiType.substring(0, colon); 437 xsiTypeLocal = xsiType.substring(colon + 1); 438 } 439 440 String xsiTypeNs = nsRegistry.getNamespaceURI(xsiTypePrefix); 441 QName xsiTypeQName = new QName (xsiTypeNs, xsiTypeLocal); 442 443 TypeBinding xsiTypeBinding = schemaBinding.getType(xsiTypeQName); 444 if(xsiTypeBinding == null) 445 { 446 throw new JBossXBRuntimeException("Type binding not found for type " + 447 xsiTypeQName + 448 " specified with xsi:type for element " + startName 449 ); 450 } 451 452 element = new ElementBinding(schemaBinding, startName, xsiTypeBinding); 453 particle = 454 new ParticleBinding(element, 455 particle.getMinOccurs(), 456 particle.getMaxOccurs(), 457 particle.getMaxOccursUnbounded() 458 ); 459 } 460 461 if(!repeated && particle.isRepeatable()) 462 { 463 startRepeatableParticle(startName, particle); 464 } 465 466 TypeBinding type = element.getType(); 467 if(type == null) 468 { 469 throw new JBossXBRuntimeException("No type for element " + element); 470 } 471 472 handler = type.getHandler(); 473 if(handler == null) 474 { 475 handler = defParticleHandler; 476 } 477 478 List interceptors = element.getInterceptors(); 479 if(!interceptors.isEmpty()) 480 { 481 if (repeated) 482 { 483 pop(); 484 } 485 486 for (int i = 0; i < interceptors.size(); ++i) 487 { 488 ElementInterceptor interceptor = (ElementInterceptor) interceptors.get(i); 489 parent = interceptor.startElement(parent, startName, type); 490 push(startName, particle, parent, handler); 491 interceptor.attributes(parent, startName, type, atts, nsRegistry); 492 } 493 494 if (repeated) 495 { 496 stack.push(item); 498 } 499 } 500 501 String nil = atts.getValue("xsi:nil"); 502 if(nil == null || !("1".equals(nil) || "true".equals(nil))) 503 { 504 o = handler.startParticle(parent, startName, particle, atts, nsRegistry); 505 } 506 else 507 { 508 o = NIL; 509 } 510 } 511 else 512 { 513 ElementBinding parentBinding = null; 514 if(!stack.isEmpty()) 515 { 516 ParticleBinding stackParticle = repeated ? stack.peek(1).particle : stack.peek().particle; 517 if(stackParticle != null) 518 { 519 parentBinding = (ElementBinding)stackParticle.getTerm(); 520 } 521 } 522 523 if(parentBinding != null && parentBinding.getSchema() != null) 524 { 525 schemaBinding = parentBinding.getSchema(); 526 } 527 528 String msg = "Element " + 529 startName + 530 " is not bound " + 531 (parentBinding == null ? "as a global element." : "in type " + parentBinding.getType().getQName()); 532 if(schemaBinding != null && schemaBinding.isStrictSchema()) 533 { 534 throw new JBossXBRuntimeException(msg); 535 } 536 else if(trace) 537 { 538 log.trace(msg); 539 } 540 } 541 542 if(repeated) 543 { 544 item.o = o; 545 } 546 else 547 { 548 push(startName, particle, o, handler); 549 } 550 } 551 552 private ParticleHandler getHandler(ParticleBinding modelGroupParticle) 553 { 554 ParticleHandler handler = ((ModelGroupBinding)modelGroupParticle.getTerm()).getHandler(); 555 return handler == null ? defParticleHandler : handler; 556 } 557 558 private void endRepeatableParent(QName startName) 559 { 560 int parentPos = 1; 561 StackItem parentItem; 562 ParticleBinding parentParticle = null; 563 while(true) 564 { 565 parentItem = stack.peek(parentPos); 566 if(parentItem.cursor == null) 567 { 568 throw new JBossXBRuntimeException( 569 "Failed to start " + startName + 570 ": the element is not repeatable, repeatable parent expected to be a model group but got element " + 571 ((ElementBinding)parentItem.particle.getTerm()).getQName() 572 ); 573 } 574 575 parentParticle = parentItem.particle; 576 if(parentParticle.isRepeatable()) 577 { 578 break; 579 } 580 581 endParticle(parentItem, startName, ++parentPos); 582 } 583 584 if(!parentParticle.isRepeatable()) 585 { 586 StringBuffer msg = new StringBuffer (); 587 588 StackItem item = stack.peek(); 589 ParticleBinding currentParticle = item.particle; 590 msg.append("Failed to start ").append(startName).append(": ") 591 .append(currentParticle.getTerm()) 592 .append(" is not repeatable.") 593 .append(" Its parent ") 594 .append(parentParticle.getTerm()) 595 .append(" expected to be repeatable!") 596 .append("\ncurrent stack: "); 597 598 for(int i = stack.size() - 1; i >= 0; --i) 599 { 600 item = stack.peek(i); 601 ParticleBinding particle = item.particle; 602 TermBinding term = particle.getTerm(); 603 if(term.isModelGroup()) 604 { 605 if(term instanceof SequenceBinding) 606 { 607 msg.append("sequence"); 608 } 609 else if(term instanceof ChoiceBinding) 610 { 611 msg.append("choice"); 612 } 613 else 614 { 615 msg.append("all"); 616 } 617 } 618 else if(term.isWildcard()) 619 { 620 msg.append("wildcard"); 621 } 622 else 623 { 624 msg.append(((ElementBinding)term).getQName()); 625 } 626 msg.append("\\"); 627 } 628 629 throw new JBossXBRuntimeException(msg.toString()); 630 } 631 632 endParticle(parentItem, startName, parentPos + 1); 634 635 parentItem = stack.peek(parentPos + 1); 636 while(parentPos > 0) 637 { 638 StackItem item = stack.peek(parentPos--); 639 ParticleHandler handler = getHandler(item.particle); 640 item.reset(); 641 item.o = handler.startParticle(parentItem.o, startName, item.particle, null, nsRegistry); 642 parentItem = item; 643 } 644 } 645 646 private void startRepeatableParticle(QName startName, ParticleBinding particle) 647 { 648 650 TermBinding term = particle.getTerm(); 651 if(term.isSkip()) 652 { 653 return; 654 } 655 656 StackItem item = stack.peek(); 657 if(item.o != null && 658 !(item.o instanceof GenericValueContainer) && 659 term.getAddMethodMetaData() == null && 660 term.getMapEntryMetaData() == null && 661 term.getPutMethodMetaData() == null) 662 { 663 ValueListHandler handler = ValueListHandler.FACTORY.lazy(item.o); 664 Class cls = item.o.getClass(); 665 item.repeatableParticleValue = new ValueListInitializer().newValueList(handler, cls); 666 } 667 } 668 669 private void endRepeatableParticle(ParticleBinding particle) 670 { 671 673 StackItem item = stack.peek(); 674 ValueList valueList = item.repeatableParticleValue; 675 if(valueList != null) 676 { 677 item.repeatableParticleValue = null; 678 if(valueList.size() == 0) 679 { 680 return; 681 } 682 683 if(particle.getTerm().isWildcard()) 684 { 685 ParticleHandler handler = ((WildcardBinding)particle.getTerm()).getWildcardHandler(); 686 if(handler == null) 687 { 688 handler = defParticleHandler; 689 } 690 691 QName qName = valueList.getValue(0).qName; 693 Collection col = new ArrayList (); 694 for(int i = 0; i < valueList.size(); ++i) 695 { 696 col.add(valueList.getValue(i).value); 697 } 698 StackItem parentItem = stack.peek(1); 699 handler.setParent(parentItem.o, col, qName, particle, parentItem.particle); 700 } 701 else 702 { 703 valueList.getHandler().newInstance(particle, valueList); 704 } 705 } 706 } 707 708 private void endParticle(StackItem item, QName qName, int parentStackPos) 709 { 710 if(item.ended) 711 { 712 throw new JBossXBRuntimeException(item.particle.getTerm() + " has already been ended."); 713 } 714 715 ParticleBinding modelGroupParticle = item.particle; 716 ParticleHandler handler = item.handler; 718 Object o; 719 if(item.o instanceof ValueList && !modelGroupParticle.getTerm().isSkip()) 720 { 721 if(trace) 722 { 723 log.trace("endParticle " + modelGroupParticle.getTerm() + " valueList"); 724 } 725 ValueList valueList = (ValueList)item.o; 726 o = valueList.getHandler().newInstance(modelGroupParticle, valueList); 727 } 728 else 729 { 730 o = handler.endParticle(item.o, qName, modelGroupParticle); 731 } 732 733 item.ended = true; 734 735 item = (StackItem)stack.peek(parentStackPos); 737 if(item.o != null) 738 { 739 ParticleBinding parentParticle = getParentParticle(); if(parentParticle == null) 741 { 742 parentParticle = item.particle; 743 } 744 setParent(handler, 745 item.repeatableParticleValue == null ? item.o : item.repeatableParticleValue, 746 o, qName, modelGroupParticle, parentParticle); 747 } 748 } 749 750 public void startPrefixMapping(String prefix, String uri) 751 { 752 nsRegistry.addPrefixMapping(prefix, uri); 753 } 754 755 public void endPrefixMapping(String prefix) 756 { 757 nsRegistry.removePrefixMapping(prefix); 758 } 759 760 public void processingInstruction(String target, String data) 761 { 762 } 763 764 public Object getRoot() 765 { 766 return root; 767 } 768 769 771 private ParticleBinding getParentParticle() 772 { 773 ListIterator iter = stack.prevIterator(); 774 while(iter.hasPrevious()) 775 { 776 StackItem prev = (StackItem)iter.previous(); 777 ParticleBinding peeked = prev.particle; 778 779 TermBinding term = peeked.getTerm(); 780 if(!term.isSkip()) 781 { 782 return peeked; 783 } 784 } 785 return null; 786 } 787 788 private void endElement() 789 { 790 StackItem item = stack.peek(); 791 Object o = item.o; 792 ParticleBinding particle = item.particle; 793 794 ElementBinding element = (ElementBinding)particle.getTerm(); 795 QName endName = element.getQName(); 796 TypeBinding type = element.getType(); 797 List interceptors = element.getInterceptors(); 798 int interceptorsTotal = interceptors.size(); 799 800 if(o != NIL) 801 { 802 806 TypeBinding charType = type.getSimpleType(); 807 if(charType == null) 808 { 809 charType = type; 810 } 811 812 CharactersHandler charHandler = item.ignoreCharacters ? null : charType.getCharactersHandler(); 813 814 822 String textContent = item.textContent == null ? "" : item.textContent.toString(); 823 if(textContent.length() > 0 || charHandler != null && type.isSimple()) 824 { 825 String dataContent; 826 SchemaBinding schema = element.getSchema(); 827 if(textContent.length() == 0) 828 { 829 dataContent = null; 830 } 831 else 832 { 833 dataContent = textContent.toString(); 834 if(schema != null && schema.isReplacePropertyRefs()) 835 { 836 dataContent = StringPropertyReplacer.replaceProperties(dataContent); 837 } 838 } 839 840 Object unmarshalled; 841 842 if(charHandler == null) 843 { 844 if(!type.isSimple() && 845 schema != null && 846 schema.isStrictSchema() 847 && !element.isSkip()) 849 { 850 throw new JBossXBRuntimeException("Element " + 851 endName + 852 " with type binding " + 853 type.getQName() + 854 " does not include text content binding: " + dataContent 855 ); 856 } 857 unmarshalled = dataContent; 858 } 859 else 860 { 861 ValueMetaData valueMetaData = element.getValueMetaData(); 862 if(valueMetaData == null) 863 { 864 CharactersMetaData charactersMetaData = type.getCharactersMetaData(); 865 if(charactersMetaData != null) 866 { 867 valueMetaData = charactersMetaData.getValue(); 868 } 869 } 870 871 unmarshalled = dataContent == null ? 873 charHandler.unmarshalEmpty(endName, charType, nsRegistry, valueMetaData) : 874 charHandler.unmarshal(endName, charType, nsRegistry, valueMetaData, dataContent); 875 } 876 877 if(unmarshalled != null) 878 { 879 if(o == null) 881 { 882 o = unmarshalled; 883 } 884 else if(charHandler != null) 885 { 886 TermBeforeSetParentCallback beforeSetParent = charType.getBeforeSetParentCallback(); 887 if(beforeSetParent != null) 888 { 889 ctx.parent = o; 890 ctx.particle = particle; 891 ctx.parentParticle = getParentParticle(); 892 unmarshalled = beforeSetParent.beforeSetParent(unmarshalled, ctx); 893 ctx.clear(); 894 } 895 896 if(o instanceof ValueList) 897 { 898 ValueList valueList = (ValueList)o; 899 if(type.isSimple()) 900 { 901 valueList.getInitializer().addTermValue(endName, 902 particle, 903 charHandler, 904 valueList, 905 unmarshalled, 906 null 907 ); 908 } 909 else 910 { 911 valueList.getInitializer().addTextValue(endName, 912 particle, 913 charHandler, 914 valueList, 915 unmarshalled 916 ); 917 } 918 } 919 else 920 { 921 charHandler.setValue(endName, element, o, unmarshalled); 922 } 923 } 924 } 925 926 for(int i = interceptorsTotal - 1; i >= 0; --i) 927 { 928 ElementInterceptor interceptor = (ElementInterceptor)interceptors.get(i); 929 interceptor.characters(((StackItem)stack.peek(interceptorsTotal - i)).o, 930 endName, type, nsRegistry, dataContent 931 ); 932 } 933 } 934 } 935 else 936 { 937 o = null; 938 } 939 940 944 StackItem parentItem = stack.size() == 1 ? null : stack.peek(1); 945 Object parent = parentItem == null ? null : parentItem.o; 946 ParticleHandler handler = stack.peek().handler; 947 948 if(o instanceof ValueList && !particle.getTerm().isSkip()) 949 { 950 if(trace) 951 { 952 log.trace("endParticle " + endName + " valueList"); 953 } 954 ValueList valueList = (ValueList)o; 955 o = valueList.getHandler().newInstance(particle, valueList); 956 } 957 else 958 { 959 o = handler.endParticle(o, endName, particle); 960 } 961 962 for(int i = interceptorsTotal - 1; i >= 0; --i) 963 { 964 ElementInterceptor interceptor = (ElementInterceptor)interceptors.get(i); 965 interceptor.endElement(((StackItem)stack.peek(interceptorsTotal - i)).o, endName, type); 966 } 967 968 972 if(interceptorsTotal == 0) 973 { 974 ParticleBinding parentParticle = getParentParticle(); 975 boolean hasWildcard = false; 976 ParticleHandler wildcardHandler = null; 977 978 if (parentParticle != null && parentParticle.getTerm().isElement()) 979 { 980 WildcardBinding wildcard = ((ElementBinding) parentParticle.getTerm()).getType().getWildcard(); 981 if (wildcard != null) 982 { 983 hasWildcard = true; 984 wildcardHandler = wildcard.getWildcardHandler(); 985 } 986 } 987 988 if(parent != null) 989 { 990 994 if(wildcardHandler != null) 995 { 996 setParent(wildcardHandler, 997 parentItem.repeatableParticleValue == null ? parent : parentItem.repeatableParticleValue, 998 o, endName, particle, parentParticle); 999 } 1000 else 1001 { 1002 setParent(handler, 1003 parentItem.repeatableParticleValue == null ? parent : parentItem.repeatableParticleValue, 1004 o, endName, particle, parentParticle); 1005 } 1006 } 1007 else if(parentParticle != null && hasWildcard && stack.size() > 1) 1008 { 1009 ListIterator iter = stack.prevIterator(); 1011 while(iter.hasPrevious()) 1012 { 1013 StackItem peeked = (StackItem)iter.previous(); 1014 peeked.o = o; 1015 if(peeked.cursor == null) 1016 { 1017 break; 1018 } 1019 } 1020 1021 if(trace) 1022 { 1023 log.trace("Value of " + endName + " " + o + " is promoted as the value of its parent element."); 1024 } 1025 } 1026 } 1027 else 1028 { 1029 StackItem popped = pop(); 1030 for(int i = interceptorsTotal - 1; i >= 0; --i) 1031 { 1032 ElementInterceptor interceptor = (ElementInterceptor)interceptors.get(i); 1033 parent = pop().o; 1034 interceptor.add(parent, o, endName); 1035 o = parent; 1036 } 1037 stack.push(popped); 1039 } 1040 1041 if(stack.size() == 1) 1042 { 1043 root = o; 1044 stack.clear(); 1045 } 1046 } 1047 1048 private void setParent(ParticleHandler handler, 1049 Object parent, 1050 Object o, 1051 QName endName, 1052 ParticleBinding particle, 1053 ParticleBinding parentParticle) 1054 { 1055 TermBeforeSetParentCallback beforeSetParent = particle.getTerm().getBeforeSetParentCallback(); 1056 if(beforeSetParent != null) 1057 { 1058 ctx.parent = parent; 1059 ctx.particle = particle; 1060 ctx.parentParticle = parentParticle; 1061 o = beforeSetParent.beforeSetParent(o, ctx); 1062 ctx.clear(); 1063 } 1064 1065 if(parent instanceof ValueList ) 1066 { 1067 if(parent == o) 1068 { 1069 return; 1070 } 1071 ValueList valueList = (ValueList)parent; 1072 valueList.getInitializer().addTermValue(endName, particle, handler, valueList, o, parentParticle); 1073 } 1074 else 1075 { 1076 handler.setParent(parent, o, endName, particle, parentParticle); 1077 } 1078 } 1079 1080 private void push(QName qName, ParticleBinding particle, Object o, ParticleHandler handler) 1081 { 1082 StackItem item = new StackItem(particle, o, handler); 1083 stack.push(item); 1084 if(trace) 1085 { 1086 Object binding = null; 1087 if(particle != null) 1088 { 1089 binding = particle.getTerm(); 1090 } 1091 log.trace("pushed " + qName + "=" + o + ", binding=" + binding); 1092 } 1093 } 1094 1095 private void push(ModelGroupBinding.Cursor cursor, Object o, ParticleHandler handler) 1096 { 1097 StackItem item = new StackItem(cursor, o, handler); 1098 stack.push(item); 1099 if(trace) 1100 { 1101 log.trace("pushed cursor " + cursor + ", o=" + o); 1102 } 1103 } 1104 1105 private StackItem pop() 1106 { 1107 StackItem item = stack.pop(); 1108 if(trace) 1109 { 1110 if(item.cursor == null) 1111 { 1112 log.trace("poped " + ((ElementBinding)item.particle.getTerm()).getQName() + "=" + item.particle); 1113 } 1114 else 1115 { 1116 log.trace("poped " + item.cursor.getCurrentParticle().getTerm()); 1117 } 1118 } 1119 return item; 1120 } 1121 1122 1124 private static class StackItem 1125 { 1126 final ModelGroupBinding.Cursor cursor; 1127 final ParticleBinding particle; 1128 ParticleHandler handler; 1129 boolean ignoreCharacters; 1130 Object o; 1131 ValueList repeatableParticleValue; 1132 StringBuffer textContent; 1133 boolean ended; 1134 1135 public StackItem(ModelGroupBinding.Cursor cursor, Object o, ParticleHandler handler) 1136 { 1137 if (cursor == null) 1138 throw new IllegalArgumentException ("Null cursor"); 1139 this.cursor = cursor; 1141 this.particle = cursor.getParticle(); 1142 this.o = o; 1143 this.handler = handler; 1144 } 1145 1146 public StackItem(ParticleBinding particle, Object o, ParticleHandler handler) 1147 { 1148 if (particle == null) 1149 throw new IllegalArgumentException ("Null particle"); 1150 this.cursor = null; 1152 this.particle = particle; 1153 this.o = o; 1154 this.handler = handler; 1155 } 1156 1157 void reset() 1158 { 1159 if(!ended) 1160 { 1161 throw new JBossXBRuntimeException( 1162 "Attempt to reset a particle that has already been reset: " + particle.getTerm() 1163 ); 1164 } 1165 1166 ended = false; 1167 o = null; 1168 if(textContent != null) 1169 { 1170 textContent.delete(0, textContent.length()); 1171 } 1172 } 1173 } 1174 1175 static class StackImpl 1176 { 1177 private List list = new ArrayList (); 1178 1179 public void clear() 1180 { 1181 list.clear(); 1182 } 1183 1184 public void push(Object o) 1185 { 1186 list.add(o); 1187 } 1188 1189 public StackItem pop() 1190 { 1191 return (StackItem)list.remove(list.size() - 1); 1192 } 1193 1194 public ListIterator prevIterator() 1195 { 1196 return list.listIterator(list.size() - 1); 1197 } 1198 1199 public StackItem peek() 1200 { 1201 return (StackItem)list.get(list.size() - 1); 1202 } 1203 1204 public StackItem peek(int i) 1205 { 1206 return (StackItem)list.get(list.size() - 1 - i); 1207 } 1208 1209 public boolean isEmpty() 1210 { 1211 return list.isEmpty(); 1212 } 1213 1214 public int size() 1215 { 1216 return list.size(); 1217 } 1218 } 1219 1220 private class UnmarshallingContextImpl implements UnmarshallingContext 1221 { 1222 Object parent; 1223 ParticleBinding particle; 1224 ParticleBinding parentParticle; 1225 1226 public Object getParentValue() 1227 { 1228 return parent; 1229 } 1230 1231 public ParticleBinding getParticle() 1232 { 1233 return particle; 1234 } 1235 1236 public ParticleBinding getParentParticle() 1237 { 1238 return parentParticle; 1239 } 1240 1241 public String resolvePropertyName() 1242 { 1243 TermBinding term = particle.getTerm(); 1244 PropertyMetaData propertyMetaData = term.getPropertyMetaData(); 1245 String prop = propertyMetaData == null ? null : propertyMetaData.getName(); 1246 1247 if(prop != null) 1248 { 1249 return prop; 1250 } 1251 1252 if(term.isElement()) 1253 { 1254 QName name = ((ElementBinding)term).getQName(); 1255 prop = Util.xmlNameToFieldName(name.getLocalPart(), term.getSchema().isIgnoreLowLine()); 1256 } 1257 1258 return prop; 1259 } 1260 1261 public Class resolvePropertyType() 1262 { 1263 if(parent == null) 1264 { 1265 return null; 1266 } 1267 1268 String prop = resolvePropertyName(); 1269 if(prop != null) 1270 { 1271 FieldInfo fieldInfo = FieldInfo.getFieldInfo(parent.getClass(), prop, false); 1272 if (fieldInfo != null) 1273 { 1274 return fieldInfo.getType(); 1275 } 1276 } 1277 return null; 1278 } 1279 1280 1282 void clear() 1283 { 1284 ctx.parent = null; 1285 ctx.particle = null; 1286 ctx.parentParticle = null; 1287 } 1288 } 1289} 1290 | Popular Tags |