1 22 package org.jboss.xb.binding; 23 24 import java.io.IOException ; 25 import java.io.Writer ; 26 import java.util.ArrayList ; 27 import java.util.Collections ; 28 import java.util.HashMap ; 29 import java.util.List ; 30 import java.util.Map ; 31 import java.util.Properties ; 32 import java.util.Iterator ; 33 import javax.xml.namespace.QName ; 34 import org.jboss.logging.Logger; 35 import org.jboss.xb.binding.introspection.FieldInfo; 36 import org.xml.sax.SAXException ; 37 import org.xml.sax.ContentHandler ; 38 import org.xml.sax.Locator ; 39 import org.xml.sax.Attributes ; 40 41 45 public abstract class AbstractMarshaller 46 implements Marshaller 47 { 48 protected final Logger log = Logger.getLogger(getClass()); 49 50 protected String version = VERSION; 51 protected String encoding = ENCODING; 52 protected List rootQNames = new ArrayList (); 53 54 protected NamespaceRegistry nsRegistry = new NamespaceRegistry(); 55 56 private Map classMappings = Collections.EMPTY_MAP; 57 protected Map field2WildcardMap = Collections.EMPTY_MAP; 58 protected Map cls2TypeMap = Collections.EMPTY_MAP; 59 60 63 protected Content content = new Content(); 64 65 private Properties props; 66 67 69 public void mapClassToGlobalElement(Class cls, 70 String localName, 71 String namespaceUri, 72 String schemaUrl, 73 ObjectModelProvider provider) 74 { 75 GenericObjectModelProvider delProv = null; 76 if(provider != null) 77 { 78 delProv = provider instanceof GenericObjectModelProvider ? 79 (GenericObjectModelProvider)provider : 80 new DelegatingObjectModelProvider(provider); 81 } 82 83 ClassMapping mapping = new ClassMapping(cls, 84 localName, 85 null, 86 namespaceUri, 87 schemaUrl, 88 delProv 89 ); 90 91 addClassMapping(mapping); 92 } 93 94 public void mapClassToGlobalType(Class cls, 95 String localName, 96 String nsUri, 97 String schemaUrl, 98 ObjectModelProvider provider) 99 { 100 ClassMapping mapping = new ClassMapping(cls, 101 null, 102 localName, 103 nsUri, 104 schemaUrl, 105 provider instanceof GenericObjectModelProvider ? 106 (GenericObjectModelProvider)provider : 107 new DelegatingObjectModelProvider(provider) 108 ); 109 110 addClassMapping(mapping); 111 } 112 113 public void mapFieldToWildcard(Class cls, String field, ObjectLocalMarshaller marshaller) 114 { 115 FieldToWildcardMapping mapping = new FieldToWildcardMapping(cls, field, marshaller); 116 switch(field2WildcardMap.size()) 117 { 118 case 0: 119 field2WildcardMap = Collections.singletonMap(cls, mapping); 120 break; 121 case 1: 122 field2WildcardMap = new HashMap (field2WildcardMap); 123 default: 124 field2WildcardMap.put(cls, mapping); 125 } 126 } 127 128 public void mapClassToXsiType(Class cls, String typeNs, String typeLocalPart) 129 { 130 QName typeQName = new QName (typeNs, typeLocalPart); 131 switch(cls2TypeMap.size()) 132 { 133 case 0: 134 cls2TypeMap = Collections.singletonMap(cls, typeQName); 135 break; 136 case 1: 137 cls2TypeMap = new HashMap (cls2TypeMap); 138 default: 139 cls2TypeMap.put(cls, typeQName); 140 } 141 142 if(log.isTraceEnabled()) 143 { 144 log.trace("mapped " + cls + " to xsi:type " + typeQName); 145 } 146 } 147 148 public void setVersion(String version) 149 { 150 this.version = version; 151 } 152 153 public void setEncoding(String encoding) 154 { 155 this.encoding = encoding; 156 } 157 158 public void mapPublicIdToSystemId(String publicId, String systemId) 159 { 160 throw new UnsupportedOperationException (); 161 } 162 163 public void addRootElement(String namespaceUri, String prefix, String name) 164 { 165 addRootElement(new QName (namespaceUri, name, prefix)); 166 } 167 168 public void addRootElement(QName qName) 169 { 170 rootQNames.add(qName); 171 } 172 173 public void setProperty(String name, String value) 174 { 175 if(props == null) 176 { 177 props = new Properties (); 178 } 179 props.setProperty(name, value); 180 } 181 182 public String getProperty(String name) 183 { 184 return props == null ? null : props.getProperty(name); 185 } 186 187 197 public void declareNamespace(String prefix, String uri) 198 { 199 if(prefix == null) 200 { 201 return; 202 } 203 204 nsRegistry.addPrefixMapping(prefix, uri); 205 } 206 207 public void removePrefixMapping(String prefix) 208 { 209 nsRegistry.removePrefixMapping(prefix); 210 } 211 212 public String getPrefix(String ns) 213 { 214 String prefix = nsRegistry.getPrefix(ns); 215 if(prefix == null && Constants.NS_XML_NAMESPACE.equals(ns)) 216 { 217 prefix = "xml"; 218 } 219 return prefix; 220 } 221 222 protected void declareNs(AttributesImpl attrs) 223 { 224 for(Iterator i = nsRegistry.getRegisteredURIs(); i.hasNext();) 225 { 226 String uri = (String )i.next(); 227 String prefix = nsRegistry.getPrefix(uri); 228 declareNs(attrs, prefix, uri); 229 } 230 } 231 232 protected static void declareNs(AttributesImpl attrs, String prefix, String ns) 233 { 234 attrs.add(null, prefix, prefix.length() == 0 ? "xmlns" : "xmlns:" + prefix, "CDATA", ns); 235 } 236 237 244 protected String declareXsiType(QName typeQName, AttributesImpl attrs) 245 { 246 String result = null; 247 String xsiPrefix = nsRegistry.getPrefix(Constants.NS_XML_SCHEMA_INSTANCE); 248 if(xsiPrefix == null) 249 { 250 declareNs(attrs, "xsi", Constants.NS_XML_SCHEMA_INSTANCE); 251 xsiPrefix = "xsi"; 252 } 253 254 String pref = getPrefix(typeQName.getNamespaceURI()); 255 if(pref == null) 256 { 257 result = pref = typeQName.getLocalPart() + "_ns"; 259 } 260 261 String qName = prefixLocalName(pref, typeQName.getLocalPart()); 262 attrs.add(Constants.NS_XML_SCHEMA_INSTANCE, "type", xsiPrefix + ":type", "CDATA", qName); 263 return result; 264 } 265 266 protected static String prefixLocalName(String prefix, String local) 267 { 268 return prefix == null || prefix.length() == 0 ? local : prefix + ':' + local; 269 } 270 271 public abstract void addAttribute(String prefix, String localName, String type, String value); 272 273 275 protected boolean propertyIsTrueOrNotSet(String name) 276 { 277 String value = getProperty(name); 278 return value == null || "true".equalsIgnoreCase(value); 279 } 280 281 protected void writeXmlVersion(Writer writer) throws IOException 282 { 283 String xmlVersion = getProperty(Marshaller.PROP_OUTPUT_XML_VERSION); 284 if(xmlVersion == null || "true".equalsIgnoreCase(xmlVersion)) 285 { 286 writer.write("<?xml version=\""); 287 writer.write(version); 288 writer.write("\" encoding=\""); 289 writer.write(encoding); 290 writer.write("\"?>\n"); 291 } 292 } 293 294 protected ClassMapping getClassMapping(Class cls) 295 { 296 return (ClassMapping)classMappings.get(cls); 297 } 298 299 private void addClassMapping(ClassMapping mapping) 300 { 301 if(classMappings == Collections.EMPTY_MAP) 302 { 303 classMappings = new HashMap (); 304 } 305 classMappings.put(mapping.cls, mapping); 306 } 307 308 310 protected class ClassMapping 311 { 312 public final Class cls; 313 public final QName elementName; 314 public final QName typeName; 315 public final String schemaUrl; 316 public final GenericObjectModelProvider provider; 317 318 public ClassMapping(Class cls, 319 String elementName, 320 String typeName, 321 String nsUri, 322 String schemaUrl, 323 GenericObjectModelProvider provider) 324 { 325 this.cls = cls; 326 if(elementName != null) 327 { 328 this.elementName = nsUri == null ? new QName (elementName) : new QName (nsUri, elementName); 329 this.typeName = null; 330 } 331 else if(typeName != null) 332 { 333 this.elementName = null; 334 this.typeName = nsUri == null ? new QName (typeName) : new QName (nsUri, typeName); 335 } 336 else 337 { 338 throw new JBossXBRuntimeException("Element or type name must not null for " + cls); 339 } 340 341 this.schemaUrl = schemaUrl; 342 this.provider = provider; 343 } 344 345 public boolean equals(Object o) 346 { 347 if(this == o) 348 { 349 return true; 350 } 351 if(o == null || getClass() != o.getClass()) 352 { 353 return false; 354 } 355 356 final ClassMapping that = (ClassMapping)o; 357 358 if(cls != null ? !cls.equals(that.cls) : that.cls != null) 359 { 360 return false; 361 } 362 if(elementName != null ? !elementName.equals(that.elementName) : that.elementName != null) 363 { 364 return false; 365 } 366 if(provider != null ? !provider.equals(that.provider) : that.provider != null) 367 { 368 return false; 369 } 370 if(schemaUrl != null ? !schemaUrl.equals(that.schemaUrl) : that.schemaUrl != null) 371 { 372 return false; 373 } 374 if(typeName != null ? !typeName.equals(that.typeName) : that.typeName != null) 375 { 376 return false; 377 } 378 379 return true; 380 } 381 382 public int hashCode() 383 { 384 int result; 385 result = (cls != null ? cls.hashCode() : 0); 386 result = 29 * result + (elementName != null ? elementName.hashCode() : 0); 387 result = 29 * result + (typeName != null ? typeName.hashCode() : 0); 388 result = 29 * result + (schemaUrl != null ? schemaUrl.hashCode() : 0); 389 result = 29 * result + (provider != null ? provider.hashCode() : 0); 390 return result; 391 } 392 } 393 394 protected class FieldToWildcardMapping 395 { 396 public final Class cls; 397 public final ObjectLocalMarshaller marshaller; 398 public final FieldInfo fieldInfo; 399 400 public FieldToWildcardMapping(Class cls, String field, ObjectLocalMarshaller marshaller) 401 { 402 if(log.isTraceEnabled()) 403 { 404 log.trace("new FieldToWildcardMapping: [cls=" + 405 cls.getName() + 406 ",field=" + 407 field + 408 "]" 409 ); 410 } 411 412 this.cls = cls; 413 this.marshaller = marshaller; 414 this.fieldInfo = FieldInfo.getFieldInfo(cls, field, true); 415 } 416 417 public boolean equals(Object o) 418 { 419 if(this == o) 420 { 421 return true; 422 } 423 if(!(o instanceof FieldToWildcardMapping)) 424 { 425 return false; 426 } 427 428 final FieldToWildcardMapping fieldToWildcardMapping = (FieldToWildcardMapping)o; 429 430 if(!cls.equals(fieldToWildcardMapping.cls)) 431 { 432 return false; 433 } 434 if(!fieldInfo.getName().equals(fieldToWildcardMapping.fieldInfo.getName())) 435 { 436 return false; 437 } 438 439 return true; 440 } 441 442 public int hashCode() 443 { 444 int result; 445 result = cls.hashCode(); 446 result = 29 * result + fieldInfo.getName().hashCode(); 447 return result; 448 } 449 } 450 451 protected static interface Stack 452 { 453 void clear(); 454 455 void push(Object o); 456 457 Object pop(); 458 459 Object peek(); 460 461 boolean isEmpty(); 462 } 463 464 public static class StackImpl 465 implements Stack 466 { 467 private List list = new ArrayList (); 468 469 public void clear() 470 { 471 list.clear(); 472 } 473 474 public void push(Object o) 475 { 476 list.add(o); 477 } 478 479 public Object pop() 480 { 481 return list.remove(list.size() - 1); 482 } 483 484 public Object peek() 485 { 486 return list.get(list.size() - 1); 487 } 488 489 public boolean isEmpty() 490 { 491 return list.isEmpty(); 492 } 493 } 494 495 public class ContentHandlerAdaptor 496 implements ContentHandler 497 { 498 public void setDocumentLocator(Locator locator) 499 { 500 } 501 502 public void startDocument() throws SAXException 503 { 504 } 506 507 public void endDocument() throws SAXException 508 { 509 } 511 512 public void startPrefixMapping(String prefix, String uri) throws SAXException 513 { 514 content.startPrefixMapping(prefix, uri); 515 } 516 517 public void endPrefixMapping(String prefix) throws SAXException 518 { 519 content.endPrefixMapping(prefix); 520 } 521 522 public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException 523 { 524 content.startElement(uri, localName, qName, atts); 525 } 526 527 public void endElement(String uri, String localName, String qName) throws SAXException 528 { 529 content.endElement(uri, localName, qName); 530 } 531 532 public void characters(char ch[], int start, int length) throws SAXException 533 { 534 content.characters(ch, start, length); 535 } 536 537 public void ignorableWhitespace(char ch[], int start, int length) throws SAXException 538 { 539 } 540 541 public void processingInstruction(String target, String data) throws SAXException 542 { 543 } 544 545 public void skippedEntity(String name) throws SAXException 546 { 547 } 548 } 549 } 550 | Popular Tags |