1 28 29 package org.jibx.binding.def; 30 31 import org.apache.bcel.Constants; 32 import org.apache.bcel.generic.*; 33 34 import org.jibx.binding.classes.*; 35 import org.jibx.runtime.JiBXException; 36 37 46 47 public class ValueChild implements IComponent 48 { 49 52 static final int DIRECT_IDENT = 0; 53 static final int AUTO_IDENT = 1; 54 static final int DEF_IDENT = 2; 55 static final int REF_IDENT = 3; 56 57 60 static final int ATTRIBUTE_STYLE = 0; 61 static final int ELEMENT_STYLE = 1; 62 static final int TEXT_STYLE = 2; 63 static final int CDATA_STYLE = 3; 64 65 68 69 private static final String BACKFILL_SUFFIX = "_backfill_"; 70 71 private static final String [] BACKFILL_INTERFACES = 72 { 73 "org.jibx.runtime.impl.BackFillReference" 74 }; 75 private static final String BACKFILL_METHODNAME = "backfill"; 76 private static final Type[] BACKFILL_METHODARGS = 77 { 78 Type.OBJECT 79 }; 80 private static final String BOUNDREF_NAME = "m_obj"; 81 private static final String CHECK_ELEMENT_NAME = 82 "org.jibx.runtime.impl.UnmarshallingContext.isAt"; 83 private static final String CHECK_ATTRIBUTE_NAME = 84 "org.jibx.runtime.impl.UnmarshallingContext.hasAttribute"; 85 private static final String CHECK_SIGNATURE = 86 "(Ljava/lang/String;Ljava/lang/String;)Z"; 87 private static final String UNMARSHAL_DEFREF_ATTR_NAME = 88 "org.jibx.runtime.impl.UnmarshallingContext.attributeExistingIDREF"; 89 private static final String UNMARSHAL_DEFREF_ELEM_NAME = 90 "org.jibx.runtime.impl.UnmarshallingContext.parseElementExistingIDREF"; 91 private static final String UNMARSHAL_FWDREF_ATTR_NAME = 92 "org.jibx.runtime.impl.UnmarshallingContext.attributeForwardIDREF"; 93 private static final String UNMARSHAL_FWDREF_ELEM_NAME = 94 "org.jibx.runtime.impl.UnmarshallingContext.parseElementForwardIDREF"; 95 private static final String UNMARSHAL_DEFREF_SIGNATURE = 96 "(Ljava/lang/String;Ljava/lang/String;I)Ljava/lang/Object;"; 97 private static final String REGISTER_BACKFILL_NAME = 98 "org.jibx.runtime.impl.UnmarshallingContext.registerBackFill"; 99 private static final String REGISTER_BACKFILL_SIGNATURE = 100 "(ILorg/jibx/runtime/impl/BackFillReference;)V"; 101 private static final String DEFINE_ID_NAME = 102 "org.jibx.runtime.impl.UnmarshallingContext.defineID"; 103 private static final String DEFINE_ID_SIGNATURE = 104 "(Ljava/lang/String;ILjava/lang/Object;)V"; 105 private static final String UNMARSHAL_TEXT_NAME = 106 "org.jibx.runtime.impl.UnmarshallingContext.parseContentText"; 107 private static final String UNMARSHAL_TEXT_SIGNATURE = 108 "()Ljava/lang/String;"; 109 private static final String MARSHAL_TEXT_NAME = 110 "org.jibx.runtime.impl.MarshallingContext.writeContent"; 111 private static final String MARSHAL_CDATA_NAME = 112 "org.jibx.runtime.impl.MarshallingContext.writeCData"; 113 private static final String MARSHAL_TEXT_SIGNATURE = 114 "(Ljava/lang/String;)Lorg/jibx/runtime/impl/MarshallingContext;"; 115 private static final String UNMARSHALLING_THROWEXCEPTION_METHOD = 116 "org.jibx.runtime.impl.UnmarshallingContext.throwException"; 117 private static final String UNMARSHALLING_THROWEXCEPTION_SIGNATURE = 118 "(Ljava/lang/String;)V"; 119 protected static final String MARSHAL_ATTRIBUTE = 120 "org.jibx.runtime.impl.MarshallingContext.attribute"; 121 protected static final String MARSHAL_ELEMENT = 122 "org.jibx.runtime.impl.MarshallingContext.element"; 123 protected static final String MARSHAL_SIGNATURE = 124 "(ILjava/lang/String;Ljava/lang/String;)" + 125 "Lorg/jibx/runtime/impl/MarshallingContext;"; 126 127 130 131 private final IContainer m_container; 132 133 134 private final IContextObj m_objContext; 135 136 137 private final int m_valueStyle; 138 139 140 private final String m_constantValue; 141 142 143 private final int m_identType; 144 145 146 private final NameDefinition m_name; 147 148 149 private final String m_type; 150 151 152 private final PropertyDefinition m_property; 153 154 155 private final StringConversion m_conversion; 156 157 158 private IMapping m_idRefMap; 159 160 173 174 public ValueChild(IContainer contain, IContextObj objc, NameDefinition name, 175 PropertyDefinition prop, StringConversion conv, int style, int ident, 176 String constant) { 177 m_container = contain; 178 m_objContext = objc; 179 m_name = name; 180 m_property = prop; 181 m_type = prop.getTypeName(); 182 m_conversion = conv; 183 m_valueStyle = style; 184 m_identType = ident; 185 m_constantValue = constant; 186 } 187 188 196 197 private ClassFile createBackfillClass() throws JiBXException { 198 199 BoundClass bc = m_objContext.getBoundClass(); 201 BindingDefinition def = m_container.getBindingRoot(); 202 String name = bc.getClassFile().deriveClassName(def.getPrefix(), 203 BACKFILL_SUFFIX + m_property.getName()); 204 ClassFile base = ClassCache.getClassFile("java.lang.Object"); 205 ClassFile cf = new ClassFile(name, bc.getClassFile().getRoot(), 206 base, Constants.ACC_PUBLIC, BACKFILL_INTERFACES); 207 208 String type = bc.getClassFile().getName(); 210 ClassItem ref = cf.addPrivateField(type, BOUNDREF_NAME); 211 212 Type[] args = new Type[] { ClassItem.typeFromName(type) }; 214 MethodBuilder mb = new ExceptionMethodBuilder("<init>", 215 Type.VOID, args, cf, (short)0); 216 217 mb.appendLoadLocal(0); 219 mb.appendCallInit("java.lang.Object", "()V"); 220 221 mb.appendLoadLocal(0); 223 mb.appendLoadLocal(1); 224 mb.appendPutField(ref); 225 mb.appendReturn(); 226 mb.codeComplete(false); 227 mb.addMethod(); 228 229 mb = new ExceptionMethodBuilder(BACKFILL_METHODNAME, Type.VOID, 231 BACKFILL_METHODARGS, cf, Constants.ACC_PUBLIC); 232 mb.appendLoadLocal(0); 233 mb.appendGetField(ref); 234 mb.appendLoadLocal(1); 235 mb.appendCreateCast(m_property.getSetValueType()); 236 m_property.genStore(mb); 237 mb.appendReturn(); 238 mb.codeComplete(false); 239 mb.addMethod(); 240 241 return MungedClass.getUniqueSupportClass(cf); 243 } 244 245 253 254 private void genParseIdRef(ContextMethodBuilder mb) throws JiBXException { 255 256 BranchWrapper ifmiss = null; 259 if (m_property.isOptional()) { 260 261 String name = m_valueStyle == ValueChild.ATTRIBUTE_STYLE ? 264 CHECK_ATTRIBUTE_NAME : CHECK_ELEMENT_NAME; 265 mb.appendCallVirtual(name, CHECK_SIGNATURE); 266 BranchWrapper ifpres = mb.appendIFNE(this); 267 268 mb.appendACONST_NULL(); 270 ifmiss = mb.appendUnconditionalBranch(this); 271 272 mb.targetNext(ifpres); 275 mb.loadContext(); 276 m_name.genPushUriPair(mb); 277 278 } 279 280 int index = m_container.getBindingRoot(). 282 getIdClassIndex(m_property.getTypeName()); 283 284 if (m_container.getBindingRoot().isForwards()) { 286 287 mb.appendLoadConstant(index); 289 String name = m_valueStyle == ValueChild.ATTRIBUTE_STYLE ? 290 UNMARSHAL_FWDREF_ATTR_NAME : UNMARSHAL_FWDREF_ELEM_NAME; 291 mb.appendCallVirtual(name, UNMARSHAL_DEFREF_SIGNATURE); 292 293 mb.appendDUP(); 295 BranchWrapper ifdef = mb.appendIFNONNULL(this); 296 297 ClassFile backclas = createBackfillClass(); 301 mb.loadContext(); 302 mb.appendLoadConstant(index); 303 mb.appendCreateNew(backclas.getName()); 304 305 mb.appendDUP(); 309 mb.loadObject(); 310 mb.appendCallInit(backclas.getName(), "(" + 311 m_objContext.getBoundClass().getClassFile().getSignature() + 312 ")V"); 313 mb.appendCallVirtual(REGISTER_BACKFILL_NAME, 314 REGISTER_BACKFILL_SIGNATURE); 315 316 mb.targetNext(ifdef); 318 319 } else { 320 321 mb.appendLoadConstant(index); 323 String name = m_valueStyle == ValueChild.ATTRIBUTE_STYLE ? 324 UNMARSHAL_DEFREF_ATTR_NAME : UNMARSHAL_DEFREF_ELEM_NAME; 325 mb.appendCallVirtual(name, UNMARSHAL_DEFREF_SIGNATURE); 326 } 327 328 mb.appendCreateCast(m_property.getSetValueType()); 330 331 if (ifmiss != null) { 333 mb.targetNext(ifmiss); 334 } 335 m_property.genStore(mb); 336 } 337 338 346 347 public void genIfPresentTest(UnmarshalBuilder mb) throws JiBXException { 348 349 if (m_name == null) { 351 throw new JiBXException("Method call on invalid value"); 352 } 353 354 mb.loadContext(); 357 m_name.genPushUriPair(mb); 358 String name = (m_valueStyle == ValueChild.ATTRIBUTE_STYLE) ? 359 CHECK_ATTRIBUTE_NAME : CHECK_ELEMENT_NAME; 360 mb.appendCallVirtual(name, CHECK_SIGNATURE); 361 } 362 363 372 373 private void genUnmarshal(ContextMethodBuilder mb) throws JiBXException { 374 375 if (m_constantValue == null && !m_property.isImplicit()) { 379 mb.loadObject(); 380 } 381 mb.loadContext(); 382 if (m_name != null) { 383 m_name.genPushUriPair(mb); 384 } 385 386 boolean isatt = (m_valueStyle == ValueChild.ATTRIBUTE_STYLE); 388 if (m_identType == DEF_IDENT || m_identType == AUTO_IDENT) { 389 390 BindingDefinition.s_stringConversion.genParseRequired(isatt, mb); 393 if (m_identType != AUTO_IDENT) { 394 mb.appendDUP(); 395 } 396 397 mb.loadContext(); 401 mb.appendSWAP(); 402 int index = m_container.getBindingRoot(). 403 getIdClassIndex(m_property.getTypeName()); 404 mb.appendLoadConstant(index); 405 mb.loadObject(); 406 mb.appendCallVirtual(DEFINE_ID_NAME, DEFINE_ID_SIGNATURE); 407 408 if (m_identType != AUTO_IDENT) { 411 m_conversion.genFromText(mb); 412 m_property.genStore(mb); 413 } 414 415 } else if (m_identType == REF_IDENT) { 416 417 genParseIdRef(mb); 419 420 } else if (m_constantValue == null) { 421 422 if (m_valueStyle == ValueChild.TEXT_STYLE || 424 m_valueStyle == ValueChild.CDATA_STYLE) { 425 426 mb.appendCallVirtual(UNMARSHAL_TEXT_NAME, 428 UNMARSHAL_TEXT_SIGNATURE); 429 m_conversion.genFromText(mb); 430 431 } else if (m_property.isOptional() && 432 (isatt || m_container.isContentOrdered())) { 433 434 m_conversion.genParseOptional(isatt, mb); 436 437 } else { 438 439 m_conversion.genParseRequired(isatt, mb); 441 442 } 443 444 if (!m_conversion.isPrimitive() && m_property != null) { 446 String stype = m_conversion.getTypeName(); 447 String dtype = m_property.getSetValueType(); 448 mb.appendCreateCast(stype, dtype); 449 } 450 451 m_property.genStore(mb); 453 454 } else { 455 456 BranchWrapper ifmiss = null; 458 if (m_valueStyle == ValueChild.TEXT_STYLE || 459 m_valueStyle == ValueChild.CDATA_STYLE) { 460 461 mb.appendCallVirtual(UNMARSHAL_TEXT_NAME, 463 UNMARSHAL_TEXT_SIGNATURE); 464 465 } else { 466 467 m_conversion.genParseOptional(isatt, mb); 469 mb.appendDUP(); 470 ifmiss = mb.appendIFNULL(this); 471 } 472 473 mb.appendDUP(); 475 mb.appendLoadConstant(m_constantValue); 476 mb.appendCallVirtual("java.lang.String.equals", 477 "(Ljava/lang/Object;)Z"); 478 BranchWrapper ifmatch = mb.appendIFNE(this); 479 480 mb.appendCreateNew("java.lang.StringBuffer"); 482 mb.appendDUP(); 483 mb.appendLoadConstant("Expected constant value \"" + 484 m_constantValue + "\", found \""); 485 mb.appendCallInit("java.lang.StringBuffer", 486 "(Ljava/lang/String;)V"); 487 mb.appendSWAP(); 488 mb.appendCallVirtual("java.lang.StringBuffer.append", 489 "(Ljava/lang/String;)Ljava/lang/StringBuffer;"); 490 mb.appendLoadConstant("\""); 491 mb.appendCallVirtual("java.lang.StringBuffer.append", 492 "(Ljava/lang/String;)Ljava/lang/StringBuffer;"); 493 mb.appendCallVirtual("java.lang.StringBuffer.toString", 494 "()Ljava/lang/String;"); 495 mb.loadContext(); 496 mb.appendSWAP(); 497 mb.appendCallVirtual(UNMARSHALLING_THROWEXCEPTION_METHOD, 498 UNMARSHALLING_THROWEXCEPTION_SIGNATURE); 499 500 mb.targetNext(ifmatch); 502 mb.targetNext(ifmiss); 503 mb.appendPOP(); 504 } 505 } 506 507 516 517 private void genMarshal(ContextMethodBuilder mb) throws JiBXException { 518 if (m_constantValue == null) { 519 520 BranchWrapper ifmiss = null; 525 if (m_property.hasTest()) { 526 mb.loadObject(); 527 ifmiss = m_property.genTest(mb); 528 } 529 String type = m_property.getTypeName(); 530 if (m_name != null) { 531 532 Type tobj = ClassItem.typeFromName(type); 535 if (m_property.isImplicit()) { 536 mb.defineSlot(this, tobj); 537 } 538 m_name.genPushIndexPair(mb); 539 if (m_property.isImplicit()) { 540 mb.appendLoadLocal(mb.getSlot(this)); 541 mb.freeSlot(this); 542 } 543 } 544 if (!m_property.isImplicit()) { 545 mb.loadObject(); 546 m_property.genLoad(mb); 547 } 548 549 StringConversion convert = m_conversion; 551 if (m_identType == REF_IDENT) { 552 m_idRefMap.getImplComponent().genLoadId(mb); 553 convert = BindingDefinition.s_stringConversion; 554 type = "java.lang.String"; 555 } 556 557 boolean isatt = m_valueStyle == ValueChild.ATTRIBUTE_STYLE; 559 if (m_valueStyle == ValueChild.TEXT_STYLE || 560 m_valueStyle == ValueChild.CDATA_STYLE) { 561 convert.genToText(type, mb); 562 String name = (m_valueStyle == ValueChild.TEXT_STYLE) ? 563 MARSHAL_TEXT_NAME : MARSHAL_CDATA_NAME; 564 mb.appendCallVirtual(name, MARSHAL_TEXT_SIGNATURE); 565 } else if (m_property.isOptional()) { 566 convert.genWriteOptional(isatt, type, mb); 567 } else { 568 convert.genWriteRequired(isatt, type, mb); 569 } 570 571 if (ifmiss != null) { 573 mb.targetNext(ifmiss); 574 } 575 576 } else { 577 578 if (m_name != null) { 580 m_name.genPushIndexPair(mb); 581 } 582 mb.appendLoadConstant(m_constantValue); 583 switch (m_valueStyle) { 584 case ATTRIBUTE_STYLE: 585 mb.appendCallVirtual(MARSHAL_ATTRIBUTE, MARSHAL_SIGNATURE); 586 break; 587 case ELEMENT_STYLE: 588 mb.appendCallVirtual(MARSHAL_ELEMENT, MARSHAL_SIGNATURE); 589 break; 590 case TEXT_STYLE: 591 mb.appendCallVirtual(MARSHAL_TEXT_NAME, 592 MARSHAL_TEXT_SIGNATURE); 593 break; 594 case CDATA_STYLE: 595 mb.appendCallVirtual(MARSHAL_CDATA_NAME, 596 MARSHAL_TEXT_SIGNATURE); 597 break; 598 } 599 } 600 } 601 602 608 609 public String getPropertyName() { 610 if (m_property == null) { 611 return null; 612 } else { 613 return m_property.getName(); 614 } 615 } 616 617 620 public boolean isOptional() { 621 return m_property.isOptional(); 622 } 623 624 public boolean hasAttribute() { 625 return m_valueStyle == ATTRIBUTE_STYLE; 626 } 627 628 public void genAttrPresentTest(ContextMethodBuilder mb) 629 throws JiBXException { 630 631 if (m_valueStyle != ATTRIBUTE_STYLE || m_name == null) { 633 throw new JiBXException("Method call on invalid structure"); 634 } 635 636 mb.loadContext(); 639 m_name.genPushUriPair(mb); 640 mb.appendCallVirtual(CHECK_ATTRIBUTE_NAME, CHECK_SIGNATURE); 641 } 642 643 public void genAttributeUnmarshal(ContextMethodBuilder mb) 644 throws JiBXException { 645 if (m_valueStyle == ATTRIBUTE_STYLE) { 646 genUnmarshal(mb); 647 } 648 } 649 650 public void genAttributeMarshal(ContextMethodBuilder mb) 651 throws JiBXException { 652 if (m_valueStyle == ATTRIBUTE_STYLE) { 653 genMarshal(mb); 654 } 655 } 656 657 public boolean hasContent() { 658 return m_valueStyle != ATTRIBUTE_STYLE; 659 } 660 661 662 public void genContentPresentTest(ContextMethodBuilder mb) 663 throws JiBXException { 664 665 if (m_valueStyle != ELEMENT_STYLE) { 667 throw new JiBXException("Method call on invalid structure"); 668 } 669 670 mb.loadContext(); 673 m_name.genPushUriPair(mb); 674 mb.appendCallVirtual(CHECK_ELEMENT_NAME, CHECK_SIGNATURE); 675 } 676 677 public void genContentUnmarshal(ContextMethodBuilder mb) 678 throws JiBXException { 679 if (m_valueStyle != ATTRIBUTE_STYLE) { 680 genUnmarshal(mb); 681 } 682 } 683 684 public void genContentMarshal(ContextMethodBuilder mb) 685 throws JiBXException { 686 if (m_valueStyle != ATTRIBUTE_STYLE) { 687 genMarshal(mb); 688 } 689 } 690 691 public void genNewInstance(ContextMethodBuilder mb) { 692 throw new IllegalStateException 693 ("Internal error - no instance creation"); 694 } 695 696 public String getType() { 697 return m_type; 698 } 699 700 public boolean hasId() { 701 return m_identType == DEF_IDENT; 702 } 703 704 public void genLoadId(ContextMethodBuilder mub) throws JiBXException { 705 m_property.genLoad(mub); 706 } 707 708 public boolean checkContentSequence(boolean text) throws JiBXException { 709 if (m_valueStyle == ELEMENT_STYLE) { 710 return true; 711 } else if (m_valueStyle == ATTRIBUTE_STYLE) { 712 return text; 713 } else if (text) { 714 return false; 715 } else { 716 throw new JiBXException("Text value must follow required element"); 717 } 718 } 719 720 public void setLinkages() throws JiBXException { 721 if (m_identType == REF_IDENT) { 722 String type; 723 if (m_property == null) { 724 type = m_objContext.getBoundClass().getClassFile().getName(); 725 } else { 726 type = m_property.getTypeName(); 727 } 728 m_idRefMap = m_container.getDefinitionContext(). 729 getClassMapping(type); 730 if (m_idRefMap == null) { 731 throw new JiBXException("No mapping defined for " + 732 type + " used as IDREF target"); 733 } else if (!m_idRefMap.getImplComponent().hasId()) { 734 throw new JiBXException("No ID value defined for " + 735 type + " used as IDREF target"); 736 } 737 } 738 } 739 740 public void print(int depth) { 742 BindingDefinition.indent(depth); 743 if (m_valueStyle == ELEMENT_STYLE) { 744 System.out.print("element"); 745 } else if (m_valueStyle == ATTRIBUTE_STYLE) { 746 System.out.print("attribute"); 747 } else if (m_valueStyle == TEXT_STYLE) { 748 System.out.print("text"); 749 } else if (m_valueStyle == CDATA_STYLE) { 750 System.out.print("cdata"); 751 } 752 if (m_name != null) { 753 System.out.print(" " + m_name.toString()); 754 } 755 if (m_property != null) { 756 System.out.print(" from " + m_property.toString()); 757 } 758 System.out.println(); 759 } 760 } 761 | Popular Tags |