1 7 8 package org.dom4j.datatype; 9 10 import com.sun.msv.datatype.xsd.DatatypeFactory; 11 import com.sun.msv.datatype.xsd.TypeIncubator; 12 import com.sun.msv.datatype.xsd.XSDatatype; 13 14 import java.util.HashMap ; 15 import java.util.Iterator ; 16 import java.util.Map ; 17 18 import org.dom4j.Attribute; 19 import org.dom4j.Document; 20 import org.dom4j.DocumentFactory; 21 import org.dom4j.Element; 22 import org.dom4j.Namespace; 23 import org.dom4j.QName; 24 import org.dom4j.io.SAXReader; 25 import org.dom4j.util.AttributeHelper; 26 27 import org.relaxng.datatype.DatatypeException; 28 import org.relaxng.datatype.ValidationContext; 29 30 import org.xml.sax.EntityResolver ; 31 import org.xml.sax.InputSource ; 32 33 42 public class SchemaParser { 43 private static final Namespace XSD_NAMESPACE = Namespace.get("xsd", 44 "http://www.w3.org/2001/XMLSchema"); 45 46 private static final QName XSD_ELEMENT = QName 48 .get("element", XSD_NAMESPACE); 49 50 private static final QName XSD_ATTRIBUTE = QName.get("attribute", 51 XSD_NAMESPACE); 52 53 private static final QName XSD_SIMPLETYPE = QName.get("simpleType", 54 XSD_NAMESPACE); 55 56 private static final QName XSD_COMPLEXTYPE = QName.get("complexType", 57 XSD_NAMESPACE); 58 59 private static final QName XSD_RESTRICTION = QName.get("restriction", 60 XSD_NAMESPACE); 61 62 private static final QName XSD_SEQUENCE = QName.get("sequence", 63 XSD_NAMESPACE); 64 65 private static final QName XSD_CHOICE = QName.get("choice", XSD_NAMESPACE); 66 67 private static final QName XSD_ALL = QName.get("all", XSD_NAMESPACE); 68 69 private static final QName XSD_INCLUDE = QName 70 .get("include", XSD_NAMESPACE); 71 72 73 private DatatypeDocumentFactory documentFactory; 74 75 79 private Map dataTypeCache = new HashMap (); 80 81 82 private NamedTypeResolver namedTypeResolver; 83 84 85 private Namespace targetNamespace; 86 87 public SchemaParser() { 88 this(DatatypeDocumentFactory.singleton); 89 } 90 91 public SchemaParser(DatatypeDocumentFactory documentFactory) { 92 this.documentFactory = documentFactory; 93 this.namedTypeResolver = new NamedTypeResolver(documentFactory); 94 } 95 96 102 public void build(Document schemaDocument) { 103 this.targetNamespace = null; 104 internalBuild(schemaDocument); 105 } 106 107 public void build(Document schemaDocument, Namespace namespace) { 108 this.targetNamespace = namespace; 109 internalBuild(schemaDocument); 110 } 111 112 private synchronized void internalBuild(Document schemaDocument) { 113 Element root = schemaDocument.getRootElement(); 114 115 if (root != null) { 116 Iterator includeIter = root.elementIterator(XSD_INCLUDE); 118 119 while (includeIter.hasNext()) { 120 Element includeElement = (Element) includeIter.next(); 121 String inclSchemaInstanceURI = includeElement 122 .attributeValue("schemaLocation"); 123 EntityResolver resolver = schemaDocument.getEntityResolver(); 124 125 try { 126 if (resolver == null) { 127 String msg = "No EntityResolver available"; 128 throw new InvalidSchemaException(msg); 129 } 130 131 InputSource inputSource = resolver.resolveEntity(null, 132 inclSchemaInstanceURI); 133 134 if (inputSource == null) { 135 String msg = "Could not resolve the schema URI: " 136 + inclSchemaInstanceURI; 137 throw new InvalidSchemaException(msg); 138 } 139 140 SAXReader reader = new SAXReader(); 141 Document inclSchemaDocument = reader.read(inputSource); 142 build(inclSchemaDocument); 143 } catch (Exception e) { 144 System.out.println("Failed to load schema: " 145 + inclSchemaInstanceURI); 146 System.out.println("Caught: " + e); 147 e.printStackTrace(); 148 throw new InvalidSchemaException("Failed to load schema: " 149 + inclSchemaInstanceURI); 150 } 151 } 152 153 Iterator iter = root.elementIterator(XSD_ELEMENT); 155 156 while (iter.hasNext()) { 157 onDatatypeElement((Element) iter.next(), documentFactory); 158 } 159 160 iter = root.elementIterator(XSD_SIMPLETYPE); 162 163 while (iter.hasNext()) { 164 onNamedSchemaSimpleType((Element) iter.next()); 165 } 166 167 iter = root.elementIterator(XSD_COMPLEXTYPE); 169 170 while (iter.hasNext()) { 171 onNamedSchemaComplexType((Element) iter.next()); 172 } 173 174 namedTypeResolver.resolveNamedTypes(); 175 } 176 } 177 178 181 189 private void onDatatypeElement(Element xsdElement, 190 DocumentFactory parentFactory) { 191 String name = xsdElement.attributeValue("name"); 192 String type = xsdElement.attributeValue("type"); 193 QName qname = getQName(name); 194 195 DatatypeElementFactory factory = getDatatypeElementFactory(qname); 196 197 if (type != null) { 198 XSDatatype dataType = getTypeByName(type); 200 201 if (dataType != null) { 202 factory.setChildElementXSDatatype(qname, dataType); 203 } else { 204 QName typeQName = getQName(type); 205 namedTypeResolver.registerTypedElement(xsdElement, typeQName, 206 parentFactory); 207 } 208 209 return; 210 } 211 212 Element xsdSimpleType = xsdElement.element(XSD_SIMPLETYPE); 214 215 if (xsdSimpleType != null) { 216 XSDatatype dataType = loadXSDatatypeFromSimpleType(xsdSimpleType); 217 218 if (dataType != null) { 219 factory.setChildElementXSDatatype(qname, dataType); 220 } 221 } 222 223 Element schemaComplexType = xsdElement.element(XSD_COMPLEXTYPE); 224 225 if (schemaComplexType != null) { 226 onSchemaComplexType(schemaComplexType, factory); 227 } 228 229 Iterator iter = xsdElement.elementIterator(XSD_ATTRIBUTE); 230 231 if (iter.hasNext()) { 232 do { 233 onDatatypeAttribute(xsdElement, factory, (Element) iter 234 .next()); 235 } while (iter.hasNext()); 236 } 237 } 238 239 245 private void onNamedSchemaComplexType(Element schemaComplexType) { 246 Attribute nameAttr = schemaComplexType.attribute("name"); 247 248 if (nameAttr == null) { 249 return; 250 } 251 252 String name = nameAttr.getText(); 253 QName qname = getQName(name); 254 255 DatatypeElementFactory factory = getDatatypeElementFactory(qname); 256 257 onSchemaComplexType(schemaComplexType, factory); 258 namedTypeResolver.registerComplexType(qname, factory); 259 } 260 261 269 private void onSchemaComplexType(Element schemaComplexType, 270 DatatypeElementFactory elementFactory) { 271 Iterator iter = schemaComplexType.elementIterator(XSD_ATTRIBUTE); 272 273 while (iter.hasNext()) { 274 Element xsdAttribute = (Element) iter.next(); 275 String name = xsdAttribute.attributeValue("name"); 276 QName qname = getQName(name); 277 278 XSDatatype dataType = dataTypeForXsdAttribute(xsdAttribute); 279 280 if (dataType != null) { 281 elementFactory.setAttributeXSDatatype(qname, dataType); 285 } 286 } 287 288 Element schemaSequence = schemaComplexType.element(XSD_SEQUENCE); 290 291 if (schemaSequence != null) { 292 onChildElements(schemaSequence, elementFactory); 293 } 294 295 Element schemaChoice = schemaComplexType.element(XSD_CHOICE); 297 298 if (schemaChoice != null) { 299 onChildElements(schemaChoice, elementFactory); 300 } 301 302 Element schemaAll = schemaComplexType.element(XSD_ALL); 304 305 if (schemaAll != null) { 306 onChildElements(schemaAll, elementFactory); 307 } 308 } 309 310 private void onChildElements(Element element, DatatypeElementFactory fact) { 311 Iterator iter = element.elementIterator(XSD_ELEMENT); 312 313 while (iter.hasNext()) { 314 Element xsdElement = (Element) iter.next(); 315 onDatatypeElement(xsdElement, fact); 316 } 317 } 318 319 329 private void onDatatypeAttribute(Element xsdElement, 330 DatatypeElementFactory elementFactory, Element xsdAttribute) { 331 String name = xsdAttribute.attributeValue("name"); 332 QName qname = getQName(name); 333 XSDatatype dataType = dataTypeForXsdAttribute(xsdAttribute); 334 335 if (dataType != null) { 336 elementFactory.setAttributeXSDatatype(qname, dataType); 338 } else { 339 String type = xsdAttribute.attributeValue("type"); 340 System.out.println("Warning: Couldn't find XSDatatype for type: " 341 + type + " attribute: " + name); 342 } 343 } 344 345 356 private XSDatatype dataTypeForXsdAttribute(Element xsdAttribute) { 357 String type = xsdAttribute.attributeValue("type"); 358 XSDatatype dataType = null; 359 360 if (type != null) { 361 dataType = getTypeByName(type); 362 } else { 363 Element xsdSimpleType = xsdAttribute.element(XSD_SIMPLETYPE); 365 366 if (xsdSimpleType == null) { 367 String name = xsdAttribute.attributeValue("name"); 368 String msg = "The attribute: " + name 369 + " has no type attribute and does not contain a " 370 + "<simpleType/> element"; 371 throw new InvalidSchemaException(msg); 372 } 373 374 dataType = loadXSDatatypeFromSimpleType(xsdSimpleType); 375 } 376 377 return dataType; 378 } 379 380 386 private void onNamedSchemaSimpleType(Element schemaSimpleType) { 387 Attribute nameAttr = schemaSimpleType.attribute("name"); 388 389 if (nameAttr == null) { 390 return; 391 } 392 393 String name = nameAttr.getText(); 394 QName qname = getQName(name); 395 XSDatatype datatype = loadXSDatatypeFromSimpleType(schemaSimpleType); 396 namedTypeResolver.registerSimpleType(qname, datatype); 397 } 398 399 408 private XSDatatype loadXSDatatypeFromSimpleType(Element xsdSimpleType) { 409 Element xsdRestriction = xsdSimpleType.element(XSD_RESTRICTION); 410 411 if (xsdRestriction != null) { 412 String base = xsdRestriction.attributeValue("base"); 413 414 if (base != null) { 415 XSDatatype baseType = getTypeByName(base); 416 417 if (baseType == null) { 418 onSchemaError("Invalid base type: " + base 419 + " when trying to build restriction: " 420 + xsdRestriction); 421 } else { 422 return deriveSimpleType(baseType, xsdRestriction); 423 } 424 } else { 425 Element xsdSubType = xsdSimpleType.element(XSD_SIMPLETYPE); 428 429 if (xsdSubType == null) { 430 String msg = "The simpleType element: " + xsdSimpleType 431 + " must contain a base attribute or simpleType" 432 + " element"; 433 onSchemaError(msg); 434 } else { 435 return loadXSDatatypeFromSimpleType(xsdSubType); 436 } 437 } 438 } else { 439 onSchemaError("No <restriction>. Could not create XSDatatype for" 440 + " simpleType: " + xsdSimpleType); 441 } 442 443 return null; 444 } 445 446 456 private XSDatatype deriveSimpleType(XSDatatype baseType, 457 Element xsdRestriction) { 458 TypeIncubator incubator = new TypeIncubator(baseType); 459 ValidationContext context = null; 460 461 try { 462 for (Iterator iter = xsdRestriction.elementIterator(); iter 463 .hasNext();) { 464 Element element = (Element) iter.next(); 465 String name = element.getName(); 466 String value = element.attributeValue("value"); 467 boolean fixed = AttributeHelper.booleanValue(element, "fixed"); 468 469 incubator.addFacet(name, value, fixed, context); 471 } 472 473 String newTypeName = null; 475 476 return incubator.derive("", newTypeName); 477 } catch (DatatypeException e) { 478 onSchemaError("Invalid restriction: " + e.getMessage() 479 + " when trying to build restriction: " + xsdRestriction); 480 481 return null; 482 } 483 } 484 485 494 private DatatypeElementFactory getDatatypeElementFactory(QName name) { 495 DatatypeElementFactory factory = documentFactory 496 .getElementFactory(name); 497 498 if (factory == null) { 499 factory = new DatatypeElementFactory(name); 500 name.setDocumentFactory(factory); 501 } 502 503 return factory; 504 } 505 506 private XSDatatype getTypeByName(String type) { 507 XSDatatype dataType = (XSDatatype) dataTypeCache.get(type); 508 509 if (dataType == null) { 510 int idx = type.indexOf(':'); 513 514 if (idx >= 0) { 515 String localName = type.substring(idx + 1); 516 517 try { 518 dataType = DatatypeFactory.getTypeByName(localName); 519 } catch (DatatypeException e) { 520 } 521 } 522 523 if (dataType == null) { 524 try { 525 dataType = DatatypeFactory.getTypeByName(type); 526 } catch (DatatypeException e) { 527 } 528 } 529 530 if (dataType == null) { 531 QName typeQName = getQName(type); 533 dataType = (XSDatatype) namedTypeResolver.simpleTypeMap 534 .get(typeQName); 535 } 536 537 if (dataType != null) { 538 dataTypeCache.put(type, dataType); 540 } 541 } 542 543 return dataType; 544 } 545 546 private QName getQName(String name) { 547 if (targetNamespace == null) { 548 return documentFactory.createQName(name); 549 } else { 550 return documentFactory.createQName(name, targetNamespace); 551 } 552 } 553 554 564 private void onSchemaError(String message) { 565 throw new InvalidSchemaException(message); 569 } 570 } 571 572 608 | Popular Tags |