1 7 package org.jboss.xb.binding; 8 9 import org.xml.sax.SAXException ; 10 import org.xml.sax.InputSource ; 11 import org.apache.ws.jaxme.xs.XSParser; 12 import org.apache.ws.jaxme.xs.XSSchema; 13 import org.apache.ws.jaxme.xs.XSElement; 14 import org.apache.ws.jaxme.xs.XSType; 15 import org.apache.ws.jaxme.xs.XSSimpleType; 16 import org.apache.ws.jaxme.xs.XSComplexType; 17 import org.apache.ws.jaxme.xs.XSParticle; 18 import org.apache.ws.jaxme.xs.XSGroup; 19 import org.apache.ws.jaxme.xs.XSAttributable; 20 import org.apache.ws.jaxme.xs.XSAttribute; 21 import org.apache.ws.jaxme.xs.xml.XsQName; 22 import org.jboss.logging.Logger; 23 24 import javax.xml.parsers.ParserConfigurationException ; 25 import javax.xml.namespace.QName ; 26 import java.io.Reader ; 27 import java.io.Writer ; 28 import java.io.IOException ; 29 import java.util.Iterator ; 30 import java.util.List ; 31 import java.util.Collection ; 32 import java.util.Map ; 33 import java.util.HashMap ; 34 import java.util.Arrays ; 35 36 37 43 public class XsMarshaller 44 extends AbstractMarshaller 45 { 46 private static final Logger log = Logger.getLogger(XsMarshaller.class); 47 48 private Stack stack = new StackImpl(); 49 50 53 private GenericObjectModelProvider provider; 54 57 private Content content = new Content(); 58 61 private final Map prefixByUri = new HashMap (); 62 63 private Object root; 64 65 public void marshal(Reader schema, ObjectModelProvider provider, Object root, Writer writer) 66 throws IOException , SAXException , ParserConfigurationException 67 { 68 InputSource source = new InputSource (schema); 69 70 XSParser xsParser = new XSParser(); 71 xsParser.setValidating(false); 72 XSSchema xsSchema = xsParser.parse(source); 73 74 this.provider = provider instanceof GenericObjectModelProvider ? 75 (GenericObjectModelProvider)provider : new DelegatingObjectModelProvider(provider); 76 77 this.root = root; 78 79 content.startDocument(); 81 82 if(rootQNames.isEmpty()) 83 { 84 XSElement[] elements = xsSchema.getElements(); 85 for(int i = 0; i < elements.length; ++i) 86 { 87 log.info("marshalling " + elements[i].getName().getLocalName()); 88 processElement(elements[i], 1, true); 90 } 91 } 92 else 93 { 94 for(int i = 0; i < rootQNames.size(); ++i) 95 { 96 QName qName = (QName)rootQNames.get(i); 97 XsQName rootName = new XsQName(qName.getNamespaceURI(), qName.getLocalPart(), qName.getPrefix()); 98 99 final XSElement xsRoot = xsSchema.getElement(rootName); 100 if(xsRoot == null) 101 { 102 throw new IllegalStateException ("Root element not found: " + rootName); 103 } 104 105 processElement(xsRoot, 1, true); 107 } 108 } 109 110 content.endDocument(); 111 112 writeXmlVersion(writer); 114 115 ContentWriter contentWriter = new ContentWriter(writer, 116 propertyIsTrueOrNotSet(Marshaller.PROP_OUTPUT_INDENTATION) 117 ); 118 content.handleContent(contentWriter); 119 } 120 121 131 public void declareNamespace(String prefix, String uri) 132 { 133 prefixByUri.put(uri, prefix); 134 } 135 136 146 public void addAttribute(String prefix, String localName, String type, String value) 147 { 148 164 } 165 166 175 public void addAttribute(String namespaceUri, String prefix, String localName, String type, String value) 176 { 177 declareNamespace(prefix, namespaceUri); 178 addAttribute(prefix, localName, type, value); 179 } 180 181 183 private final void processElement(XSElement element, int maxOccurs, boolean declareNs) throws SAXException 184 { 185 XSType type = element.getType(); 186 processType(element, type, maxOccurs, declareNs); 187 } 188 189 private final void processType(XSElement element, XSType type, int maxOccurs, boolean declareNs) 190 throws SAXException 191 { 192 if(type.isSimple()) 193 { 194 processSimpleType(element, type, null, declareNs); 195 } 196 else 197 { 198 XSComplexType complexType = type.getComplexType(); 199 processComplexType(element, complexType, maxOccurs, declareNs); 200 } 201 } 202 203 private final void processSimpleType(XSElement element, XSType xsType, AttributesImpl attrs, boolean declareNs) 204 throws SAXException 205 { 206 XSSimpleType type = xsType.getSimpleType(); 207 if(type.isAtomic()) 208 { 209 if(log.isTraceEnabled()) 210 { 211 log.trace("atomic simple type"); 212 } 213 } 214 else if(type.isList()) 215 { 216 if(log.isTraceEnabled()) 217 { 218 log.trace("list of types"); 219 } 220 } 221 else if(type.isRestriction()) 222 { 223 if(log.isTraceEnabled()) 224 { 225 log.trace("restricted type"); 226 } 227 } 228 else if(type.isUnion()) 229 { 230 if(log.isTraceEnabled()) 231 { 232 log.trace("union of types"); 233 } 234 } 235 else 236 { 237 throw new IllegalStateException ("Simple type is not atomic, list, restriction or union!"); 238 } 239 240 XsQName name = element.getName(); 241 final String prefix = name.getPrefix(); 242 String qName = ( 243 prefix == null || prefix.length() == 0 ? 244 name.getLocalName() : prefix + ':' + name.getLocalName() 245 ); 246 247 if(declareNs && prefixByUri.size() > 0) 248 { 249 if(attrs == null) 250 { 251 attrs = new AttributesImpl(prefixByUri.size()); 252 } 253 declareNs(attrs); 254 } 255 256 Object parent; 257 if(stack.isEmpty()) 258 { 259 parent = provider.getRoot(this.root, null, name.getNamespaceURI(), name.getLocalName()); 260 if(parent == null) 261 { 262 return; 263 } 264 char[] ch = parent.toString().toCharArray(); 265 content.startElement(name.getNamespaceURI(), name.getLocalName(), qName, attrs); 266 content.characters(ch, 0, ch.length); 267 content.endElement(name.getNamespaceURI(), name.getLocalName(), qName); 268 } 269 else 270 { 271 parent = stack.peek(); 272 Object value = provider.getElementValue(parent, null, name.getNamespaceURI(), name.getLocalName()); 273 274 if(value != null) 275 { 276 XsQName typeName = xsType.getName(); 277 String marshalled; 278 if(Constants.NS_XML_SCHEMA.equals(typeName.getNamespaceURI())) 279 { 280 marshalled = SimpleTypeBindings.marshal(typeName.getLocalName(), value, null); 281 } 282 else 283 { 284 marshalled = value.toString(); 285 } 286 287 char[] ch = marshalled.toCharArray(); 288 content.startElement(name.getNamespaceURI(), name.getLocalName(), qName, attrs); 289 content.characters(ch, 0, ch.length); 290 content.endElement(name.getNamespaceURI(), name.getLocalName(), qName); 291 } 292 } 293 } 294 295 private final void processComplexType(XSElement element, 296 XSComplexType type, 297 int maxOccurs, 298 boolean declareNs) 299 throws SAXException 300 { 301 final XsQName xsName = element.getName(); 302 303 AttributesImpl attrs = null; 304 if(declareNs && prefixByUri.size() > 0) 305 { 306 attrs = new AttributesImpl(prefixByUri.size()); 307 declareNs(attrs); 308 } 309 310 Object parent; 311 boolean popRoot = false; 312 if(stack.isEmpty()) 313 { 314 parent = provider.getRoot(this.root, null, xsName.getNamespaceURI(), xsName.getLocalName()); 315 if(parent == null) 316 { 317 return; 318 } 319 320 if(type.getAttributes() != null) 321 { 322 if(attrs == null) 323 { 324 attrs = provideAttributes(type.getAttributes(), parent); 325 } 326 else 327 { 328 attrs.addAll(provideAttributes(type.getAttributes(), parent)); 329 } 330 } 331 332 String qName = xsName.getPrefix() == null ? 333 xsName.getLocalName() : 334 xsName.getPrefix() + ":" + xsName.getLocalName(); 335 content.startElement(xsName.getNamespaceURI(), xsName.getLocalName(), qName, attrs); 336 337 stack.push(parent); 338 popRoot = true; 339 } 340 else 341 { 342 parent = stack.peek(); 343 } 344 345 Object children = null; 347 if(!popRoot) 348 { 349 children = provider.getChildren(parent, null, xsName.getNamespaceURI(), xsName.getLocalName()); 350 } 351 352 if(children != null) 353 { 354 String qName = null; 355 if(maxOccurs == 1) 356 { 357 if(type.getAttributes() != null) 358 { 359 if(attrs != null) 360 { 361 attrs.addAll(provideAttributes(type.getAttributes(), parent)); 362 } 363 else 364 { 365 attrs = provideAttributes(type.getAttributes(), parent); 366 } 367 } 368 369 qName = xsName.getPrefix() == null ? 370 xsName.getLocalName() : 371 xsName.getPrefix() + ":" + xsName.getLocalName(); 372 content.startElement(xsName.getNamespaceURI(), xsName.getLocalName(), qName, attrs); 373 } 374 375 handleChildren(element, type, children, maxOccurs); 376 377 if(qName != null) 378 { 379 content.endElement(xsName.getNamespaceURI(), xsName.getLocalName(), qName); 380 } 381 } 382 else 383 { 384 if(type.hasSimpleContent()) 385 { 386 processSimpleType(element, type.getSimpleContent().getType(), null, declareNs); 387 } 388 else 389 { 390 if(type.isEmpty()) 391 { 392 final XsQName name = element.getName(); 393 394 final Object value = provider.getElementValue(parent, 395 null, 396 name.getNamespaceURI(), 397 name.getLocalName() 398 ); 399 if(Boolean.TRUE.equals(value)) 400 { 401 final String prefix = name.getPrefix(); 402 String qName = ( 403 prefix == null || prefix.length() == 0 ? 404 name.getLocalName() : prefix + ':' + name.getLocalName() 405 ); 406 407 AttributesImpl ownAttrs = provideAttributes(type.getAttributes(), parent); 408 409 if(declareNs && prefixByUri.size() > 0) 410 { 411 if(ownAttrs == null) 412 { 413 ownAttrs = new AttributesImpl(prefixByUri.size()); 414 } 415 declareNs(ownAttrs); 416 } 417 418 content.startElement(name.getNamespaceURI(), name.getLocalName(), qName, ownAttrs); 419 content.endElement(name.getNamespaceURI(), name.getLocalName(), qName); 420 } 421 } 422 else 423 { 424 final XSParticle particle = type.getParticle(); 425 if(particle != null) 426 { 427 processParticle(particle); 428 } 429 else 430 { 431 } 433 } 434 } 435 } 436 437 if(popRoot) 438 { 439 stack.pop(); 440 String qName = xsName.getPrefix() == null ? 441 xsName.getLocalName() : 442 xsName.getPrefix() + ":" + xsName.getLocalName(); 443 content.endElement(xsName.getNamespaceURI(), xsName.getLocalName(), qName); 444 } 445 } 446 447 private void handleChildren(XSElement parent, 448 XSComplexType type, 449 Object children, 450 int maxOccurs) 451 throws SAXException 452 { 453 if(children != null) 454 { 455 if(children instanceof List ) 456 { 457 handleChildrenList(parent, type, (List )children, maxOccurs); 458 } 459 else if(children instanceof Collection ) 460 { 461 handleChildrenIterator(parent, type, ((Collection )children).iterator(), maxOccurs); 462 } 463 else if(children instanceof Iterator ) 464 { 465 handleChildrenIterator(parent, type, (Iterator )children, maxOccurs); 466 } 467 else if(children.getClass().isArray()) 468 { 469 handleChildrenArray(parent, type, (Object [])children, maxOccurs); 470 } 471 else 472 { 473 handleChild(parent, type, children, false); 474 } 475 } 476 } 477 478 private AttributesImpl provideAttributes(XSAttributable[] xsAttrs, Object container) 479 { 480 AttributesImpl attrs = new AttributesImpl(xsAttrs.length); 481 for(int i = 0; i < xsAttrs.length; ++i) 482 { 483 final XSAttributable attributable = xsAttrs[i]; 484 if(attributable instanceof XSAttribute) 485 { 486 final XSAttribute attr = (XSAttribute)attributable; 487 488 final XsQName attrQName = attr.getName(); 489 final Object attrValue = provider.getAttributeValue(container, 490 null, attrQName.getNamespaceURI(), 491 attrQName.getLocalName() 492 ); 493 494 if(attrValue != null) 495 { 496 final String prefix = attrQName.getPrefix(); 497 String qName = ( 498 prefix == null || prefix.length() == 0 ? 499 attrQName.getLocalName() : attrQName.getPrefix() + ':' + attrQName.getLocalName() 500 ); 501 502 attrs.add(attrQName.getNamespaceURI(), 503 attrQName.getLocalName(), 504 qName, 505 attr.getType().getName().getLocalName(), 506 attrValue.toString() 507 ); 508 } 509 else 510 { 511 log.info("no val for attr " + attrQName.getLocalName() + ", container=" + container); 512 } 513 } 514 } 515 return attrs; 516 } 517 518 private final void processParticle(XSParticle particle) throws SAXException 519 { 520 if(particle.isElement()) 521 { 522 XSElement element = particle.getElement(); 523 processElement(element, particle.getMaxOccurs(), false); 524 } 525 else if(particle.isGroup()) 526 { 527 XSGroup group = particle.getGroup(); 528 processGroup(group); 529 } 530 else if(particle.isWildcard()) 531 { 532 if(log.isTraceEnabled()) 533 { 534 log.trace("any"); 535 } 536 } 537 else 538 { 539 throw new IllegalStateException ("Particle is not an element, group or wildcard!"); 540 } 541 } 542 543 private final void processGroup(XSGroup group) throws SAXException 544 { 545 if(group.isSequence()) 546 { 547 } 548 else if(group.isChoice()) 549 { 550 } 551 else if(group.isAll()) 552 { 553 } 554 else 555 { 556 throw new IllegalStateException ("Group is not a sequence, choice or all!"); 557 } 558 559 XSParticle[] particles = group.getParticles(); 560 for(int i = 0; i < particles.length; ++i) 561 { 562 XSParticle particle = particles[i]; 563 processParticle(particle); 564 } 565 } 566 567 private void handleChildrenList(XSElement parent, 568 XSComplexType type, 569 List children, 570 int maxOccurs) 571 throws SAXException 572 { 573 579 handleChildrenIterator(parent, type, children.iterator(), maxOccurs); 580 } 581 582 private void handleChildrenIterator(XSElement parent, 583 XSComplexType type, 584 Iterator children, 585 int maxOccurs) 586 throws SAXException 587 { 588 XsQName name = parent.getName(); 590 String qName = null; 591 if(maxOccurs == -1 || maxOccurs > 0) 592 { 593 qName = name.getPrefix() == null ? name.getLocalName() : name.getPrefix() + ':' + name.getLocalName(); 594 } 595 596 while(children.hasNext()) 597 { 598 Object child = children.next(); 599 600 if(qName != null) 601 { 602 AttributesImpl attrs = null; 603 if(type.getAttributes() != null) 604 { 605 if(attrs != null) 606 { 607 attrs.addAll(provideAttributes(type.getAttributes(), child)); 608 } 609 else 610 { 611 attrs = provideAttributes(type.getAttributes(), child); 612 } 613 } 614 615 content.startElement(name.getNamespaceURI(), name.getLocalName(), qName, attrs); 616 } 617 618 handleChild(parent, type, child, false); 619 620 if(qName != null) 621 { 622 content.endElement(name.getNamespaceURI(), name.getLocalName(), qName); 623 } 624 } 625 } 626 627 private void handleChildrenArray(XSElement parent, 628 XSComplexType type, 629 Object [] children, 630 int maxOccurs) 631 throws SAXException 632 { 633 639 handleChildrenIterator(parent, type, Arrays.asList(children).iterator(), maxOccurs); 640 } 641 642 private void handleChild(XSElement parent, XSComplexType type, Object child, boolean declareNs) 643 throws SAXException 644 { 645 stack.push(child); 646 647 final XSAttributable[] xsAttrs = type.getAttributes(); 648 AttributesImpl ownAttrs = (xsAttrs == null ? null : provideAttributes(xsAttrs, child)); 649 650 if(type.hasSimpleContent()) 651 { 652 processSimpleType(parent, type.getSimpleContent().getType(), ownAttrs, declareNs); 653 } 654 else 655 { 656 if(!type.isEmpty() && type.getParticle() != null) 657 { 658 processParticle(type.getParticle()); 659 } 660 else 661 { 662 ClassMapping mapping = getClassMapping(child.getClass()); 663 664 InputSource source = new InputSource (mapping.schemaUrl); 665 666 XSParser xsParser = new XSParser(); 667 xsParser.setValidating(false); 668 XSSchema xsSchema; 669 try 670 { 671 xsSchema = xsParser.parse(source); 672 } 673 catch(Exception e) 674 { 675 log.error(e); 676 throw new IllegalStateException (e.getMessage()); 677 } 678 679 XsQName rootName = new XsQName(mapping.namespaceUri, mapping.root); 680 XSElement root = xsSchema.getElement(rootName); 681 rootName = root.getName(); 683 684 String rootPrefix = rootName.getPrefix(); 685 String rootQName = (rootPrefix == null || rootPrefix.length() == 0 ? 686 rootName.getLocalName() : rootPrefix + ':' + rootName.getLocalName() 687 ); 688 689 Stack oldStack = this.stack; 690 this.stack = new StackImpl(); 691 Object oldRoot = this.root; 692 this.root = child; 693 GenericObjectModelProvider oldProvider = this.provider; 694 this.provider = mapping.provider; 695 content.startElement(rootName.getNamespaceURI(), rootName.getLocalName(), rootQName, null); 696 697 processElement(root, 1, false); 698 699 content.endElement(rootName.getNamespaceURI(), rootName.getLocalName(), rootQName); 700 this.root = oldRoot; 701 this.stack = oldStack; 702 this.provider = oldProvider; 703 } 704 } 705 706 stack.pop(); 707 } 708 709 private void declareNs(AttributesImpl ownAttrs) 710 { 711 for(Iterator i = prefixByUri.entrySet().iterator(); i.hasNext();) 712 { 713 Map.Entry entry = (Map.Entry )i.next(); 714 String localName = (String )entry.getValue(); 715 ownAttrs.add(null, 716 localName, 717 localName == null ? "xmlns" : "xmlns:" + localName, 718 null, 719 (String )entry.getKey() 720 ); 721 } 722 } 723 724 730 } 731 | Popular Tags |