1 28 29 package org.jibx.binding.def; 30 31 import java.util.ArrayList ; 32 33 import org.apache.bcel.Constants; 34 import org.apache.bcel.generic.*; 35 36 import org.jibx.binding.classes.*; 37 import org.jibx.runtime.JiBXException; 38 39 47 48 public class MappingDefinition extends MappingBase 49 { 50 53 private static final String ADAPTERCLASS_SUFFIX = "_access"; 55 private static final String MARSHAL_METHODNAME = "marshal"; 56 private static final String BASEMARSHAL_METHODNAME = "baseMarshal"; 57 private static final String UNMARSHAL_METHODNAME = "unmarshal"; 58 private static final String ISPRESENT_METHODNAME = "isPresent"; 59 private static final String UNMARSHALCONTEXT_CLASS = 60 "org.jibx.runtime.impl.UnmarshallingContext"; 61 private static final String MARSHALCONTEXT_CLASS = 62 "org.jibx.runtime.impl.MarshallingContext"; 63 private static final String UNMARSHAL_ISATMETHOD = 64 "org.jibx.runtime.IUnmarshallingContext.isAt"; 65 private static final String UNMARSHAL_ISATSIGNATURE = 66 "(Ljava/lang/String;Ljava/lang/String;)Z"; 67 private static final String CHECKEXTENDS_METHOD = 68 "org.jibx.runtime.IMarshaller.isExtension"; 69 private static final String GETINDEX_METHOD = 70 "org.jibx.runtime.IMarshallable.JiBX_getIndex"; 71 private static final String UNMARSHALLERPRESENT_METHOD = 72 "org.jibx.runtime.IUnmarshaller.isPresent"; 73 private static final String UNMARSHALLERPRESENT_SIGNATURE = 74 "(Lorg/jibx/runtime/IUnmarshallingContext;)Z"; 75 private static final String UNMARSHALCONTEXT_INTERFACE = 76 "org.jibx.runtime.IUnmarshallingContext"; 77 private static final String MARSHALCONTEXT_INTERFACE = 78 "org.jibx.runtime.IMarshallingContext"; 79 private static final String CURRENTELEMENT_METHOD = 80 "org.jibx.runtime.impl.UnmarshallingContext.currentNameString"; 81 private static final String CURRENTELEMENT_SIGNATURE = 82 "()Ljava/lang/String;"; 83 private static final String ADDUNMARSHALLER_METHOD = 84 "org.jibx.runtime.impl.UnmarshallingContext.addUnmarshalling"; 85 private static final String ADDUNMARSHALLER_SIGNATURE = 86 "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"; 87 private static final String REMOVEUNMARSHALLER_METHOD = 88 "org.jibx.runtime.impl.UnmarshallingContext.removeUnmarshalling"; 89 private static final String REMOVEUNMARSHALLER_SIGNATURE = "(I)V"; 90 private static final String ADDMARSHALLER_METHOD = 91 "org.jibx.runtime.impl.MarshallingContext.addMarshalling"; 92 private static final String ADDMARSHALLER_SIGNATURE = 93 "(ILjava/lang/String;)V"; 94 private static final String REMOVEMARSHALLER_METHOD = 95 "org.jibx.runtime.impl.MarshallingContext.removeMarshalling"; 96 private static final String REMOVEMARSHALLER_SIGNATURE = "(I)V"; 97 98 private static final Type[] ISPRESENT_METHOD_ARGS = 100 { 101 ClassItem.typeFromName("org.jibx.runtime.IUnmarshallingContext") 102 }; 103 private static final Type[] UNMARSHAL_METHOD_ARGS = 104 { 105 Type.OBJECT, 106 ClassItem.typeFromName("org.jibx.runtime.IUnmarshallingContext") 107 }; 108 109 private static final Type[] MARSHAL_METHOD_ARGS = 111 { 112 Type.OBJECT, 113 ClassItem.typeFromName("org.jibx.runtime.IMarshallingContext") 114 }; 115 116 119 static final String [] UNMARSHALLER_INTERFACES = 121 { 122 UNMARSHALLER_INTERFACE 123 }; 124 125 static final String [] MARSHALLER_INTERFACES = 127 { 128 MARSHALLER_INTERFACE 129 }; 130 131 static final String [] BOTH_INTERFACES = 133 { 134 UNMARSHALLER_INTERFACE, MARSHALLER_INTERFACE 135 }; 136 137 140 141 private final IContainer m_container; 142 143 144 private final DefinitionContext m_defContext; 145 146 147 private final BoundClass m_class; 148 149 151 private final NameDefinition m_name; 152 153 154 private final boolean m_isAbstract; 155 156 157 private final String m_baseType; 158 159 161 private IMapping m_baseMapping; 162 163 164 private ClassFile m_marshaller; 165 166 167 private ClassFile m_unmarshaller; 168 169 170 private ArrayList m_extensions; 171 172 185 public MappingDefinition(IContainer contain, DefinitionContext defc, 186 String type, NameDefinition name, boolean abs, String base, 187 IComponent bind) throws JiBXException { 188 super(contain, type); 189 if (name == null) { 190 setWrappedComponent(bind); 191 } else { 192 setWrappedComponent(new ElementWrapper(defc, name, bind)); 193 } 194 m_container = contain; 195 m_defContext = defc; 196 m_class = BoundClass.getInstance(type, null); 197 m_name = name; 198 m_isAbstract = abs; 199 if (abs) { 200 m_extensions = new ArrayList (); 201 } 202 m_baseType = base; 203 } 204 205 211 boolean hasNamespace() { 212 return m_defContext.hasNamespace(); 213 } 214 215 223 void genLoadNamespaces(MethodBuilder mb) throws JiBXException { 224 m_defContext.genLoadNamespaces(mb); 225 } 226 227 233 public BoundClass getBoundClass() { 234 return m_class; 235 } 236 237 244 public void linkMappings() throws JiBXException { 245 if (m_isAbstract && m_component instanceof ObjectBinding) { 246 ((ObjectBinding)m_component).setAbstract(true); 247 } 248 if (m_baseType != null) { 249 m_baseMapping = m_defContext.getClassMapping(m_baseType); 250 if (m_baseMapping == null) { 251 throw new JiBXException("Mapping for base class " + m_baseType + 252 " not defined"); 253 } 254 m_baseMapping.addExtension(this); 255 } 256 m_defContext.linkMappings(); 257 } 258 259 262 public String getBoundType() { 263 return m_class.getClassName(); 264 } 265 266 public IComponent getImplComponent() { 267 return m_component; 268 } 269 270 public ClassFile getMarshaller() { 271 return m_marshaller; 272 } 273 274 public ClassFile getUnmarshaller() { 275 return m_unmarshaller; 276 } 277 278 public NameDefinition getName() { 279 return m_name; 280 } 281 282 public void addNamespace(NamespaceDefinition ns) throws JiBXException { 283 m_defContext.addNamespace(ns); 284 } 285 286 public boolean isAbstract() { 287 return m_isAbstract; 288 } 289 290 public void addExtension(MappingDefinition mdef) { 291 if (!m_extensions.contains(mdef)) { 292 m_extensions.add(mdef); 293 } 294 } 295 296 public IComponent buildRef(IContainer parent, IContextObj objc, String type, 297 PropertyDefinition prop) throws JiBXException { 298 if (m_isAbstract && prop.isThis()) { 299 300 if (m_component instanceof ObjectBinding) { 302 ((ObjectBinding)m_component).setAbstract(true); 303 } 304 return new BaseMappingWrapper(m_component); 305 306 } else if (m_isAbstract && m_extensions.size() == 0) { 307 308 if (m_component instanceof ObjectBinding) { 310 ((ObjectBinding)m_component).setAbstract(true); 311 } 312 ObjectBinding bind = new ObjectBinding(parent, objc, type, null, 313 null, null, null); 314 NestedStructure nest = new NestedStructure(parent, bind, true, 315 false, true); 316 nest.addComponent(new BaseMappingWrapper(m_component)); 317 bind.setWrappedComponent(nest); 318 return new ComponentProperty(prop, bind, false); 319 320 } else { 321 322 DirectObject dobj = new DirectObject(m_container, null, 324 m_class.getClassFile(), m_isAbstract, m_marshaller, 325 m_unmarshaller, getIndex(), null); 326 return new DirectProperty(prop, dobj); 327 328 } 329 } 330 331 public void generateCode() throws JiBXException { 332 333 335 m_defContext.generateCode(false); 337 if (m_isAbstract && m_extensions.size() == 0) { 338 return; 339 } 340 341 ClassFile target = m_class.getMungedFile(); 343 BindingDefinition def = m_container.getBindingRoot(); 344 String name = target.deriveClassName(def.getPrefix(), 345 ADAPTERCLASS_SUFFIX); 346 ClassFile base = ClassCache.getClassFile("java.lang.Object"); 347 String [] intfs = def.isInput() ? 348 (def.isOutput() ? BOTH_INTERFACES : UNMARSHALLER_INTERFACES) : 349 MARSHALLER_INTERFACES; 350 ClassFile cf = new ClassFile(name, target.getRoot(), base, 351 Constants.ACC_PUBLIC, intfs); 352 cf.addDefaultConstructor(); 353 354 boolean hasattr = !m_isAbstract && m_component.hasAttribute(); 356 boolean hascont = m_component.hasContent(); 357 boolean genfull = !m_isAbstract || m_extensions.size() > 0; 358 if (def.isInput()) { 359 360 ContextMethodBuilder mb = new ContextMethodBuilder 362 (ISPRESENT_METHODNAME, Type.BOOLEAN, ISPRESENT_METHOD_ARGS, 363 cf, Constants.ACC_PUBLIC|Constants.ACC_FINAL, -1, null, 364 1, UNMARSHALCONTEXT_INTERFACE); 365 366 if (m_isAbstract) { 368 369 mb.addException(MethodBuilder.FRAMEWORK_EXCEPTION_CLASS); 372 BranchWrapper[] iffounds = 373 new BranchWrapper[m_extensions.size()]; 374 if (iffounds.length > 0) { 375 for (int i = 0; i < iffounds.length; i++) { 376 IMapping map = (IMapping)m_extensions.get(i); 377 mb.loadContext(); 378 mb.appendLoadConstant(map.getIndex()); 379 mb.appendCallInterface(GETUNMARSHALLER_METHOD, 380 GETUNMARSHALLER_SIGNATURE); 381 mb.loadContext(); 382 mb.appendCallInterface(UNMARSHALLERPRESENT_METHOD, 383 UNMARSHALLERPRESENT_SIGNATURE); 384 iffounds[i] = mb.appendIFNE(this); 385 } 386 mb.appendICONST_0(); 387 mb.appendReturn("int"); 388 mb.initStackState(iffounds[0]); 389 BranchTarget found = mb.appendTargetLoadConstant(1); 390 for (int i = 0; i < iffounds.length; i++) { 391 iffounds[i].setTarget(found, mb); 392 } 393 } else { 394 mb.appendLoadConstant(1); 395 } 396 397 } else if (m_name == null) { 398 399 mb.appendICONST_1(); 402 403 } else { 404 405 mb.addException(MethodBuilder.FRAMEWORK_EXCEPTION_CLASS); 408 mb.loadContext(); 409 m_name.genPushUriPair(mb); 410 mb.appendCallInterface(UNMARSHAL_ISATMETHOD, 411 UNMARSHAL_ISATSIGNATURE); 412 413 } 414 mb.appendReturn("int"); 415 mb.codeComplete(false); 416 mb.addMethod(); 417 418 String type = m_class.getClassName(); 423 mb = new ContextMethodBuilder(UNMARSHAL_METHODNAME, 424 Type.OBJECT, UNMARSHAL_METHOD_ARGS, cf, 425 Constants.ACC_PUBLIC|Constants.ACC_FINAL, 1, type, 426 2, UNMARSHALCONTEXT_INTERFACE); 427 mb.addException(MethodBuilder.FRAMEWORK_EXCEPTION_CLASS); 428 429 mb.loadObject(); 435 BranchWrapper ifnnull = mb.appendIFNONNULL(this); 436 437 if (m_isAbstract) { 439 440 BranchWrapper[] iffounds = 444 new BranchWrapper[m_extensions.size()]; 445 for (int i = 0; i < iffounds.length; i++) { 446 IMapping map = (IMapping)m_extensions.get(i); 447 mb.loadContext(); 448 mb.appendLoadConstant(map.getIndex()); 449 mb.appendCallInterface(GETUNMARSHALLER_METHOD, 450 GETUNMARSHALLER_SIGNATURE); 451 mb.appendDUP(); 452 mb.loadContext(); 453 mb.appendCallInterface(UNMARSHALLERPRESENT_METHOD, 454 UNMARSHALLERPRESENT_SIGNATURE); 455 iffounds[i] = mb.appendIFNE(this); 456 mb.appendPOP(); 457 } 458 459 mb.appendCreateNew("java.lang.StringBuffer"); 462 mb.appendDUP(); 463 mb.appendLoadConstant("Element "); 464 mb.appendCallInit("java.lang.StringBuffer", 465 "(Ljava/lang/String;)V"); 466 mb.appendDUP(); 467 mb.loadContext(UNMARSHALCONTEXT_CLASS); 468 mb.appendCallVirtual(CURRENTELEMENT_METHOD, 469 CURRENTELEMENT_SIGNATURE); 470 mb.appendCallVirtual("java.lang.StringBuffer.append", 471 "(Ljava/lang/String;)Ljava/lang/StringBuffer;"); 472 mb.appendDUP(); 473 mb.appendLoadConstant(" has no mapping that extends " + 474 m_class.getClassName()); 475 mb.appendCallVirtual("java.lang.StringBuffer.append", 476 "(Ljava/lang/String;)Ljava/lang/StringBuffer;"); 477 mb.appendCallVirtual("java.lang.StringBuffer.toString", 478 "()Ljava/lang/String;"); 479 mb.appendCreateNew(MethodBuilder.FRAMEWORK_EXCEPTION_CLASS); 480 mb.appendDUP_X1(); 481 mb.appendSWAP(); 482 mb.appendCallInit(MethodBuilder.FRAMEWORK_EXCEPTION_CLASS, 483 MethodBuilder.EXCEPTION_CONSTRUCTOR_SIGNATURE1); 484 mb.appendThrow(); 485 if (iffounds.length > 0) { 486 487 mb.initStackState(iffounds[0]); 491 BranchTarget found = mb.appendTargetACONST_NULL(); 492 for (int i = 0; i < iffounds.length; i++) { 493 iffounds[i].setTarget(found, mb); 494 } 495 mb.loadContext(); 496 mb.appendCallInterface(UNMARSHALLERUNMARSHAL_METHOD, 497 UNMARSHALLERUNMARSHAL_SIGNATURE); 498 mb.appendReturn("java.lang.Object"); 499 } 500 501 } else { 502 503 genNewInstance(mb); 505 mb.storeObject(); 506 507 } 508 509 ArrayList maps = m_defContext.getMappings(); 511 if (maps != null && maps.size() > 0) { 512 for (int i = 0; i < maps.size(); i++) { 513 mb.loadContext(UNMARSHALCONTEXT_CLASS); 514 IMapping map = (IMapping)maps.get(i); 515 mb.appendLoadConstant(map.getIndex()); 516 NameDefinition mname = map.getName(); 517 if (mname == null) { 518 mb.appendACONST_NULL(); 519 mb.appendACONST_NULL(); 520 } else { 521 map.getName().genPushUriPair(mb); 522 } 523 mb.appendLoadConstant(map.getUnmarshaller().getName()); 524 mb.appendCallVirtual(ADDUNMARSHALLER_METHOD, 525 ADDUNMARSHALLER_SIGNATURE); 526 } 527 } 528 529 mb.targetNext(ifnnull); 531 mb.loadObject(); 532 mb.appendCreateCast(type); 533 534 if (hasattr) { 536 mb.appendDUP(); 537 m_component.genAttributeUnmarshal(mb); 538 } 539 if (hascont) { 540 mb.appendDUP(); 541 m_component.genContentUnmarshal(mb); 542 } 543 544 if (maps != null && maps.size() > 0) { 546 for (int i = 0; i < maps.size(); i++) { 547 mb.loadContext(UNMARSHALCONTEXT_CLASS); 548 IMapping map = (IMapping)maps.get(i); 549 mb.appendLoadConstant(map.getIndex()); 550 mb.appendCallVirtual(REMOVEUNMARSHALLER_METHOD, 551 REMOVEUNMARSHALLER_SIGNATURE); 552 } 553 } 554 555 mb.appendReturn("java.lang.Object"); 557 mb.codeComplete(false); 558 mb.addMethod(); 559 560 if (m_name != null && !m_isAbstract && 562 m_class.getClassFile() == m_class.getMungedFile()) { 563 addIUnmarshallableMethod(); 564 } 565 } 566 567 if (def.isOutput()) { 569 570 ContextMethodBuilder mb = new ContextMethodBuilder 575 (MARSHAL_METHODNAME, Type.VOID, MARSHAL_METHOD_ARGS, cf, 576 Constants.ACC_PUBLIC|Constants.ACC_FINAL, 577 1, "java.lang.Object", 2, MARSHALCONTEXT_INTERFACE); 578 mb.addException(MethodBuilder.FRAMEWORK_EXCEPTION_CLASS); 579 581 ArrayList maps = m_defContext.getMappings(); 583 if (maps != null && maps.size() > 0) { 584 for (int i = 0; i < maps.size(); i++) { 585 mb.loadContext(MARSHALCONTEXT_CLASS); 586 IMapping map = (IMapping)maps.get(i); 587 mb.appendLoadConstant(map.getIndex()); 588 mb.appendLoadConstant(map.getMarshaller().getName()); 589 mb.appendCallVirtual(ADDMARSHALLER_METHOD, 590 ADDMARSHALLER_SIGNATURE); 591 } 592 } 593 594 if (hasattr || hascont) { 596 mb.loadObject(m_class.getClassName()); 597 if (hasattr) { 598 if (hascont) { 599 mb.appendDUP(); 600 } 601 m_component.genAttributeMarshal(mb); 602 } 603 if (hascont) { 604 m_component.genContentMarshal(mb); 605 } 606 } 607 608 if (maps != null && maps.size() > 0) { 610 for (int i = 0; i < maps.size(); i++) { 611 mb.loadContext(MARSHALCONTEXT_CLASS); 612 IMapping map = (IMapping)maps.get(i); 613 mb.appendLoadConstant(map.getIndex()); 614 mb.appendCallVirtual(REMOVEMARSHALLER_METHOD, 615 REMOVEMARSHALLER_SIGNATURE); 616 } 617 } 618 619 mb.appendReturn(); 621 mb.codeComplete(false); 622 mb.addMethod(); 623 624 ExceptionMethodBuilder xb = new ExceptionMethodBuilder 627 (CHECKEXTENDS_METHODNAME, CHECKEXTENDS_SIGNATURE, cf, 628 Constants.ACC_PUBLIC|Constants.ACC_FINAL); 629 if (m_baseMapping == null) { 630 xb.appendICONST_0(); 631 } else { 632 xb.appendLoadLocal(1); 633 xb.appendLoadConstant(m_baseMapping.getIndex()); 634 xb.appendISUB(); 635 BranchWrapper iftrue = xb.appendIFEQ(this); 636 xb.appendICONST_0(); 637 xb.appendReturn("int"); 638 xb.targetNext(iftrue); 639 xb.appendICONST_1(); 640 } 641 xb.appendReturn("int"); 642 xb.codeComplete(false); 643 xb.addMethod(); 644 645 if (m_name != null && !m_isAbstract && 647 m_class.getClassFile() == m_class.getMungedFile()) { 648 addIMarshallableMethod(); 649 } 650 651 if (m_isAbstract) { 654 655 mb = new ContextMethodBuilder(BASEMARSHAL_METHODNAME, 660 Type.VOID, MARSHAL_METHOD_ARGS, cf, 661 Constants.ACC_PUBLIC|Constants.ACC_FINAL, 662 1, "java.lang.Object", 2, MARSHALCONTEXT_INTERFACE); 663 mb.addException(MethodBuilder.FRAMEWORK_EXCEPTION_CLASS); 664 mb.loadContext(); 666 mb.loadObject(IMARSHALLABLE_INTERFACE); 667 mb.appendCallInterface(GETINDEX_METHOD, GETINDEX_SIGNATURE); 668 mb.loadObject(); 669 mb.appendCallVirtual("java.lang.Object.getClass", 670 "()Ljava/lang/Class;"); 671 mb.appendCallVirtual("java.lang.Class.getName", 672 "()Ljava/lang/String;"); 673 mb.appendCallInterface(GETMARSHALLER_METHOD, 674 GETMARSHALLER_SIGNATURE); 675 mb.appendDUP(); 676 mb.appendLoadConstant(getIndex()); 677 mb.appendCallInterface(CHECKEXTENDS_METHOD, 678 CHECKEXTENDS_SIGNATURE); 679 BranchWrapper ifvalid = mb.appendIFNE(this); 680 681 mb.appendCreateNew("java.lang.StringBuffer"); 683 mb.appendDUP(); 684 mb.appendLoadConstant("Mapping for type "); 685 mb.appendCallInit("java.lang.StringBuffer", 686 "(Ljava/lang/String;)V"); 687 mb.appendDUP(); 688 mb.loadObject(); 689 mb.appendCallVirtual("java.lang.Object.getClass", 690 "()Ljava/lang/Class;"); 691 mb.appendCallVirtual("java.lang.Class.getName", 692 "()Ljava/lang/String;"); 693 mb.appendCallVirtual("java.lang.StringBuffer.append", 694 "(Ljava/lang/String;)Ljava/lang/StringBuffer;"); 695 mb.appendDUP(); 696 mb.appendLoadConstant(" must extend abstract mapping for " + 697 "type " + m_class.getClassName()); 698 mb.appendCallVirtual("java.lang.StringBuffer.append", 699 "(Ljava/lang/String;)Ljava/lang/StringBuffer;"); 700 mb.appendCallVirtual("java.lang.StringBuffer.toString", 701 "()Ljava/lang/String;"); 702 mb.appendCreateNew(MethodBuilder.FRAMEWORK_EXCEPTION_CLASS); 703 mb.appendDUP_X1(); 704 mb.appendSWAP(); 705 mb.appendCallInit(MethodBuilder.FRAMEWORK_EXCEPTION_CLASS, 706 MethodBuilder.EXCEPTION_CONSTRUCTOR_SIGNATURE1); 707 mb.appendThrow(); 708 709 mb.targetNext(ifvalid); 711 mb.loadObject(); 712 mb.loadContext(); 713 mb.appendCallInterface(MARSHALLERMARSHAL_METHOD, 714 MARSHALLERMARSHAL_SIGNATURE); 715 mb.appendReturn(); 716 mb.codeComplete(false); 717 mb.addMethod(); 718 719 cf.addInterface(ABSTRACTMARSHALLER_INTERFACE); 721 } 722 } 723 724 m_marshaller = m_unmarshaller = MungedClass.getUniqueSupportClass(cf); 726 } 727 728 731 public void setLinkages() throws JiBXException { 732 m_component.setLinkages(); 733 if (!m_isAbstract) { 734 m_component.checkContentSequence(true); 735 } 736 m_defContext.setLinkages(); 737 } 738 739 public void print(int depth) { 741 BindingDefinition.indent(depth); 742 System.out.print("mapping class " + m_class.getClassFile().getName()); 743 if (m_name != null) { 744 System.out.print(" to element " + m_name.toString()); 745 } 746 System.out.println(); 747 m_component.print(depth+1); 748 } 749 } | Popular Tags |