1 7 package org.jboss.xml.binding; 8 9 import org.apache.xerces.dom3.bootstrap.DOMImplementationRegistry; 10 import org.apache.xerces.xs.XSAttributeDeclaration; 11 import org.apache.xerces.xs.XSAttributeUse; 12 import org.apache.xerces.xs.XSComplexTypeDefinition; 13 import org.apache.xerces.xs.XSConstants; 14 import org.apache.xerces.xs.XSElementDeclaration; 15 import org.apache.xerces.xs.XSImplementation; 16 import org.apache.xerces.xs.XSLoader; 17 import org.apache.xerces.xs.XSModel; 18 import org.apache.xerces.xs.XSModelGroup; 19 import org.apache.xerces.xs.XSNamedMap; 20 import org.apache.xerces.xs.XSObject; 21 import org.apache.xerces.xs.XSObjectList; 22 import org.apache.xerces.xs.XSParticle; 23 import org.apache.xerces.xs.XSTerm; 24 import org.apache.xerces.xs.XSTypeDefinition; 25 import org.apache.xerces.xs.XSWildcard; 26 import org.jboss.logging.Logger; 27 import org.xml.sax.SAXException ; 28 29 import javax.xml.parsers.ParserConfigurationException ; 30 import javax.xml.namespace.QName ; 31 import java.io.IOException ; 32 import java.io.Reader ; 33 import java.io.Writer ; 34 import java.util.Collection ; 35 import java.util.HashMap ; 36 import java.util.Iterator ; 37 import java.util.Map ; 38 39 43 public class XercesXsMarshaller 44 extends AbstractMarshaller 45 { 46 private static final Logger log = Logger.getLogger(XercesXsMarshaller.class); 47 48 private Stack stack = new StackImpl(); 49 50 53 private GenericObjectModelProvider provider; 54 57 private Content content = new Content(); 58 59 private final Map prefixByUri = new HashMap (); 60 61 private Object root; 62 63 73 public void declareNamespace(String name, String uri) 74 { 75 prefixByUri.put(uri, name); 76 } 77 78 88 public void addAttribute(String prefix, String localName, String type, String value) 89 { 90 } 92 93 95 public void marshal(Reader xsdReader, ObjectModelProvider provider, Object root, Writer writer) 96 throws IOException , SAXException , ParserConfigurationException 97 { 98 XSModel model = loadSchema(xsdReader); 99 marshallInternal(provider, root, model, writer); 100 } 101 102 public void marshal(String xsdURL, ObjectModelProvider provider, Object root, Writer writer) throws IOException , 103 SAXException 104 { 105 XSModel model = loadSchema(xsdURL); 106 marshallInternal(provider, root, model, writer); 107 } 108 109 private void marshallInternal(ObjectModelProvider provider, Object root, XSModel model, Writer writer) 110 throws IOException , SAXException 111 { 112 this.provider = provider instanceof GenericObjectModelProvider ? 113 (GenericObjectModelProvider)provider : new DelegatingObjectModelProvider(provider); 114 115 this.root = root; 116 117 content.startDocument(); 118 119 if (rootQNames.isEmpty()) 120 { 121 XSNamedMap components = model.getComponents(XSConstants.ELEMENT_DECLARATION); 122 for (int i = 0; i < components.getLength(); ++i) 123 { 124 XSElementDeclaration element = (XSElementDeclaration)components.item(i); 125 marshalElement(element, 1, 1); } 127 } 128 else 129 { 130 for (int i = 0; i < rootQNames.size(); ++i) 131 { 132 QName qName = (QName )rootQNames.get(i); 133 XSElementDeclaration element = model.getElementDeclaration(qName.getLocalPart(), qName.getNamespaceURI()); 134 if (element == null) 135 { 136 XSNamedMap components = model.getComponents(XSConstants.ELEMENT_DECLARATION); 137 String roots = ""; 138 for (int j = 0; j < components.getLength(); ++j) 139 { 140 XSObject xsObject = components.item(j); 141 if (j > 0) 142 { 143 roots += ", "; 144 } 145 roots += xsObject.getNamespace() + ":" + xsObject.getName(); 146 } 147 throw new IllegalStateException ("Root element not found: " + qName + " among " + roots); 148 } 149 150 marshalElement(element, 1, 1); } 152 } 153 154 content.endDocument(); 155 156 writeXmlVersion(writer); 158 159 ContentWriter contentWriter = new ContentWriter(writer, propertyIsTrueOrNotSet(Marshaller.PROP_OUTPUT_INDENTATION)); 160 content.handleContent(contentWriter); 161 } 162 163 private boolean marshalElement(XSElementDeclaration element, int minOccurs, int maxOccurs) 164 { 165 Object value; 166 if (stack.isEmpty()) 167 { 168 value = provider.getRoot(root, element.getNamespace(), element.getName()); 169 if (value == null) 170 { 171 return false; 172 } 173 } 174 else 175 { 176 if (stack.peek() instanceof Collection ) 177 { 178 value = (Collection )stack.peek(); 180 } 181 else 182 { 183 value = provider.getChildren(stack.peek(), element.getNamespace(), element.getName()); 184 if (value == null) 185 { 186 value = provider.getElementValue(stack.peek(), element.getNamespace(), element.getName()); 187 } 188 } 189 } 190 191 if (value != null) 192 { 193 stack.push(value); 194 195 if (maxOccurs != 1 && value instanceof Collection ) 196 { 197 for (Iterator iter = ((Collection )value).iterator(); iter.hasNext();) 198 { 199 Object item = iter.next(); 200 stack.push(item); 201 marshalElementType(element); 202 stack.pop(); 203 } 204 } 205 else 206 { 207 marshalElementType(element); 208 } 209 210 stack.pop(); 211 } 212 213 return minOccurs == 0 || value != null; 214 } 215 216 private void marshalElementType(XSElementDeclaration element) 217 { 218 XSTypeDefinition type = element.getTypeDefinition(); 219 switch (type.getTypeCategory()) 220 { 221 case XSTypeDefinition.SIMPLE_TYPE: 222 marshalSimpleType(element); 223 break; 224 case XSTypeDefinition.COMPLEX_TYPE: 225 marshalComplexType(element); 226 break; 227 default: 228 throw new IllegalStateException ("Unexpected type category: " + type.getTypeCategory()); 229 } 230 } 231 232 private void marshalSimpleType(XSElementDeclaration element) 233 { 234 Object value = stack.peek(); 235 String valueStr = value.toString(); 236 237 String prefix = (String )prefixByUri.get(element.getNamespace()); 238 String qName = prefix == null ? element.getName() : prefix + ':' + element.getName(); 239 240 content.startElement(element.getNamespace(), element.getName(), qName, null); 241 content.characters(valueStr.toCharArray(), 0, valueStr.length()); 242 content.endElement(element.getNamespace(), element.getName(), qName); 243 } 244 245 private void marshalComplexType(XSElementDeclaration element) 246 { 247 XSComplexTypeDefinition type = (XSComplexTypeDefinition)element.getTypeDefinition(); 248 XSParticle particle = type.getParticle(); 249 250 XSObjectList attributeUses = type.getAttributeUses(); 251 AttributesImpl attrs = attributeUses.getLength() > 0 ? new AttributesImpl(attributeUses.getLength()) : null; 252 for (int i = 0; i < attributeUses.getLength(); ++i) 253 { 254 XSAttributeUse attrUse = (XSAttributeUse)attributeUses.item(i); 255 XSAttributeDeclaration attrDec = attrUse.getAttrDeclaration(); 256 Object attrValue = provider.getAttributeValue(stack.peek(), attrDec.getNamespace(), attrDec.getName()); 257 if (attrValue != null) 258 { 259 attrs.add(attrDec.getNamespace(), 260 attrDec.getName(), 261 attrDec.getName(), 262 attrDec.getTypeDefinition().getName(), 263 attrValue.toString()); 264 } 265 } 266 267 String prefix = (String )prefixByUri.get(element.getNamespace()); 268 String qName = prefix == null ? element.getName() : prefix + ':' + element.getName(); 269 content.startElement(element.getNamespace(), element.getName(), qName, attrs); 270 271 if (particle != null) 272 { 273 marshalParticle(particle); 274 } 275 276 content.endElement(element.getNamespace(), element.getName(), qName); 277 } 278 279 private boolean marshalParticle(XSParticle particle) 280 { 281 boolean marshalled; 282 XSTerm term = particle.getTerm(); 283 switch (term.getType()) 284 { 285 case XSConstants.MODEL_GROUP: 286 marshalled = marshalModelGroup((XSModelGroup)term); 287 break; 288 case XSConstants.WILDCARD: 289 marshalled = marshalWildcard((XSWildcard)term); 290 break; 291 case XSConstants.ELEMENT_DECLARATION: 292 marshalled = marshalElement((XSElementDeclaration)term, particle.getMinOccurs(), particle.getMaxOccurs()); 293 break; 294 default: 295 throw new IllegalStateException ("Unexpected term type: " + term.getType()); 296 } 297 return marshalled; 298 } 299 300 private boolean marshalWildcard(XSWildcard wildcard) 301 { 302 ClassMapping mapping = getClassMapping(stack.peek().getClass()); 304 if (mapping == null) 305 { 306 throw new IllegalStateException ("Failed to marshal wildcard. Class mapping not found for " + stack.peek()); 307 } 308 309 GenericObjectModelProvider parentProvider = this.provider; 310 Object parentRoot = this.root; 311 Stack parentStack = this.stack; 312 313 this.root = stack.peek(); 314 this.provider = mapping.provider; 315 this.stack = new StackImpl(); 316 317 boolean marshalled = false; 318 XSModel model = loadSchema(mapping.schemaUrl); 319 XSNamedMap components = model.getComponents(XSConstants.ELEMENT_DECLARATION); 320 for (int i = 0; i < components.getLength(); ++i) 321 { 322 XSElementDeclaration element = (XSElementDeclaration)components.item(i); 323 marshalled = marshalElement(element, 1, 1); } 325 326 this.root = parentRoot; 327 this.provider = parentProvider; 328 this.stack = parentStack; 329 330 return marshalled; 331 } 332 333 private boolean marshalModelGroup(XSModelGroup modelGroup) 334 { 335 boolean marshalled; 336 switch (modelGroup.getCompositor()) 337 { 338 case XSModelGroup.COMPOSITOR_ALL: 339 marshalled = marshalModelGroupAll(modelGroup.getParticles()); 340 break; 341 case XSModelGroup.COMPOSITOR_CHOICE: 342 marshalled = marshalModelGroupChoice(modelGroup.getParticles()); 343 break; 344 case XSModelGroup.COMPOSITOR_SEQUENCE: 345 marshalled = marshalModelGroupSequence(modelGroup.getParticles()); 346 break; 347 default: 348 throw new IllegalStateException ("Unexpected compsitor: " + modelGroup.getCompositor()); 349 } 350 return marshalled; 351 } 352 353 private boolean marshalModelGroupAll(XSObjectList particles) 354 { 355 boolean marshalled = false; 356 for (int i = 0; i < particles.getLength(); ++i) 357 { 358 XSParticle particle = (XSParticle)particles.item(i); 359 marshalled |= marshalParticle(particle); 360 } 361 return marshalled; 362 } 363 364 private boolean marshalModelGroupChoice(XSObjectList particles) 365 { 366 boolean marshalled = false; 367 Content mainContent = this.content; 368 for (int i = 0; i < particles.getLength() && !marshalled; ++i) 369 { 370 XSParticle particle = (XSParticle)particles.item(i); 371 this.content = new Content(); 372 marshalled = marshalParticle(particle); 373 } 374 375 if (marshalled) 376 { 377 mainContent.append(this.content); 378 } 379 this.content = mainContent; 380 381 return marshalled; 382 } 383 384 private boolean marshalModelGroupSequence(XSObjectList particles) 385 { 386 boolean marshalled = true; 387 for (int i = 0; i < particles.getLength(); ++i) 388 { 389 XSParticle particle = (XSParticle)particles.item(i); 390 marshalled &= marshalParticle(particle); 391 } 392 return marshalled; 393 } 394 395 private XSModel loadSchema(String xsdURL) 396 { 397 XSImplementation impl = getXSImplementation(); 398 XSLoader schemaLoader = impl.createXSLoader(null); 399 XSModel model = schemaLoader.loadURI(xsdURL); 400 if (model == null) 401 { 402 throw new IllegalArgumentException ("Invalid URI for schema: " + xsdURL); 403 } 404 405 return model; 406 } 407 408 private XSModel loadSchema(Reader xsdReader) 409 { 410 XSImplementation impl = getXSImplementation(); 411 XSLoader schemaLoader = impl.createXSLoader(null); 412 XSModel model = schemaLoader.load(null); 414 if (model == null) 415 { 416 throw new IllegalArgumentException ("Cannot load schema"); 417 } 418 419 return model; 420 } 421 422 private XSImplementation getXSImplementation() 423 { 424 System.setProperty(DOMImplementationRegistry.PROPERTY, "org.apache.xerces.dom.DOMXSImplementationSourceImpl"); 426 427 XSImplementation impl; 428 try 429 { 430 DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance(); 431 impl = (XSImplementation)registry.getDOMImplementation("XS-Loader"); 432 } 433 catch (Exception e) 434 { 435 log.error("Failed to create schema loader.", e); 436 throw new IllegalStateException ("Failed to create schema loader: " + e.getMessage()); 437 } 438 return impl; 439 } 440 } 441 | Popular Tags |