/** | |
* Licensed to the Apache Software Foundation (ASF) under one | |
* or more contributor license agreements. See the NOTICE file | |
* distributed with this work for additional information | |
* regarding copyright ownership. The ASF licenses this file | |
* to you under the Apache License, Version 2.0 (the | |
* "License"); you may not use this file except in compliance | |
* with the License. You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, | |
* software distributed under the License is distributed on an | |
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
* KIND, either express or implied. See the License for the | |
* specific language governing permissions and limitations | |
* under the License. | |
*/ | |
package org.apache.ws.commons.schema; | |
import java.lang.ref.SoftReference; | |
import java.util.ArrayList; | |
import java.util.Collections; | |
import java.util.HashMap; | |
import java.util.HashSet; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.Set; | |
import java.util.StringTokenizer; | |
import java.util.Vector; | |
import javax.xml.namespace.NamespaceContext; | |
import javax.xml.namespace.QName; | |
import javax.xml.parsers.DocumentBuilderFactory; | |
import org.w3c.dom.Attr; | |
import org.w3c.dom.Document; | |
import org.w3c.dom.Element; | |
import org.w3c.dom.NamedNodeMap; | |
import org.w3c.dom.Node; | |
import org.w3c.dom.NodeList; | |
import org.xml.sax.InputSource; | |
import org.apache.ws.commons.schema.XmlSchemaCollection.SchemaKey; | |
import org.apache.ws.commons.schema.constants.Constants; | |
import org.apache.ws.commons.schema.extensions.ExtensionRegistry; | |
import org.apache.ws.commons.schema.utils.NodeNamespaceContext; | |
import org.apache.ws.commons.schema.utils.TargetNamespaceValidator; | |
import org.apache.ws.commons.schema.utils.XDOMUtil; | |
/** | |
* Object used to build a schema from a schema document. This object includes a cache of previously resolved | |
* schema documents. This cache might be useful when an application has multiple webservices that each have | |
* WSDL documents that import the same schema, for example. On app startup, we may wish to cache XmlSchema | |
* objects so we don't build up the schema graph multiple times. key - use a combination of thread id and all | |
* three parameters passed to resolveXmlSchema to give minimal thread safety value - XmlSchema object wrapped | |
* in a SoftReference to encourage GC in low memory situations. CAUTION: XmlSchema objects are not likely to | |
* be thread-safe. This cache should only be used, then cleared, by callers aware of its existence. It is VERY | |
* important that users of this cache call clearCache() after they are done. Usage of the cache is controlled | |
* by calling initCache() which will initialize resolvedSchemas to non-null. Clearing of cache is done by | |
* calling clearCache() which will clear and nullify resolvedSchemas | |
*/ | |
public class SchemaBuilder { | |
// default access for unit tests. | |
static ThreadLocal<Map<String, SoftReference<XmlSchema>>> resolvedSchemas = | |
new ThreadLocal<Map<String, SoftReference<XmlSchema>>>(); | |
private static final Set<String> RESERVED_ATTRIBUTES = new HashSet<String>(); | |
private static final String[] RESERVED_ATTRIBUTES_LIST = { | |
"name", "type", "default", "fixed", "form", "id", "use", "ref" | |
}; | |
XmlSchemaCollection collection; | |
Document currentDocument; | |
XmlSchema currentSchema; | |
DocumentBuilderFactory docFac; | |
private final TargetNamespaceValidator currentValidator; | |
/** | |
* The extension registry to be used while building the schema model | |
*/ | |
private ExtensionRegistry extReg; | |
static { | |
for (String s : RESERVED_ATTRIBUTES_LIST) { | |
RESERVED_ATTRIBUTES.add(s); | |
} | |
} | |
/** | |
* Schema builder constructor | |
* | |
* @param collection | |
* @param validator | |
*/ | |
SchemaBuilder(XmlSchemaCollection collection, TargetNamespaceValidator validator) { | |
this.collection = collection; | |
this.currentValidator = validator; | |
if (collection.getExtReg() != null) { | |
this.extReg = collection.getExtReg(); | |
} | |
currentSchema = new XmlSchema(); | |
} | |
/** | |
* Remove any entries from the cache for the current thread. Entries for other threads are not altered. | |
*/ | |
public static void clearCache() { | |
Map<String, SoftReference<XmlSchema>> threadResolvedSchemas = resolvedSchemas.get(); | |
if (threadResolvedSchemas != null) { | |
// goose the gc a bit. | |
threadResolvedSchemas.clear(); | |
resolvedSchemas.remove(); | |
} | |
} | |
/** | |
* Setup the cache to be used by the current thread of execution. Multiple threads can use the cache, and | |
* each one must call this method at some point prior to attempting to resolve the first schema, or the | |
* cache will not be used on that thread. IMPORTANT: The thread MUST call clearCache() when it is done | |
* with the schemas or a large amount of memory may remain in-use. | |
*/ | |
public static void initCache() { | |
Map<String, SoftReference<XmlSchema>> threadResolvedSchemas = resolvedSchemas.get(); | |
// If there is no entry yet for this thread ID, then create one | |
if (threadResolvedSchemas == null) { | |
threadResolvedSchemas = | |
Collections.synchronizedMap(new HashMap<String, SoftReference<XmlSchema>>()); | |
resolvedSchemas.set(threadResolvedSchemas); | |
} | |
} | |
public ExtensionRegistry getExtReg() { | |
return extReg; | |
} | |
public void setExtReg(ExtensionRegistry extReg) { | |
this.extReg = extReg; | |
} | |
/** | |
* build method taking in a document and a uri | |
* | |
* @param doc | |
* @param uri | |
*/ | |
XmlSchema build(Document doc, String uri) { | |
Element schemaEl = doc.getDocumentElement(); | |
XmlSchema xmlSchema = handleXmlSchemaElement(schemaEl, uri); | |
xmlSchema.setInputEncoding(doc.getInputEncoding()); | |
return xmlSchema; | |
} | |
XmlSchemaDerivationMethod getDerivation(Element el, String attrName) { | |
if (el.hasAttribute(attrName) && !el.getAttribute(attrName).equals("")) { | |
// #all | List of (extension | restriction | substitution) | |
String derivationMethod = el.getAttribute(attrName).trim(); | |
return XmlSchemaDerivationMethod.schemaValueOf(derivationMethod); | |
} | |
return XmlSchemaDerivationMethod.NONE; | |
} | |
String getEnumString(Element el, String attrName) { | |
if (el.hasAttribute(attrName)) { | |
return el.getAttribute(attrName).trim(); | |
} | |
return "none"; // local convention for empty value. | |
} | |
XmlSchemaForm getFormDefault(Element el, String attrName) { | |
if (el.getAttributeNode(attrName) != null) { | |
String value = el.getAttribute(attrName); | |
return XmlSchemaForm.schemaValueOf(value); | |
} else { | |
return XmlSchemaForm.UNQUALIFIED; | |
} | |
} | |
long getMaxOccurs(Element el) { | |
try { | |
if (el.getAttributeNode("maxOccurs") != null) { | |
String value = el.getAttribute("maxOccurs"); | |
if ("unbounded".equals(value)) { | |
return Long.MAX_VALUE; | |
} else { | |
return Long.parseLong(value); | |
} | |
} | |
return 1; | |
} catch (java.lang.NumberFormatException e) { | |
return 1; | |
} | |
} | |
long getMinOccurs(Element el) { | |
try { | |
if (el.getAttributeNode("minOccurs") != null) { | |
String value = el.getAttribute("minOccurs"); | |
if ("unbounded".equals(value)) { | |
return Long.MAX_VALUE; | |
} else { | |
return Long.parseLong(value); | |
} | |
} | |
return 1; | |
} catch (java.lang.NumberFormatException e) { | |
return 1; | |
} | |
} | |
/** | |
* Handles the annotation Traversing if encounter appinfo or documentation add it to annotation collection | |
*/ | |
XmlSchemaAnnotation handleAnnotation(Element annotEl) { | |
XmlSchemaAnnotation annotation = new XmlSchemaAnnotation(); | |
List<XmlSchemaAnnotationItem> content = annotation.getItems(); | |
XmlSchemaAppInfo appInfoObj; | |
XmlSchemaDocumentation docsObj; | |
for (Element appinfo = XDOMUtil.getFirstChildElementNS(annotEl, XmlSchema.SCHEMA_NS, "appinfo"); | |
appinfo != null; | |
appinfo = XDOMUtil.getNextSiblingElementNS(appinfo, XmlSchema.SCHEMA_NS, "appinfo")) { | |
appInfoObj = handleAppInfo(appinfo); | |
if (appInfoObj != null) { | |
content.add(appInfoObj); | |
} | |
} | |
for (Element documentation = XDOMUtil.getFirstChildElementNS(annotEl, | |
XmlSchema.SCHEMA_NS, "documentation"); | |
documentation != null; | |
documentation = XDOMUtil.getNextSiblingElementNS(documentation, XmlSchema.SCHEMA_NS, | |
"documentation")) { | |
docsObj = handleDocumentation(documentation); | |
if (docsObj != null) { | |
content.add(docsObj); | |
} | |
} | |
// process extra attributes and elements | |
processExtensibilityComponents(annotation, annotEl, true); | |
return annotation; | |
} | |
/** | |
* create new XmlSchemaAppinfo and add value gotten from element to this obj | |
* | |
* @param content | |
*/ | |
XmlSchemaAppInfo handleAppInfo(Element content) { | |
XmlSchemaAppInfo appInfo = new XmlSchemaAppInfo(); | |
NodeList markup = new DocumentFragmentNodeList(content); | |
if (!content.hasAttribute("source") && markup.getLength() == 0) { | |
return null; | |
} | |
appInfo.setSource(getAttribute(content, "source")); | |
appInfo.setMarkup(markup); | |
return appInfo; | |
} | |
/** | |
* Handle complex types | |
* | |
* @param schema | |
* @param complexEl | |
* @param schemaEl | |
* @param topLevel | |
*/ | |
XmlSchemaComplexType handleComplexType(XmlSchema schema, Element complexEl, Element schemaEl, | |
boolean topLevel) { | |
XmlSchemaComplexType ct = new XmlSchemaComplexType(schema, topLevel); | |
if (complexEl.hasAttribute("name")) { | |
// String namespace = (schema.targetNamespace==null)? | |
// "":schema.targetNamespace; | |
ct.setName(complexEl.getAttribute("name")); | |
} | |
for (Element el = XDOMUtil.getFirstChildElementNS(complexEl, XmlSchema.SCHEMA_NS); | |
el != null; | |
el = XDOMUtil.getNextSiblingElementNS(el, XmlSchema.SCHEMA_NS)) { | |
// String elPrefix = el.getPrefix() == null ? "" : | |
// el.getPrefix(); | |
// if(elPrefix.equals(schema.schema_ns_prefix)) { | |
if (el.getLocalName().equals("sequence")) { | |
ct.setParticle(handleSequence(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("choice")) { | |
ct.setParticle(handleChoice(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("all")) { | |
ct.setParticle(handleAll(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("attribute")) { | |
ct.getAttributes().add(handleAttribute(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("attributeGroup")) { | |
ct.getAttributes().add(handleAttributeGroupRef(schema, el)); | |
} else if (el.getLocalName().equals("group")) { | |
XmlSchemaGroupRef group = handleGroupRef(schema, el, schemaEl); | |
if (group.getParticle() == null) { | |
ct.setParticle(group); | |
} else { | |
ct.setParticle(group.getParticle()); | |
} | |
} else if (el.getLocalName().equals("simpleContent")) { | |
ct.setContentModel(handleSimpleContent(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("complexContent")) { | |
ct.setContentModel(handleComplexContent(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("annotation")) { | |
ct.setAnnotation(handleAnnotation(el)); | |
} else if (el.getLocalName().equals("anyAttribute")) { | |
ct.setAnyAttribute(handleAnyAttribute(schema, el, schemaEl)); | |
} | |
// } | |
} | |
if (complexEl.hasAttribute("block")) { | |
String blockStr = complexEl.getAttribute("block"); | |
ct.setBlock(XmlSchemaDerivationMethod.schemaValueOf(blockStr)); | |
// ct.setBlock(new XmlSchemaDerivationMethod(block)); | |
} | |
if (complexEl.hasAttribute("final")) { | |
String finalstr = complexEl.getAttribute("final"); | |
ct.setFinal(XmlSchemaDerivationMethod.schemaValueOf(finalstr)); | |
} | |
if (complexEl.hasAttribute("abstract")) { | |
String abs = complexEl.getAttribute("abstract"); | |
if (abs.equalsIgnoreCase("true")) { | |
ct.setAbstract(true); | |
} else { | |
ct.setAbstract(false); | |
} | |
} | |
if (complexEl.hasAttribute("mixed")) { | |
String mixed = complexEl.getAttribute("mixed"); | |
if (mixed.equalsIgnoreCase("true")) { | |
ct.setMixed(true); | |
} else { | |
ct.setMixed(false); | |
} | |
} | |
// process extra attributes and elements | |
processExtensibilityComponents(ct, complexEl, true); | |
return ct; | |
} | |
// iterate each documentation element, create new XmlSchemaAppinfo and add | |
// to collection | |
XmlSchemaDocumentation handleDocumentation(Element content) { | |
XmlSchemaDocumentation documentation = new XmlSchemaDocumentation(); | |
List<Node> markup = getChildren(content); | |
if (!content.hasAttribute("source") && !content.hasAttribute("xml:lang") && markup == null) { | |
return null; | |
} | |
documentation.setSource(getAttribute(content, "source")); | |
documentation.setLanguage(getAttribute(content, "xml:lang")); | |
documentation.setMarkup(new DocumentFragmentNodeList(content)); | |
return documentation; | |
} | |
/* | |
* handle_complex_content_restriction | |
*/ | |
/** | |
* handle elements | |
* | |
* @param schema | |
* @param el | |
* @param schemaEl | |
* @param isGlobal | |
*/ | |
XmlSchemaElement handleElement(XmlSchema schema, Element el, Element schemaEl, boolean isGlobal) { | |
XmlSchemaElement element = new XmlSchemaElement(schema, isGlobal); | |
if (el.getAttributeNode("name") != null) { | |
element.setName(el.getAttribute("name")); | |
} | |
// String namespace = (schema.targetNamespace==null)? | |
// "" : schema.targetNamespace; | |
boolean isQualified = schema.getElementFormDefault() == XmlSchemaForm.QUALIFIED; | |
isQualified = handleElementForm(el, element, isQualified); | |
handleElementName(isGlobal, element, isQualified); | |
handleElementAnnotation(el, element); | |
handleElementGlobalType(el, element); | |
Element simpleTypeEl; | |
Element complexTypeEl; | |
Element keyEl; | |
Element keyrefEl; | |
Element uniqueEl; | |
simpleTypeEl = XDOMUtil.getFirstChildElementNS(el, XmlSchema.SCHEMA_NS, "simpleType"); | |
if (simpleTypeEl != null) { | |
XmlSchemaSimpleType simpleType = handleSimpleType(schema, simpleTypeEl, schemaEl, false); | |
element.setSchemaType(simpleType); | |
element.setSchemaTypeName(simpleType.getQName()); | |
} else { | |
complexTypeEl = XDOMUtil.getFirstChildElementNS(el, XmlSchema.SCHEMA_NS, "complexType"); | |
if (complexTypeEl != null) { | |
element.setSchemaType(handleComplexType(schema, complexTypeEl, schemaEl, false)); | |
} | |
} | |
keyEl = XDOMUtil.getFirstChildElementNS(el, XmlSchema.SCHEMA_NS, "key"); | |
if (keyEl != null) { | |
while (keyEl != null) { | |
element.getConstraints().add(handleConstraint(keyEl, XmlSchemaKey.class)); | |
keyEl = XDOMUtil.getNextSiblingElementNS(keyEl, XmlSchema.SCHEMA_NS, "key"); | |
} | |
} | |
keyrefEl = XDOMUtil.getFirstChildElementNS(el, XmlSchema.SCHEMA_NS, "keyref"); | |
if (keyrefEl != null) { | |
while (keyrefEl != null) { | |
XmlSchemaKeyref keyRef = (XmlSchemaKeyref)handleConstraint(keyrefEl, XmlSchemaKeyref.class); | |
if (keyrefEl.hasAttribute("refer")) { | |
String name = keyrefEl.getAttribute("refer"); | |
keyRef.refer = getRefQName(name, el); | |
} | |
element.getConstraints().add(keyRef); | |
keyrefEl = XDOMUtil.getNextSiblingElementNS(keyrefEl, XmlSchema.SCHEMA_NS, "keyref"); | |
} | |
} | |
uniqueEl = XDOMUtil.getFirstChildElementNS(el, XmlSchema.SCHEMA_NS, "unique"); | |
if (uniqueEl != null) { | |
while (uniqueEl != null) { | |
element.getConstraints().add(handleConstraint(uniqueEl, XmlSchemaUnique.class)); | |
uniqueEl = XDOMUtil.getNextSiblingElementNS(uniqueEl, XmlSchema.SCHEMA_NS, "unique"); | |
} | |
} | |
if (el.hasAttribute("abstract")) { | |
element.setAbstractElement(Boolean.valueOf(el.getAttribute("abstract")).booleanValue()); | |
} | |
if (el.hasAttribute("block")) { | |
element.setBlock(getDerivation(el, "block")); | |
} | |
if (el.hasAttribute("default")) { | |
element.setDefaultValue(el.getAttribute("default")); | |
} | |
if (el.hasAttribute("final")) { | |
element.setFinalDerivation(getDerivation(el, "final")); | |
} | |
if (el.hasAttribute("fixed")) { | |
element.setFixedValue(el.getAttribute("fixed")); | |
} | |
if (el.hasAttribute("id")) { | |
element.setId(el.getAttribute("id")); | |
} | |
if (el.hasAttribute("nillable")) { | |
element.setNillable(Boolean.valueOf(el.getAttribute("nillable")).booleanValue()); | |
} | |
if (el.hasAttribute("substitutionGroup")) { | |
String substitutionGroup = el.getAttribute("substitutionGroup"); | |
element.setSubstitutionGroup(getRefQName(substitutionGroup, el)); | |
} | |
element.setMinOccurs(getMinOccurs(el)); | |
element.setMaxOccurs(getMaxOccurs(el)); | |
// process extra attributes and elements | |
processExtensibilityComponents(element, el, true); | |
return element; | |
} | |
/** | |
* Handle the import | |
* | |
* @param schema | |
* @param importEl | |
* @param schemaEl | |
* @return XmlSchemaObject | |
*/ | |
XmlSchemaImport handleImport(XmlSchema schema, Element importEl, Element schemaEl) { | |
XmlSchemaImport schemaImport = new XmlSchemaImport(schema); | |
Element annotationEl = XDOMUtil.getFirstChildElementNS(importEl, XmlSchema.SCHEMA_NS, "annotation"); | |
if (annotationEl != null) { | |
XmlSchemaAnnotation importAnnotation = handleAnnotation(annotationEl); | |
schemaImport.setAnnotation(importAnnotation); | |
} | |
schemaImport.namespace = importEl.getAttribute("namespace"); | |
final String uri = schemaImport.namespace; | |
schemaImport.schemaLocation = importEl.getAttribute("schemaLocation"); | |
TargetNamespaceValidator validator = new TargetNamespaceValidator() { | |
public void validate(XmlSchema pSchema) { | |
final boolean valid; | |
if (isEmpty(uri)) { | |
valid = isEmpty(pSchema.getSyntacticalTargetNamespace()); | |
} else { | |
valid = pSchema.getSyntacticalTargetNamespace().equals(uri); | |
} | |
if (!valid) { | |
throw new XmlSchemaException("An imported schema was announced to have the namespace " | |
+ uri + ", but has the namespace " | |
+ pSchema.getSyntacticalTargetNamespace()); | |
} | |
} | |
private boolean isEmpty(String pValue) { | |
return pValue == null || Constants.NULL_NS_URI.equals(pValue); | |
} | |
}; | |
if (schema.getSourceURI() != null) { | |
schemaImport.schema = | |
resolveXmlSchema(uri, schemaImport.schemaLocation, schema.getSourceURI(), validator); | |
} else { | |
schemaImport.schema = | |
resolveXmlSchema(schemaImport.namespace, schemaImport.schemaLocation, validator); | |
} | |
return schemaImport; | |
} | |
/** | |
* Handles the include | |
* | |
* @param schema | |
* @param includeEl | |
* @param schemaEl | |
*/ | |
XmlSchemaInclude handleInclude(final XmlSchema schema, Element includeEl, Element schemaEl) { | |
XmlSchemaInclude include = new XmlSchemaInclude(schema); | |
Element annotationEl = XDOMUtil.getFirstChildElementNS(includeEl, XmlSchema.SCHEMA_NS, "annotation"); | |
if (annotationEl != null) { | |
XmlSchemaAnnotation includeAnnotation = handleAnnotation(annotationEl); | |
include.setAnnotation(includeAnnotation); | |
} | |
include.schemaLocation = includeEl.getAttribute("schemaLocation"); | |
// includes are not supposed to have a target namespace | |
// we should be passing in a null in place of the target | |
// namespace | |
final TargetNamespaceValidator validator = newIncludeValidator(schema); | |
if (schema.getSourceURI() != null) { | |
include.schema = | |
resolveXmlSchema(schema.getLogicalTargetNamespace(), include.schemaLocation, | |
schema.getSourceURI(), validator); | |
} else { | |
include.schema = | |
resolveXmlSchema(schema.getLogicalTargetNamespace(), include.schemaLocation, validator); | |
} | |
// process extra attributes and elements | |
processExtensibilityComponents(include, includeEl, true); | |
return include; | |
} | |
/** | |
* Handles simple types | |
* | |
* @param schema | |
* @param simpleEl | |
* @param schemaEl | |
*/ | |
XmlSchemaSimpleType handleSimpleType(XmlSchema schema, Element simpleEl, Element schemaEl, | |
boolean topLevel) { | |
XmlSchemaSimpleType simpleType = new XmlSchemaSimpleType(schema, topLevel); | |
if (simpleEl.hasAttribute("name")) { | |
simpleType.setName(simpleEl.getAttribute("name")); | |
} | |
handleSimpleTypeFinal(simpleEl, simpleType); | |
Element simpleTypeAnnotationEl = | |
XDOMUtil.getFirstChildElementNS(simpleEl, XmlSchema.SCHEMA_NS, "annotation"); | |
if (simpleTypeAnnotationEl != null) { | |
XmlSchemaAnnotation simpleTypeAnnotation = handleAnnotation(simpleTypeAnnotationEl); | |
simpleType.setAnnotation(simpleTypeAnnotation); | |
} | |
Element unionEl; | |
Element listEl; | |
Element restrictionEl; | |
restrictionEl = XDOMUtil.getFirstChildElementNS(simpleEl, XmlSchema.SCHEMA_NS, "restriction"); | |
listEl = XDOMUtil.getFirstChildElementNS(simpleEl, XmlSchema.SCHEMA_NS, "list"); | |
unionEl = XDOMUtil.getFirstChildElementNS(simpleEl, XmlSchema.SCHEMA_NS, "union"); | |
if (restrictionEl != null) { | |
handleSimpleTypeRestriction(schema, schemaEl, simpleType, restrictionEl); | |
} else if (listEl != null) { | |
handleSimpleTypeList(schema, schemaEl, simpleType, listEl); | |
} else if (unionEl != null) { | |
handleSimpleTypeUnion(schema, schemaEl, simpleType, unionEl); | |
} | |
// process extra attributes and elements | |
processExtensibilityComponents(simpleType, simpleEl, true); | |
return simpleType; | |
} | |
/** | |
* handles the schema element | |
* | |
* @param schemaEl | |
* @param systemId | |
*/ | |
XmlSchema handleXmlSchemaElement(Element schemaEl, String systemId) { | |
// get all the attributes along with the namespace declns | |
currentSchema.setNamespaceContext(NodeNamespaceContext.getNamespaceContext(schemaEl)); | |
setNamespaceAttributes(currentSchema, schemaEl); | |
XmlSchemaCollection.SchemaKey schemaKey = | |
new XmlSchemaCollection.SchemaKey(currentSchema.getLogicalTargetNamespace(), systemId); | |
handleSchemaElementBasics(schemaEl, systemId, schemaKey); | |
Element el = XDOMUtil.getFirstChildElementNS(schemaEl, XmlSchema.SCHEMA_NS); | |
if (el == null | |
&& XDOMUtil.getFirstChildElementNS(schemaEl, "http://www.w3.org/1999/XMLSchema") != null) { | |
throw new XmlSchemaException("Schema defined using \"http://www.w3.org/1999/XMLSchema\" " | |
+ "is not supported. " + "Please update the schema to the \"" | |
+ XmlSchema.SCHEMA_NS + "\" namespace"); | |
} | |
for (; el != null; el = XDOMUtil.getNextSiblingElementNS(el, XmlSchema.SCHEMA_NS)) { | |
handleSchemaElementChild(schemaEl, el); | |
} | |
// add the extensibility components | |
processExtensibilityComponents(currentSchema, schemaEl, false); | |
return currentSchema; | |
} | |
/** | |
* Resolve the schemas | |
* | |
* @param targetNamespace | |
* @param schemaLocation | |
*/ | |
XmlSchema resolveXmlSchema(String targetNamespace, String schemaLocation, String baseUri, | |
TargetNamespaceValidator validator) { | |
if (getCachedSchema(targetNamespace, schemaLocation, baseUri) != null) { | |
return getCachedSchema(targetNamespace, schemaLocation, baseUri); | |
} | |
// use the entity resolver provided if the schema location is present | |
// null | |
if (schemaLocation != null && !"".equals(schemaLocation)) { | |
InputSource source = | |
collection.getSchemaResolver().resolveEntity(targetNamespace, schemaLocation, baseUri); | |
// the entity resolver was unable to resolve this!! | |
if (source == null) { | |
// try resolving it with the target namespace only with the | |
// known namespace map | |
return collection.getKnownSchema(targetNamespace); | |
} | |
final String systemId = source.getSystemId() == null ? schemaLocation : source.getSystemId(); | |
// Push repaired system id back into source where read sees it. | |
// It is perhaps a bad thing to patch the source, but this fixes | |
// a problem. | |
source.setSystemId(systemId); | |
final SchemaKey key = new XmlSchemaCollection.SchemaKey(targetNamespace, systemId); | |
XmlSchema schema = collection.getSchema(key); | |
if (schema != null) { | |
return schema; | |
} | |
if (collection.check(key)) { | |
collection.push(key); | |
try { | |
XmlSchema readSchema = collection.read(source, validator); | |
putCachedSchema(targetNamespace, schemaLocation, baseUri, readSchema); | |
return readSchema; | |
} finally { | |
collection.pop(); | |
} | |
} | |
} else { | |
XmlSchema schema = collection.getKnownSchema(targetNamespace); | |
if (schema != null) { | |
return schema; | |
} | |
} | |
return null; | |
} | |
/** | |
* Resolve the schemas | |
* | |
* @param targetNamespace | |
* @param schemaLocation | |
*/ | |
XmlSchema resolveXmlSchema(String targetNamespace, String schemaLocation, | |
TargetNamespaceValidator validator) { | |
return resolveXmlSchema(targetNamespace, schemaLocation, collection.baseUri, validator); | |
} | |
void setNamespaceAttributes(XmlSchema schema, Element schemaEl) { | |
// no targetnamespace found ! | |
if (schemaEl.getAttributeNode("targetNamespace") != null) { | |
String contain = schemaEl.getAttribute("targetNamespace"); | |
schema.setTargetNamespace(contain); | |
} else { | |
// do nothing here | |
} | |
if (currentValidator != null) { | |
currentValidator.validate(schema); | |
} | |
} | |
private String getAttribute(Element content, String attrName) { | |
if (content.hasAttribute(attrName)) { | |
return content.getAttribute(attrName); | |
} | |
return null; | |
} | |
/** | |
* Return a cached schema if one exists for this thread. In order for schemas to be cached the thread must | |
* have done an initCache() previously. The parameters are used to construct a key used to lookup the | |
* schema | |
* | |
* @param targetNamespace | |
* @param schemaLocation | |
* @param baseUri | |
* @return The cached schema if one exists for this thread or null. | |
*/ | |
private XmlSchema getCachedSchema(String targetNamespace, String schemaLocation, String baseUri) { | |
XmlSchema resolvedSchema = null; | |
if (resolvedSchemas != null) { // cache is initialized, use it | |
Map<String, SoftReference<XmlSchema>> threadResolvedSchemas = resolvedSchemas.get(); | |
if (threadResolvedSchemas != null) { | |
// Not being very smart about this at the moment. One could, for | |
// example, | |
// see that the schemaLocation or baseUri is the same as | |
// another, but differs | |
// only by a trailing slash. As it is now, we assume a single | |
// character difference | |
// means it's a schema that has yet to be resolved. | |
String schemaKey = targetNamespace + schemaLocation + baseUri; | |
SoftReference<XmlSchema> softref = threadResolvedSchemas.get(schemaKey); | |
if (softref != null) { | |
resolvedSchema = softref.get(); | |
} | |
} | |
} | |
return resolvedSchema; | |
} | |
private List<Node> getChildren(Element content) { | |
List<Node> result = new ArrayList<Node>(); | |
for (Node n = content.getFirstChild(); n != null; n = n.getNextSibling()) { | |
result.add(n); | |
} | |
if (result.size() == 0) { | |
return null; | |
} else { | |
return result; | |
} | |
} | |
private QName getRefQName(String pName, NamespaceContext pContext) { | |
final int offset = pName.indexOf(':'); | |
String uri; | |
final String localName; | |
final String prefix; | |
if (offset == -1) { | |
uri = pContext.getNamespaceURI(Constants.DEFAULT_NS_PREFIX); | |
if (Constants.NULL_NS_URI.equals(uri)) { | |
return new QName(Constants.NULL_NS_URI, pName); | |
} | |
localName = pName; | |
prefix = Constants.DEFAULT_NS_PREFIX; | |
} else { | |
prefix = pName.substring(0, offset); | |
uri = pContext.getNamespaceURI(prefix); | |
if (uri == null || Constants.NULL_NS_URI.equals(uri) && currentSchema.getParent() != null | |
&& currentSchema.getParent().getNamespaceContext() != null) { | |
uri = currentSchema.getParent().getNamespaceContext().getNamespaceURI(prefix); | |
} | |
if (uri == null || Constants.NULL_NS_URI.equals(uri)) { | |
throw new IllegalStateException("The prefix " + prefix + " is not bound."); | |
} | |
localName = pName.substring(offset + 1); | |
} | |
return new QName(uri, localName, prefix); | |
} | |
private QName getRefQName(String pName, Node pNode) { | |
return getRefQName(pName, NodeNamespaceContext.getNamespaceContext(pNode)); | |
} | |
private XmlSchemaAll handleAll(XmlSchema schema, Element allEl, Element schemaEl) { | |
XmlSchemaAll all = new XmlSchemaAll(); | |
// handle min and max occurences | |
all.setMinOccurs(getMinOccurs(allEl)); | |
all.setMaxOccurs(getMaxOccurs(allEl)); | |
for (Element el = XDOMUtil.getFirstChildElementNS(allEl, XmlSchema.SCHEMA_NS); | |
el != null; | |
el = XDOMUtil.getNextSiblingElementNS(el, XmlSchema.SCHEMA_NS)) { | |
if (el.getLocalName().equals("element")) { | |
XmlSchemaElement element = handleElement(schema, el, schemaEl, false); | |
all.getItems().add(element); | |
} else if (el.getLocalName().equals("annotation")) { | |
XmlSchemaAnnotation annotation = handleAnnotation(el); | |
all.setAnnotation(annotation); | |
} | |
} | |
return all; | |
} | |
private XmlSchemaAny handleAny(XmlSchema schema, Element anyEl, Element schemaEl) { | |
XmlSchemaAny any = new XmlSchemaAny(); | |
any.setTargetNamespace(schema.getLogicalTargetNamespace()); | |
if (anyEl.hasAttribute("namespace")) { | |
any.setNamespace(anyEl.getAttribute("namespace")); | |
} | |
if (anyEl.hasAttribute("processContents")) { | |
String processContent = getEnumString(anyEl, "processContents"); | |
any.setProcessContent(XmlSchemaContentProcessing.schemaValueOf(processContent)); | |
} | |
Element annotationEl = XDOMUtil.getFirstChildElementNS(anyEl, XmlSchema.SCHEMA_NS, "annotation"); | |
if (annotationEl != null) { | |
XmlSchemaAnnotation annotation = handleAnnotation(annotationEl); | |
any.setAnnotation(annotation); | |
} | |
any.setMinOccurs(getMinOccurs(anyEl)); | |
any.setMaxOccurs(getMaxOccurs(anyEl)); | |
return any; | |
} | |
/** @noinspection UnusedParameters */ | |
private XmlSchemaAnyAttribute handleAnyAttribute(XmlSchema schema, Element anyAttrEl, Element schemaEl) { | |
XmlSchemaAnyAttribute anyAttr = new XmlSchemaAnyAttribute(); | |
if (anyAttrEl.hasAttribute("namespace")) { | |
anyAttr.namespace = anyAttrEl.getAttribute("namespace"); | |
} | |
if (anyAttrEl.hasAttribute("processContents")) { | |
String contentProcessing = getEnumString(anyAttrEl, "processContents"); | |
anyAttr.processContent = XmlSchemaContentProcessing.schemaValueOf(contentProcessing); | |
} | |
if (anyAttrEl.hasAttribute("id")) { | |
anyAttr.setId(anyAttrEl.getAttribute("id")); | |
} | |
Element annotationEl = XDOMUtil.getFirstChildElementNS(anyAttrEl, XmlSchema.SCHEMA_NS, "annotation"); | |
if (annotationEl != null) { | |
XmlSchemaAnnotation annotation = handleAnnotation(annotationEl); | |
anyAttr.setAnnotation(annotation); | |
} | |
return anyAttr; | |
} | |
/** | |
* Process non-toplevel attributes | |
* | |
* @param schema | |
* @param attrEl | |
* @param schemaEl | |
* @return | |
*/ | |
private XmlSchemaAttribute handleAttribute(XmlSchema schema, Element attrEl, Element schemaEl) { | |
return handleAttribute(schema, attrEl, schemaEl, false); | |
} | |
/** | |
* Process attributes | |
* | |
* @param schema | |
* @param attrEl | |
* @param schemaEl | |
* @param topLevel | |
* @return | |
*/ | |
private XmlSchemaAttribute handleAttribute(XmlSchema schema, Element attrEl, Element schemaEl, | |
boolean topLevel) { | |
XmlSchemaAttribute attr = new XmlSchemaAttribute(schema, topLevel); | |
if (attrEl.hasAttribute("name")) { | |
String name = attrEl.getAttribute("name"); | |
attr.setName(name); | |
} | |
if (attrEl.hasAttribute("type")) { | |
String name = attrEl.getAttribute("type"); | |
attr.setSchemaTypeName(getRefQName(name, attrEl)); | |
} | |
if (attrEl.hasAttribute("default")) { | |
attr.setDefaultValue(attrEl.getAttribute("default")); | |
} | |
if (attrEl.hasAttribute("fixed")) { | |
attr.setFixedValue(attrEl.getAttribute("fixed")); | |
} | |
if (attrEl.hasAttribute("form")) { | |
String formValue = getEnumString(attrEl, "form"); | |
attr.setForm(XmlSchemaForm.schemaValueOf(formValue)); | |
} | |
if (attrEl.hasAttribute("id")) { | |
attr.setId(attrEl.getAttribute("id")); | |
} | |
if (attrEl.hasAttribute("use")) { | |
String useType = getEnumString(attrEl, "use"); | |
attr.setUse(XmlSchemaUse.schemaValueOf(useType)); | |
} | |
if (attrEl.hasAttribute("ref")) { | |
String name = attrEl.getAttribute("ref"); | |
attr.getRef().setTargetQName(getRefQName(name, attrEl)); | |
} | |
Element simpleTypeEl = XDOMUtil.getFirstChildElementNS(attrEl, XmlSchema.SCHEMA_NS, "simpleType"); | |
if (simpleTypeEl != null) { | |
attr.setSchemaType(handleSimpleType(schema, simpleTypeEl, schemaEl, false)); | |
} | |
Element annotationEl = XDOMUtil.getFirstChildElementNS(attrEl, XmlSchema.SCHEMA_NS, "annotation"); | |
if (annotationEl != null) { | |
XmlSchemaAnnotation annotation = handleAnnotation(annotationEl); | |
attr.setAnnotation(annotation); | |
} | |
NamedNodeMap attrNodes = attrEl.getAttributes(); | |
List<Attr> attrs = new ArrayList<Attr>(); | |
NodeNamespaceContext ctx = null; | |
for (int i = 0; i < attrNodes.getLength(); i++) { | |
Attr att = (Attr)attrNodes.item(i); | |
String attName = att.getName(); | |
if (!RESERVED_ATTRIBUTES.contains(attName)) { | |
attrs.add(att); | |
String value = att.getValue(); | |
if (value.indexOf(":") > -1) { | |
// there is a possibility of some namespace mapping | |
String prefix = value.substring(0, value.indexOf(":")); | |
if (ctx == null) { | |
ctx = NodeNamespaceContext.getNamespaceContext(attrEl); | |
} | |
String namespace = ctx.getNamespaceURI(prefix); | |
if (!Constants.NULL_NS_URI.equals(namespace)) { | |
Attr nsAttr = attrEl.getOwnerDocument().createAttributeNS(Constants.XMLNS_ATTRIBUTE_NS_URI, | |
"xmlns:" + prefix); | |
nsAttr.setValue(namespace); | |
attrs.add(nsAttr); | |
} | |
} | |
} | |
} | |
if (attrs.size() > 0) { | |
attr.setUnhandledAttributes(attrs.toArray(new Attr[attrs.size()])); | |
} | |
// process extra attributes and elements | |
processExtensibilityComponents(attr, attrEl, true); | |
return attr; | |
} | |
private XmlSchemaAttributeGroup handleAttributeGroup(XmlSchema schema, | |
Element groupEl, Element schemaEl) { | |
XmlSchemaAttributeGroup attrGroup = new XmlSchemaAttributeGroup(schema); | |
if (groupEl.hasAttribute("name")) { | |
attrGroup.setName(groupEl.getAttribute("name")); | |
} | |
if (groupEl.hasAttribute("id")) { | |
attrGroup.setId(groupEl.getAttribute("id")); | |
} | |
for (Element el = XDOMUtil.getFirstChildElementNS(groupEl, XmlSchema.SCHEMA_NS); | |
el != null; | |
el = XDOMUtil.getNextSiblingElementNS(el, XmlSchema.SCHEMA_NS)) { | |
if (el.getLocalName().equals("attribute")) { | |
XmlSchemaAttribute attr = handleAttribute(schema, el, schemaEl); | |
attrGroup.getAttributes().add(attr); | |
} else if (el.getLocalName().equals("attributeGroup")) { | |
XmlSchemaAttributeGroupRef attrGroupRef = handleAttributeGroupRef(schema, el); | |
attrGroup.getAttributes().add(attrGroupRef); | |
} else if (el.getLocalName().equals("anyAttribute")) { | |
attrGroup.setAnyAttribute(handleAnyAttribute(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("annotation")) { | |
XmlSchemaAnnotation ann = handleAnnotation(el); | |
attrGroup.setAnnotation(ann); | |
} | |
} | |
return attrGroup; | |
} | |
private XmlSchemaAttributeGroupRef handleAttributeGroupRef(XmlSchema schema, Element attrGroupEl) { | |
XmlSchemaAttributeGroupRef attrGroup = new XmlSchemaAttributeGroupRef(schema); | |
if (attrGroupEl.hasAttribute("ref")) { | |
String ref = attrGroupEl.getAttribute("ref"); | |
attrGroup.getRef().setTargetQName(getRefQName(ref, attrGroupEl)); | |
} | |
if (attrGroupEl.hasAttribute("id")) { | |
attrGroup.setId(attrGroupEl.getAttribute("id")); | |
} | |
Element annotationEl = | |
XDOMUtil.getFirstChildElementNS(attrGroupEl, XmlSchema.SCHEMA_NS, "annotation"); | |
if (annotationEl != null) { | |
XmlSchemaAnnotation annotation = handleAnnotation(annotationEl); | |
attrGroup.setAnnotation(annotation); | |
} | |
return attrGroup; | |
} | |
private XmlSchemaChoice handleChoice(XmlSchema schema, Element choiceEl, Element schemaEl) { | |
XmlSchemaChoice choice = new XmlSchemaChoice(); | |
if (choiceEl.hasAttribute("id")) { | |
choice.setId(choiceEl.getAttribute("id")); | |
} | |
choice.setMinOccurs(getMinOccurs(choiceEl)); | |
choice.setMaxOccurs(getMaxOccurs(choiceEl)); | |
for (Element el = XDOMUtil.getFirstChildElementNS(choiceEl, XmlSchema.SCHEMA_NS); | |
el != null; | |
el = XDOMUtil.getNextSiblingElementNS(el, XmlSchema.SCHEMA_NS)) { | |
if (el.getLocalName().equals("sequence")) { | |
XmlSchemaSequence seq = handleSequence(schema, el, schemaEl); | |
choice.getItems().add(seq); | |
} else if (el.getLocalName().equals("element")) { | |
XmlSchemaElement element = handleElement(schema, el, schemaEl, false); | |
choice.getItems().add(element); | |
} else if (el.getLocalName().equals("group")) { | |
XmlSchemaGroupRef group = handleGroupRef(schema, el, schemaEl); | |
choice.getItems().add(group); | |
} else if (el.getLocalName().equals("choice")) { | |
XmlSchemaChoice choiceItem = handleChoice(schema, el, schemaEl); | |
choice.getItems().add(choiceItem); | |
} else if (el.getLocalName().equals("any")) { | |
XmlSchemaAny any = handleAny(schema, el, schemaEl); | |
choice.getItems().add(any); | |
} else if (el.getLocalName().equals("annotation")) { | |
XmlSchemaAnnotation annotation = handleAnnotation(el); | |
choice.setAnnotation(annotation); | |
} | |
} | |
return choice; | |
} | |
private XmlSchemaComplexContent | |
handleComplexContent(XmlSchema schema, Element complexEl, Element schemaEl) { | |
XmlSchemaComplexContent complexContent = new XmlSchemaComplexContent(); | |
for (Element el = XDOMUtil.getFirstChildElementNS(complexEl, XmlSchema.SCHEMA_NS); | |
el != null; | |
el = XDOMUtil.getNextSiblingElementNS(el, XmlSchema.SCHEMA_NS)) { | |
if (el.getLocalName().equals("restriction")) { | |
complexContent.content = handleComplexContentRestriction(schema, el, schemaEl); | |
} else if (el.getLocalName().equals("extension")) { | |
complexContent.content = handleComplexContentExtension(schema, el, schemaEl); | |
} else if (el.getLocalName().equals("annotation")) { | |
complexContent.setAnnotation(handleAnnotation(el)); | |
} | |
} | |
if (complexEl.hasAttribute("mixed")) { | |
String mixed = complexEl.getAttribute("mixed"); | |
if (mixed.equalsIgnoreCase("true")) { | |
complexContent.setMixed(true); | |
} else { | |
complexContent.setMixed(false); | |
} | |
} | |
return complexContent; | |
} | |
private XmlSchemaComplexContentExtension handleComplexContentExtension(XmlSchema schema, Element extEl, | |
Element schemaEl) { | |
XmlSchemaComplexContentExtension ext = new XmlSchemaComplexContentExtension(); | |
if (extEl.hasAttribute("base")) { | |
String name = extEl.getAttribute("base"); | |
ext.setBaseTypeName(getRefQName(name, extEl)); | |
} | |
for (Element el = XDOMUtil.getFirstChildElementNS(extEl, XmlSchema.SCHEMA_NS); | |
el != null; | |
el = XDOMUtil.getNextSiblingElementNS(el, XmlSchema.SCHEMA_NS)) { | |
if (el.getLocalName().equals("sequence")) { | |
ext.setParticle(handleSequence(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("choice")) { | |
ext.setParticle(handleChoice(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("all")) { | |
ext.setParticle(handleAll(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("attribute")) { | |
ext.getAttributes().add(handleAttribute(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("attributeGroup")) { | |
ext.getAttributes().add(handleAttributeGroupRef(schema, el)); | |
} else if (el.getLocalName().equals("group")) { | |
ext.setParticle(handleGroupRef(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("anyAttribute")) { | |
ext.setAnyAttribute(handleAnyAttribute(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("annotation")) { | |
ext.setAnnotation(handleAnnotation(el)); | |
} | |
} | |
return ext; | |
} | |
private XmlSchemaComplexContentRestriction handleComplexContentRestriction(XmlSchema schema, | |
Element restrictionEl, | |
Element schemaEl) { | |
XmlSchemaComplexContentRestriction restriction = new XmlSchemaComplexContentRestriction(); | |
if (restrictionEl.hasAttribute("base")) { | |
String name = restrictionEl.getAttribute("base"); | |
restriction.setBaseTypeName(getRefQName(name, restrictionEl)); | |
} | |
for (Element el = XDOMUtil.getFirstChildElementNS(restrictionEl, XmlSchema.SCHEMA_NS); | |
el != null; | |
el = XDOMUtil.getNextSiblingElementNS(el, XmlSchema.SCHEMA_NS)) { | |
if (el.getLocalName().equals("sequence")) { | |
restriction.setParticle(handleSequence(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("choice")) { | |
restriction.setParticle(handleChoice(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("all")) { | |
restriction.setParticle(handleAll(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("attribute")) { | |
restriction.getAttributes().add(handleAttribute(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("attributeGroup")) { | |
restriction.getAttributes().add(handleAttributeGroupRef(schema, el)); | |
} else if (el.getLocalName().equals("group")) { | |
restriction.setParticle(handleGroupRef(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("anyAttribute")) { | |
restriction.setAnyAttribute(handleAnyAttribute(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("annotation")) { | |
restriction.setAnnotation(handleAnnotation(el)); | |
} | |
} | |
return restriction; | |
} | |
private XmlSchemaIdentityConstraint | |
handleConstraint(Element constraintEl, | |
Class<? extends XmlSchemaIdentityConstraint> typeClass) { | |
try { | |
XmlSchemaIdentityConstraint constraint = typeClass.newInstance(); | |
if (constraintEl.hasAttribute("name")) { | |
constraint.setName(constraintEl.getAttribute("name")); | |
} | |
if (constraintEl.hasAttribute("refer")) { | |
String name = constraintEl.getAttribute("refer"); | |
((XmlSchemaKeyref)constraint).refer = getRefQName(name, constraintEl); | |
} | |
for (Element el = XDOMUtil.getFirstChildElementNS(constraintEl, XmlSchema.SCHEMA_NS); | |
el != null; | |
el = XDOMUtil.getNextSiblingElementNS(el, XmlSchema.SCHEMA_NS)) { | |
// String elPrefix = el.getPrefix() == null ? "" | |
// : el.getPrefix(); | |
// if(elPrefix.equals(schema.schema_ns_prefix)) { | |
if (el.getLocalName().equals("selector")) { | |
XmlSchemaXPath selectorXPath = new XmlSchemaXPath(); | |
selectorXPath.xpath = el.getAttribute("xpath"); | |
Element annotationEl = | |
XDOMUtil.getFirstChildElementNS(el, XmlSchema.SCHEMA_NS, "annotation"); | |
if (annotationEl != null) { | |
XmlSchemaAnnotation annotation = handleAnnotation(annotationEl); | |
selectorXPath.setAnnotation(annotation); | |
} | |
constraint.setSelector(selectorXPath); | |
} else if (el.getLocalName().equals("field")) { | |
XmlSchemaXPath fieldXPath = new XmlSchemaXPath(); | |
fieldXPath.xpath = el.getAttribute("xpath"); | |
constraint.getFields().add(fieldXPath); | |
Element annotationEl = | |
XDOMUtil.getFirstChildElementNS(el, XmlSchema.SCHEMA_NS, "annotation"); | |
if (annotationEl != null) { | |
XmlSchemaAnnotation annotation = handleAnnotation(annotationEl); | |
fieldXPath.setAnnotation(annotation); | |
} | |
} else if (el.getLocalName().equals("annotation")) { | |
XmlSchemaAnnotation constraintAnnotation = handleAnnotation(el); | |
constraint.setAnnotation(constraintAnnotation); | |
} | |
} | |
return constraint; | |
} catch (InstantiationException e) { | |
throw new XmlSchemaException(e.getMessage()); | |
} catch (IllegalAccessException e) { | |
throw new XmlSchemaException(e.getMessage()); | |
} | |
} | |
private void handleElementAnnotation(Element el, XmlSchemaElement element) { | |
Element annotationEl = XDOMUtil.getFirstChildElementNS(el, XmlSchema.SCHEMA_NS, "annotation"); | |
if (annotationEl != null) { | |
XmlSchemaAnnotation annotation = handleAnnotation(annotationEl); | |
element.setAnnotation(annotation); | |
} | |
} | |
private boolean handleElementForm(Element el, XmlSchemaElement element, boolean isQualified) { | |
if (el.hasAttribute("form")) { | |
String formDef = el.getAttribute("form"); | |
element.setForm(XmlSchemaForm.schemaValueOf(formDef)); | |
} | |
isQualified = element.getForm() == XmlSchemaForm.QUALIFIED; | |
return isQualified; | |
} | |
private void handleElementGlobalType(Element el, XmlSchemaElement element) { | |
if (el.getAttributeNode("type") != null) { | |
String typeName = el.getAttribute("type"); | |
element.setSchemaTypeName(getRefQName(typeName, el)); | |
QName typeQName = element.getSchemaTypeName(); | |
XmlSchemaType type = collection.getTypeByQName(typeQName); | |
if (type == null) { | |
// Could be a forward reference... | |
collection.addUnresolvedType(typeQName, element); | |
} | |
element.setSchemaType(type); | |
} else if (el.getAttributeNode("ref") != null) { | |
String refName = el.getAttribute("ref"); | |
QName refQName = getRefQName(refName, el); | |
element.getRef().setTargetQName(refQName); | |
} | |
} | |
private void handleElementName(boolean isGlobal, XmlSchemaElement element, boolean isQualified) { | |
} | |
/* | |
* handle_simple_content_restriction if( restriction has base attribute ) set the baseType else if( | |
* restriction has an inline simpleType ) handleSimpleType add facets if any to the restriction | |
*/ | |
/* | |
* handle_simple_content_extension extension should have a base name and cannot have any inline defn for( | |
* each childNode ) if( attribute) handleAttribute else if( attributeGroup) handleAttributeGroup else if( | |
* anyAttribute) handleAnyAttribute | |
*/ | |
private XmlSchemaGroup handleGroup(XmlSchema schema, Element groupEl, Element schemaEl) { | |
XmlSchemaGroup group = new XmlSchemaGroup(schema); | |
group.setName(groupEl.getAttribute("name")); | |
for (Element el = XDOMUtil.getFirstChildElementNS(groupEl, XmlSchema.SCHEMA_NS); | |
el != null; | |
el = XDOMUtil.getNextSiblingElementNS(el, XmlSchema.SCHEMA_NS)) { | |
if (el.getLocalName().equals("all")) { | |
group.setParticle(handleAll(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("sequence")) { | |
group.setParticle(handleSequence(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("choice")) { | |
group.setParticle(handleChoice(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("annotation")) { | |
XmlSchemaAnnotation groupAnnotation = handleAnnotation(el); | |
group.setAnnotation(groupAnnotation); | |
} | |
} | |
return group; | |
} | |
private XmlSchemaGroupRef handleGroupRef(XmlSchema schema, Element groupEl, Element schemaEl) { | |
XmlSchemaGroupRef group = new XmlSchemaGroupRef(); | |
group.setMaxOccurs(getMaxOccurs(groupEl)); | |
group.setMinOccurs(getMinOccurs(groupEl)); | |
Element annotationEl = XDOMUtil.getFirstChildElementNS(groupEl, XmlSchema.SCHEMA_NS, "annotation"); | |
if (annotationEl != null) { | |
XmlSchemaAnnotation annotation = handleAnnotation(annotationEl); | |
group.setAnnotation(annotation); | |
} | |
if (groupEl.hasAttribute("ref")) { | |
String ref = groupEl.getAttribute("ref"); | |
group.setRefName(getRefQName(ref, groupEl)); | |
return group; | |
} | |
for (Element el = XDOMUtil.getFirstChildElementNS(groupEl, XmlSchema.SCHEMA_NS); | |
el != null; | |
el = XDOMUtil.getNextSiblingElement(el)) { | |
if (el.getLocalName().equals("sequence")) { | |
group.setParticle(handleSequence(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("all")) { | |
group.setParticle(handleAll(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("choice")) { | |
group.setParticle(handleChoice(schema, el, schemaEl)); | |
} | |
} | |
return group; | |
} | |
private XmlSchemaNotation handleNotation(XmlSchema schema, Element notationEl) { | |
XmlSchemaNotation notation = new XmlSchemaNotation(schema); | |
if (notationEl.hasAttribute("id")) { | |
notation.setId(notationEl.getAttribute("id")); | |
} | |
if (notationEl.hasAttribute("name")) { | |
notation.setName(notationEl.getAttribute("name")); | |
} | |
if (notationEl.hasAttribute("public")) { | |
notation.setPublicNotation(notationEl.getAttribute("public")); | |
} | |
if (notationEl.hasAttribute("system")) { | |
notation.setSystem(notationEl.getAttribute("system")); | |
} | |
Element annotationEl = XDOMUtil.getFirstChildElementNS(notationEl, XmlSchema.SCHEMA_NS, "annotation"); | |
if (annotationEl != null) { | |
XmlSchemaAnnotation annotation = handleAnnotation(annotationEl); | |
notation.setAnnotation(annotation); | |
} | |
return notation; | |
} | |
/** | |
* Handle redefine | |
* | |
* @param schema | |
* @param redefineEl | |
* @param schemaEl | |
* @return | |
*/ | |
private XmlSchemaRedefine handleRedefine(XmlSchema schema, Element redefineEl, Element schemaEl) { | |
XmlSchemaRedefine redefine = new XmlSchemaRedefine(schema); | |
redefine.schemaLocation = redefineEl.getAttribute("schemaLocation"); | |
final TargetNamespaceValidator validator = newIncludeValidator(schema); | |
if (schema.getSourceURI() != null) { | |
redefine.schema = | |
resolveXmlSchema(schema.getLogicalTargetNamespace(), redefine.schemaLocation, | |
schema.getSourceURI(), validator); | |
} else { | |
redefine.schema = | |
resolveXmlSchema(schema.getLogicalTargetNamespace(), redefine.schemaLocation, validator); | |
} | |
/* | |
* FIXME - This seems not right. Since the redefine should take into account the attributes of the | |
* original element we cannot just build the type defined in the redefine section - what we need to do | |
* is to get the original type object and modify it. However one may argue (quite reasonably) that the | |
* purpose of this object model is to provide just the representation and not the validation (as it | |
* has been always the case) | |
*/ | |
for (Element el = XDOMUtil.getFirstChildElementNS(redefineEl, XmlSchema.SCHEMA_NS); | |
el != null; | |
el = XDOMUtil.getNextSiblingElementNS(el, XmlSchema.SCHEMA_NS)) { | |
if (el.getLocalName().equals("simpleType")) { | |
XmlSchemaType type = handleSimpleType(schema, el, schemaEl, false); | |
redefine.getSchemaTypes().put(type.getQName(), type); | |
redefine.getItems().add(type); | |
} else if (el.getLocalName().equals("complexType")) { | |
XmlSchemaType type = handleComplexType(schema, el, schemaEl, true); | |
redefine.getSchemaTypes().put(type.getQName(), type); | |
redefine.getItems().add(type); | |
} else if (el.getLocalName().equals("group")) { | |
XmlSchemaGroup group = handleGroup(schema, el, schemaEl); | |
redefine.getGroups().put(group.getQName(), group); | |
redefine.getItems().add(group); | |
} else if (el.getLocalName().equals("attributeGroup")) { | |
XmlSchemaAttributeGroup group = handleAttributeGroup(schema, el, schemaEl); | |
redefine.getAttributeGroups().put(group.getQName(), group); | |
redefine.getItems().add(group); | |
} else if (el.getLocalName().equals("annotation")) { | |
XmlSchemaAnnotation annotation = handleAnnotation(el); | |
redefine.setAnnotation(annotation); | |
} | |
// } | |
} | |
return redefine; | |
} | |
private void handleSchemaElementBasics(Element schemaEl, String systemId, | |
XmlSchemaCollection.SchemaKey schemaKey) { | |
if (!collection.containsSchema(schemaKey)) { | |
collection.addSchema(schemaKey, currentSchema); | |
currentSchema.setParent(collection); // establish parentage now. | |
} else { | |
throw new XmlSchemaException("Schema name conflict in collection. Namespace: " | |
+ currentSchema.getLogicalTargetNamespace()); | |
} | |
currentSchema.setElementFormDefault(this.getFormDefault(schemaEl, "elementFormDefault")); | |
currentSchema.setAttributeFormDefault(this.getFormDefault(schemaEl, "attributeFormDefault")); | |
currentSchema.setBlockDefault(this.getDerivation(schemaEl, "blockDefault")); | |
currentSchema.setFinalDefault(this.getDerivation(schemaEl, "finalDefault")); | |
/* set id attribute */ | |
if (schemaEl.hasAttribute("id")) { | |
currentSchema.setId(schemaEl.getAttribute("id")); | |
} | |
currentSchema.setSourceURI(systemId); | |
} | |
private void handleSchemaElementChild(Element schemaEl, Element el) { | |
if (el.getLocalName().equals("simpleType")) { | |
XmlSchemaType type = handleSimpleType(currentSchema, el, schemaEl, true); | |
collection.resolveType(type.getQName(), type); | |
} else if (el.getLocalName().equals("complexType")) { | |
XmlSchemaType type = handleComplexType(currentSchema, el, schemaEl, true); | |
collection.resolveType(type.getQName(), type); | |
} else if (el.getLocalName().equals("element")) { | |
handleElement(currentSchema, el, schemaEl, true); | |
} else if (el.getLocalName().equals("include")) { | |
handleInclude(currentSchema, el, schemaEl); | |
} else if (el.getLocalName().equals("import")) { | |
handleImport(currentSchema, el, schemaEl); | |
} else if (el.getLocalName().equals("group")) { | |
handleGroup(currentSchema, el, schemaEl); | |
} else if (el.getLocalName().equals("attributeGroup")) { | |
handleAttributeGroup(currentSchema, el, schemaEl); | |
} else if (el.getLocalName().equals("attribute")) { | |
handleAttribute(currentSchema, el, schemaEl, true); | |
} else if (el.getLocalName().equals("redefine")) { | |
handleRedefine(currentSchema, el, schemaEl); | |
} else if (el.getLocalName().equals("notation")) { | |
handleNotation(currentSchema, el); | |
} else if (el.getLocalName().equals("annotation")) { | |
XmlSchemaAnnotation annotation = handleAnnotation(el); | |
currentSchema.setAnnotation(annotation); | |
} | |
} | |
private XmlSchemaSequence handleSequence(XmlSchema schema, Element sequenceEl, Element schemaEl) { | |
XmlSchemaSequence sequence = new XmlSchemaSequence(); | |
// handle min and max occurences | |
sequence.setMinOccurs(getMinOccurs(sequenceEl)); | |
sequence.setMaxOccurs(getMaxOccurs(sequenceEl)); | |
for (Element el = XDOMUtil.getFirstChildElementNS(sequenceEl, XmlSchema.SCHEMA_NS); | |
el != null; | |
el = XDOMUtil.getNextSiblingElementNS(el, XmlSchema.SCHEMA_NS)) { | |
if (el.getLocalName().equals("sequence")) { | |
XmlSchemaSequence seq = handleSequence(schema, el, schemaEl); | |
sequence.getItems().add(seq); | |
} else if (el.getLocalName().equals("element")) { | |
XmlSchemaElement element = handleElement(schema, el, schemaEl, false); | |
sequence.getItems().add(element); | |
} else if (el.getLocalName().equals("group")) { | |
XmlSchemaGroupRef group = handleGroupRef(schema, el, schemaEl); | |
sequence.getItems().add(group); | |
} else if (el.getLocalName().equals("choice")) { | |
XmlSchemaChoice choice = handleChoice(schema, el, schemaEl); | |
sequence.getItems().add(choice); | |
} else if (el.getLocalName().equals("any")) { | |
XmlSchemaAny any = handleAny(schema, el, schemaEl); | |
sequence.getItems().add(any); | |
} else if (el.getLocalName().equals("annotation")) { | |
XmlSchemaAnnotation annotation = handleAnnotation(el); | |
sequence.setAnnotation(annotation); | |
} | |
} | |
return sequence; | |
} | |
private XmlSchemaSimpleContent handleSimpleContent(XmlSchema schema, Element simpleEl, Element schemaEl) { | |
XmlSchemaSimpleContent simpleContent = new XmlSchemaSimpleContent(); | |
for (Element el = XDOMUtil.getFirstChildElementNS(simpleEl, XmlSchema.SCHEMA_NS); | |
el != null; | |
el = XDOMUtil.getNextSiblingElementNS(el, XmlSchema.SCHEMA_NS)) { | |
if (el.getLocalName().equals("restriction")) { | |
simpleContent.content = handleSimpleContentRestriction(schema, el, schemaEl); | |
} else if (el.getLocalName().equals("extension")) { | |
simpleContent.content = handleSimpleContentExtension(schema, el, schemaEl); | |
} else if (el.getLocalName().equals("annotation")) { | |
simpleContent.setAnnotation(handleAnnotation(el)); | |
} | |
} | |
return simpleContent; | |
} | |
private XmlSchemaSimpleContentExtension handleSimpleContentExtension(XmlSchema schema, Element extEl, | |
Element schemaEl) { | |
XmlSchemaSimpleContentExtension ext = new XmlSchemaSimpleContentExtension(); | |
if (extEl.hasAttribute("base")) { | |
String name = extEl.getAttribute("base"); | |
ext.setBaseTypeName(getRefQName(name, extEl)); | |
} | |
for (Element el = XDOMUtil.getFirstChildElementNS(extEl, XmlSchema.SCHEMA_NS); | |
el != null; | |
el = XDOMUtil.getNextSiblingElementNS(el, XmlSchema.SCHEMA_NS)) { | |
if (el.getLocalName().equals("attribute")) { | |
XmlSchemaAttribute attr = handleAttribute(schema, el, schemaEl); | |
ext.getAttributes().add(attr); | |
} else if (el.getLocalName().equals("attributeGroup")) { | |
XmlSchemaAttributeGroupRef attrGroup = handleAttributeGroupRef(schema, el); | |
ext.getAttributes().add(attrGroup); | |
} else if (el.getLocalName().equals("anyAttribute")) { | |
ext.setAnyAttribute(handleAnyAttribute(schema, el, schemaEl)); | |
} else if (el.getLocalName().equals("annotation")) { | |
XmlSchemaAnnotation ann = handleAnnotation(el); | |
ext.setAnnotation(ann); | |
} | |
} | |
return ext; | |
} | |
private XmlSchemaSimpleContentRestriction handleSimpleContentRestriction(XmlSchema schema, | |
Element restrictionEl, | |
Element schemaEl) { | |
XmlSchemaSimpleContentRestriction restriction = new XmlSchemaSimpleContentRestriction(); | |
if (restrictionEl.hasAttribute("base")) { | |
String name = restrictionEl.getAttribute("base"); | |
restriction.setBaseTypeName(getRefQName(name, restrictionEl)); | |
} | |
if (restrictionEl.hasAttribute("id")) { | |
restriction.setId(restrictionEl.getAttribute("id")); | |
} | |
// check back simpleContent tag children to add attributes and | |
// simpleType if any occur | |
for (Element el = XDOMUtil.getFirstChildElementNS(restrictionEl, XmlSchema.SCHEMA_NS); | |
el != null; | |
el = XDOMUtil.getNextSiblingElementNS(el, XmlSchema.SCHEMA_NS)) { | |
if (el.getLocalName().equals("attribute")) { | |
XmlSchemaAttribute attr = handleAttribute(schema, el, schemaEl); | |
restriction.getAttributes().add(attr); | |
} else if (el.getLocalName().equals("attributeGroup")) { | |
XmlSchemaAttributeGroupRef attrGroup = handleAttributeGroupRef(schema, el); | |
restriction.getAttributes().add(attrGroup); | |
} else if (el.getLocalName().equals("simpleType")) { | |
restriction.setBaseType(handleSimpleType(schema, el, schemaEl, false)); | |
} else if (el.getLocalName().equals("anyAttribute")) { | |
restriction.anyAttribute = handleAnyAttribute(schema, el, schemaEl); | |
} else if (el.getLocalName().equals("annotation")) { | |
restriction.setAnnotation(handleAnnotation(el)); | |
} else { | |
XmlSchemaFacet facet = XmlSchemaFacet.construct(el); | |
Element annotation = XDOMUtil.getFirstChildElementNS(el, XmlSchema.SCHEMA_NS, "annotation"); | |
if (annotation != null) { | |
XmlSchemaAnnotation facetAnnotation = handleAnnotation(annotation); | |
facet.setAnnotation(facetAnnotation); | |
} | |
restriction.getFacets().add(facet); | |
// process extra attributes and elements | |
processExtensibilityComponents(facet, el, true); | |
} | |
} | |
return restriction; | |
} | |
private void handleSimpleTypeFinal(Element simpleEl, XmlSchemaSimpleType simpleType) { | |
if (simpleEl.hasAttribute("final")) { | |
String finalstr = simpleEl.getAttribute("final"); | |
simpleType.setFinal(XmlSchemaDerivationMethod.schemaValueOf(finalstr)); | |
} | |
} | |
private void handleSimpleTypeList(XmlSchema schema, Element schemaEl, XmlSchemaSimpleType simpleType, | |
Element listEl) { | |
XmlSchemaSimpleTypeList list = new XmlSchemaSimpleTypeList(); | |
/****** | |
* if( list has an itemType attribute ) set the baseTypeName and look up the base type else if( list | |
* has a SimpleTypeElement as child) get that element and do a handleSimpleType set the list has the | |
* content of the simpleType | |
*/ | |
Element inlineListType; | |
Element listAnnotationEl; | |
inlineListType = XDOMUtil.getFirstChildElementNS(listEl, XmlSchema.SCHEMA_NS, "simpleType"); | |
if (listEl.hasAttribute("itemType")) { | |
String name = listEl.getAttribute("itemType"); | |
list.itemTypeName = getRefQName(name, listEl); | |
} else if (inlineListType != null) { | |
list.itemType = handleSimpleType(schema, inlineListType, schemaEl, false); | |
} | |
listAnnotationEl = XDOMUtil.getFirstChildElementNS(listEl, XmlSchema.SCHEMA_NS, "annotation"); | |
if (listAnnotationEl != null) { | |
XmlSchemaAnnotation listAnnotation = handleAnnotation(listAnnotationEl); | |
list.setAnnotation(listAnnotation); | |
} | |
simpleType.content = list; | |
} | |
private void handleSimpleTypeRestriction(XmlSchema schema, Element schemaEl, | |
XmlSchemaSimpleType simpleType, Element restrictionEl) { | |
XmlSchemaSimpleTypeRestriction restriction = new XmlSchemaSimpleTypeRestriction(); | |
Element restAnnotationEl = | |
XDOMUtil.getFirstChildElementNS(restrictionEl, XmlSchema.SCHEMA_NS, "annotation"); | |
if (restAnnotationEl != null) { | |
XmlSchemaAnnotation restAnnotation = handleAnnotation(restAnnotationEl); | |
restriction.setAnnotation(restAnnotation); | |
} | |
/** | |
* if (restriction has a base attribute ) set the baseTypeName and look up the base type else if( | |
* restriction has a SimpleType Element as child) get that element and do a handleSimpleType; get the | |
* children of restriction other than annotation and simpleTypes and construct facets from it; set the | |
* restriction has the content of the simpleType | |
**/ | |
Element inlineSimpleType = | |
XDOMUtil.getFirstChildElementNS(restrictionEl, XmlSchema.SCHEMA_NS, "simpleType"); | |
if (restrictionEl.hasAttribute("base")) { | |
NamespaceContext ctx = NodeNamespaceContext.getNamespaceContext(restrictionEl); | |
restriction.setBaseTypeName(getRefQName(restrictionEl.getAttribute("base"), ctx)); | |
} else if (inlineSimpleType != null) { | |
restriction.setBaseType(handleSimpleType(schema, inlineSimpleType, schemaEl, false)); | |
} | |
for (Element el = XDOMUtil.getFirstChildElementNS(restrictionEl, XmlSchema.SCHEMA_NS); | |
el != null; | |
el = XDOMUtil.getNextSiblingElementNS(el, XmlSchema.SCHEMA_NS)) { | |
if (!el.getLocalName().equals("annotation") && !el.getLocalName().equals("simpleType")) { | |
XmlSchemaFacet facet = XmlSchemaFacet.construct(el); | |
Element annotation = XDOMUtil.getFirstChildElementNS(el, XmlSchema.SCHEMA_NS, "annotation"); | |
if (annotation != null) { | |
XmlSchemaAnnotation facetAnnotation = handleAnnotation(annotation); | |
facet.setAnnotation(facetAnnotation); | |
} | |
// process extra attributes and elements | |
processExtensibilityComponents(facet, el, true); | |
restriction.getFacets().add(facet); | |
} | |
} | |
simpleType.content = restriction; | |
} | |
private void handleSimpleTypeUnion(XmlSchema schema, Element schemaEl, XmlSchemaSimpleType simpleType, | |
Element unionEl) { | |
XmlSchemaSimpleTypeUnion union = new XmlSchemaSimpleTypeUnion(); | |
/****** | |
* if( union has a memberTypes attribute ) add the memberTypeSources string for (each memberType in | |
* the list ) lookup(memberType) for( all SimpleType child Elements) add the simpleTypeName (if any) | |
* to the memberType Sources do a handleSimpleType with the simpleTypeElement | |
*/ | |
if (unionEl.hasAttribute("memberTypes")) { | |
String memberTypes = unionEl.getAttribute("memberTypes"); | |
union.setMemberTypesSource(memberTypes); | |
Vector<QName> v = new Vector<QName>(); | |
StringTokenizer tokenizer = new StringTokenizer(memberTypes, " "); | |
while (tokenizer.hasMoreTokens()) { | |
String member = tokenizer.nextToken(); | |
v.add(getRefQName(member, unionEl)); | |
} | |
union.setMemberTypesQNames(new QName[v.size()]); | |
v.copyInto(union.getMemberTypesQNames()); | |
} | |
Element inlineUnionType = XDOMUtil.getFirstChildElementNS(unionEl, XmlSchema.SCHEMA_NS, "simpleType"); | |
while (inlineUnionType != null) { | |
XmlSchemaSimpleType unionSimpleType = handleSimpleType(schema, inlineUnionType, schemaEl, false); | |
union.getBaseTypes().add(unionSimpleType); | |
if (!unionSimpleType.isAnonymous()) { | |
union.setMemberTypesSource(union.getMemberTypesSource() + " " + unionSimpleType.getName()); | |
} | |
inlineUnionType = | |
XDOMUtil.getNextSiblingElementNS(inlineUnionType, XmlSchema.SCHEMA_NS, "simpleType"); | |
} | |
// NodeList annotations = unionEl.getElementsByTagNameNS( | |
// XmlSchema.SCHEMA_NS, "annotation"); | |
Element unionAnnotationEl = | |
XDOMUtil.getFirstChildElementNS(unionEl, XmlSchema.SCHEMA_NS, "annotation"); | |
if (unionAnnotationEl != null) { | |
XmlSchemaAnnotation unionAnnotation = handleAnnotation(unionAnnotationEl); | |
union.setAnnotation(unionAnnotation); | |
} | |
simpleType.content = union; | |
} | |
private TargetNamespaceValidator newIncludeValidator(final XmlSchema schema) { | |
return new TargetNamespaceValidator() { | |
public void validate(XmlSchema pSchema) { | |
if (isEmpty(pSchema.getSyntacticalTargetNamespace())) { | |
pSchema.setLogicalTargetNamespace(schema.getLogicalTargetNamespace()); | |
} else { | |
if (!pSchema.getSyntacticalTargetNamespace().equals(schema.getLogicalTargetNamespace())) { | |
String msg = "An included schema was announced to have the default target namespace"; | |
if (!isEmpty(schema.getLogicalTargetNamespace())) { | |
msg += " or the target namespace " + schema.getLogicalTargetNamespace(); | |
} | |
throw new XmlSchemaException(msg + ", but has the target namespace " | |
+ pSchema.getLogicalTargetNamespace()); | |
} | |
} | |
} | |
private boolean isEmpty(String pValue) { | |
return pValue == null || Constants.NULL_NS_URI.equals(pValue); | |
} | |
}; | |
} | |
/** | |
* A generic method to process the extra attributes and the the extra elements present within the schema. | |
* What are considered extensions are child elements with non schema namespace and child attributes with | |
* any namespace | |
* | |
* @param schemaObject | |
* @param parentElement | |
*/ | |
private void processExtensibilityComponents(XmlSchemaObject schemaObject, | |
Element parentElement, | |
boolean namespaces) { | |
if (extReg != null) { | |
// process attributes | |
NamedNodeMap attributes = parentElement.getAttributes(); | |
for (int i = 0; i < attributes.getLength(); i++) { | |
Attr attribute = (Attr)attributes.item(i); | |
String namespaceURI = attribute.getNamespaceURI(); | |
String name = attribute.getLocalName(); | |
if (namespaceURI != null && !"".equals(namespaceURI) // ignore unqualified attributes | |
// ignore namespaces | |
&& (namespaces || !namespaceURI.startsWith(Constants.XMLNS_ATTRIBUTE_NS_URI)) | |
// does not belong to the schema namespace by any chance! | |
&& !Constants.URI_2001_SCHEMA_XSD.equals(namespaceURI)) { | |
QName qName = new QName(namespaceURI, name); | |
extReg.deserializeExtension(schemaObject, qName, attribute); | |
} | |
} | |
// process elements | |
Node child = parentElement.getFirstChild(); | |
while (child != null) { | |
if (child.getNodeType() == Node.ELEMENT_NODE) { | |
Element extElement = (Element)child; | |
String namespaceURI = extElement.getNamespaceURI(); | |
String name = extElement.getLocalName(); | |
if (namespaceURI != null && !Constants.URI_2001_SCHEMA_XSD.equals(namespaceURI)) { | |
// does not belong to the schema namespace | |
QName qName = new QName(namespaceURI, name); | |
extReg.deserializeExtension(schemaObject, qName, extElement); | |
} | |
} | |
child = child.getNextSibling(); | |
} | |
} | |
} | |
/** | |
* Add an XmlSchema to the cache if the current thread has the cache enabled. The first three parameters | |
* are used to construct a key | |
* | |
* @param targetNamespace | |
* @param schemaLocation | |
* @param baseUri This parameter is the value put under the key (if the cache is enabled) | |
* @param readSchema | |
*/ | |
private void putCachedSchema(String targetNamespace, String schemaLocation, String baseUri, | |
XmlSchema readSchema) { | |
if (resolvedSchemas != null) { | |
Map<String, SoftReference<XmlSchema>> threadResolvedSchemas = resolvedSchemas.get(); | |
if (threadResolvedSchemas != null) { | |
String schemaKey = targetNamespace + schemaLocation + baseUri; | |
threadResolvedSchemas.put(schemaKey, new SoftReference<XmlSchema>(readSchema)); | |
} | |
} | |
} | |
} |