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