blob: 4b0307d1393f1be8cb29978ba6cdeb9a9fa80938 [file] [log] [blame]
/**
* 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.walker;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.namespace.QName;
import org.apache.ws.commons.schema.XmlSchema;
import org.apache.ws.commons.schema.XmlSchemaAnyAttribute;
import org.apache.ws.commons.schema.XmlSchemaAttribute;
import org.apache.ws.commons.schema.XmlSchemaAttributeGroup;
import org.apache.ws.commons.schema.XmlSchemaAttributeGroupMember;
import org.apache.ws.commons.schema.XmlSchemaAttributeGroupRef;
import org.apache.ws.commons.schema.XmlSchemaAttributeOrGroupRef;
import org.apache.ws.commons.schema.XmlSchemaComplexContent;
import org.apache.ws.commons.schema.XmlSchemaComplexContentExtension;
import org.apache.ws.commons.schema.XmlSchemaComplexContentRestriction;
import org.apache.ws.commons.schema.XmlSchemaComplexType;
import org.apache.ws.commons.schema.XmlSchemaContent;
import org.apache.ws.commons.schema.XmlSchemaElement;
import org.apache.ws.commons.schema.XmlSchemaFacet;
import org.apache.ws.commons.schema.XmlSchemaParticle;
import org.apache.ws.commons.schema.XmlSchemaSequence;
import org.apache.ws.commons.schema.XmlSchemaSequenceMember;
import org.apache.ws.commons.schema.XmlSchemaSimpleContentExtension;
import org.apache.ws.commons.schema.XmlSchemaSimpleContentRestriction;
import org.apache.ws.commons.schema.XmlSchemaSimpleType;
import org.apache.ws.commons.schema.XmlSchemaSimpleTypeContent;
import org.apache.ws.commons.schema.XmlSchemaSimpleTypeList;
import org.apache.ws.commons.schema.XmlSchemaSimpleTypeRestriction;
import org.apache.ws.commons.schema.XmlSchemaSimpleTypeUnion;
import org.apache.ws.commons.schema.XmlSchemaType;
import org.apache.ws.commons.schema.XmlSchemaUse;
import org.apache.ws.commons.schema.utils.XmlSchemaNamed;
/**
* The scope represents the set of types, attributes, and child groups &
* elements that the current type represents.
*/
final class XmlSchemaScope {
private SchemasByNamespace schemasByNamespace;
private Map<QName, XmlSchemaScope> scopeCache;
private XmlSchemaTypeInfo typeInfo;
private HashMap<QName, XmlSchemaAttrInfo> attributes;
private XmlSchemaParticle child;
private XmlSchemaAnyAttribute anyAttr;
private Set<QName> userRecognizedTypes;
/**
* Initialization of members to be filled in during the walk.
*/
private XmlSchemaScope() {
typeInfo = null;
attributes = null;
child = null;
anyAttr = null;
}
private XmlSchemaScope(XmlSchemaScope child, XmlSchemaType type) {
this();
this.schemasByNamespace = child.schemasByNamespace;
this.scopeCache = child.scopeCache;
this.userRecognizedTypes = child.userRecognizedTypes;
walk(type);
}
/**
* Initializes a new {@link XmlSchemaScope} with a base
* {@link XmlSchemaElement}. The element type and attributes will be
* traversed, and attribute lists and element children will be retrieved.
*/
XmlSchemaScope(XmlSchemaType type, SchemasByNamespace xmlSchemasByNamespace,
Map<QName, XmlSchemaScope> scopeCache, Set<QName> userRecognizedTypes) {
this();
schemasByNamespace = xmlSchemasByNamespace;
this.scopeCache = scopeCache;
this.userRecognizedTypes = userRecognizedTypes;
walk(type);
}
/**
* The type information of the value in scope.
*/
XmlSchemaTypeInfo getTypeInfo() {
return typeInfo;
}
/**
* The attributes visible in the current scope.
*/
Collection<XmlSchemaAttrInfo> getAttributesInScope() {
if (attributes == null) {
return null;
}
return attributes.values();
}
/**
* If the value is represented by a particle, returns that particle.
* Otherwise returns <code>null</code>.
*/
XmlSchemaParticle getParticle() {
return child;
}
/**
* The wildcard attribute, if any.
*/
XmlSchemaAnyAttribute getAnyAttribute() {
return anyAttr;
}
private void walk(XmlSchemaType type) {
if (type instanceof XmlSchemaSimpleType) {
walk((XmlSchemaSimpleType)type);
} else if (type instanceof XmlSchemaComplexType) {
walk((XmlSchemaComplexType)type);
} else {
throw new IllegalArgumentException("Unrecognized XmlSchemaType of type "
+ type.getClass().getName());
}
}
private void walk(XmlSchemaSimpleType simpleType) {
XmlSchemaSimpleTypeContent content = simpleType.getContent();
if (content == null) {
/*
* Only anyType contains no content. We reached the root of the type
* hierarchy.
*/
typeInfo = new XmlSchemaTypeInfo(XmlSchemaBaseSimpleType.ANYTYPE);
} else if (content instanceof XmlSchemaSimpleTypeList) {
XmlSchemaSimpleTypeList list = (XmlSchemaSimpleTypeList)content;
XmlSchemaSimpleType listType = list.getItemType();
if (listType == null) {
listType = (XmlSchemaSimpleType)schemasByNamespace.getTypeByName(list.getItemTypeName());
}
if (listType == null) {
throw new IllegalArgumentException("Unrecognized schema type for list "
+ getName(simpleType, "{Anonymous List Type}"));
}
XmlSchemaScope parentScope = getScope(listType);
switch (parentScope.getTypeInfo().getType()) {
case UNION:
case ATOMIC:
break;
default:
throw new IllegalStateException("Attempted to create a list from a "
+ parentScope.getTypeInfo().getType() + " type.");
}
typeInfo = new XmlSchemaTypeInfo(parentScope.getTypeInfo());
} else if (content instanceof XmlSchemaSimpleTypeUnion) {
XmlSchemaSimpleTypeUnion union = (XmlSchemaSimpleTypeUnion)content;
QName[] namedBaseTypes = union.getMemberTypesQNames();
List<XmlSchemaSimpleType> baseTypes = union.getBaseTypes();
if (namedBaseTypes != null) {
if (baseTypes == null) {
baseTypes = new ArrayList<XmlSchemaSimpleType>(namedBaseTypes.length);
}
for (QName namedBaseType : namedBaseTypes) {
XmlSchemaSimpleType baseType = (XmlSchemaSimpleType)schemasByNamespace.getTypeByName(namedBaseType);
if (baseType != null) {
baseTypes.add(baseType);
}
}
}
/*
* baseTypes cannot be null at this point; there must be a union of
* types.
*/
if ((baseTypes == null) || baseTypes.isEmpty()) {
throw new IllegalArgumentException("Unrecognized base types for union "
+ getName(simpleType, "{Anonymous Union Type}"));
}
List<XmlSchemaTypeInfo> childTypes = new ArrayList<XmlSchemaTypeInfo>(baseTypes.size());
for (XmlSchemaSimpleType baseType : baseTypes) {
XmlSchemaScope parentScope = getScope(baseType);
if (parentScope.getTypeInfo().getType().equals(XmlSchemaTypeInfo.Type.UNION)) {
childTypes.addAll(parentScope.getTypeInfo().getChildTypes());
} else {
childTypes.add(parentScope.getTypeInfo());
}
}
typeInfo = new XmlSchemaTypeInfo(childTypes);
} else if (content instanceof XmlSchemaSimpleTypeRestriction) {
final XmlSchemaSimpleTypeRestriction restr = (XmlSchemaSimpleTypeRestriction)content;
final List<XmlSchemaFacet> facets = restr.getFacets();
XmlSchemaTypeInfo parentTypeInfo = null;
if (XmlSchemaBaseSimpleType.isBaseSimpleType(simpleType.getQName())) {
// If this is a base simple type, use it!
typeInfo = new XmlSchemaTypeInfo(XmlSchemaBaseSimpleType.getBaseSimpleTypeFor(simpleType
.getQName()), mergeFacets(null, facets));
} else {
XmlSchemaSimpleType baseType = restr.getBaseType();
if (baseType == null) {
baseType = (XmlSchemaSimpleType)schemasByNamespace.getTypeByName(restr.getBaseTypeName());
}
if (baseType != null) {
final XmlSchemaScope parentScope = getScope(baseType);
/*
* We need to track the original type as well as the set of
* facets imposed on that type. Once the recursion ends, and
* we make it all the way back to the first scope, the user
* of this type info will know the derived type and all of
* its imposed facets. Unions can restrict unions, lists can
* restrict lists, and atomic types restrict other atomic
* types. We need to follow all of these too.
*/
parentTypeInfo = parentScope.getTypeInfo();
HashMap<XmlSchemaRestriction.Type, List<XmlSchemaRestriction>> mergedFacets = mergeFacets(parentTypeInfo
.getFacets(),
facets);
typeInfo = restrictTypeInfo(parentTypeInfo, mergedFacets);
} else {
throw new IllegalArgumentException("Unrecognized base type for "
+ getName(simpleType, "{Anonymous Simple Type}"));
}
}
typeInfo.setUserRecognizedType(getUserRecognizedType(simpleType.getQName(), parentTypeInfo));
} else {
throw new IllegalArgumentException("XmlSchemaSimpleType "
+ getName(simpleType, "{Anonymous Simple Type}")
+ "contains unrecognized XmlSchemaSimpleTypeContent "
+ content.getClass().getName());
}
}
private void walk(XmlSchemaComplexType complexType) {
XmlSchemaContent complexContent = (complexType.getContentModel() != null) ? complexType
.getContentModel().getContent() : null;
/*
* Process the complex type extensions and restrictions. If there aren't
* any, the content is be defined by the particle.
*/
if (complexContent != null) {
boolean isMixed = false;
if (complexType.isMixed()) {
isMixed = complexType.isMixed();
} else if (complexType.getContentModel() instanceof XmlSchemaComplexContent) {
isMixed = ((XmlSchemaComplexContent)complexType.getContentModel()).isMixed();
}
walk(isMixed, complexContent);
final QName userRecognizedType =
getUserRecognizedType(complexType.getQName(), null);
if (userRecognizedType != null) {
typeInfo.setUserRecognizedType(userRecognizedType);
}
} else {
child = complexType.getParticle();
attributes = createAttributeMap(complexType.getAttributes());
anyAttr = complexType.getAnyAttribute();
typeInfo = new XmlSchemaTypeInfo(complexType.isMixed());
}
}
private void walk(boolean isMixed, XmlSchemaContent content) {
if (content instanceof XmlSchemaComplexContentExtension) {
XmlSchemaComplexContentExtension ext = (XmlSchemaComplexContentExtension)content;
XmlSchemaType baseType = schemasByNamespace.getTypeByName(ext.getBaseTypeName());
XmlSchemaParticle baseParticle = null;
XmlSchemaAnyAttribute baseAnyAttr = null;
XmlSchemaScope parentScope = null;
if (baseType != null) {
/*
* Complex content extensions add attributes and elements in
* addition to what was retrieved from the parent. Since there
* will be no collisions, it is safe to perform a straight add.
*/
parentScope = getScope(baseType);
attributes = createAttributeMap(ext.getAttributes());
if (attributes == null) {
attributes = parentScope.attributes;
} else if (parentScope.attributes != null) {
attributes.putAll(parentScope.attributes);
}
baseParticle = parentScope.getParticle();
baseAnyAttr = parentScope.anyAttr;
}
/*
* An extension of a complex type is equivalent to creating a
* sequence of two particles: the parent particle followed by the
* child particle.
*/
if (ext.getParticle() == null) {
child = baseParticle;
} else if (baseParticle == null) {
child = ext.getParticle();
} else {
XmlSchemaSequence seq = new XmlSchemaSequence();
seq.getItems().add((XmlSchemaSequenceMember)baseParticle);
seq.getItems().add((XmlSchemaSequenceMember)ext.getParticle());
child = seq;
}
/*
* An extension of an anyAttribute means the child defines the
* processContents field, while a union of all namespaces between
* the parent and child is taken.
*/
if (baseAnyAttr == null) {
anyAttr = ext.getAnyAttribute();
} else if (ext.getAnyAttribute() == null) {
anyAttr = baseAnyAttr;
} else {
String[] baseNamespaces = baseAnyAttr.getNamespace().split(" ");
String[] childNamespaces = ext.getAnyAttribute().getNamespace().split(" ");
HashSet<String> namespaces = new HashSet<String>();
for (String baseNs : baseNamespaces) {
if (baseNs.length() > 0) {
namespaces.add(baseNs);
}
}
for (String childNs : childNamespaces) {
if (childNs.length() > 0) {
namespaces.add(childNs);
}
}
StringBuilder nsAsString = new StringBuilder();
for (String namespace : namespaces) {
nsAsString.append(namespace).append(" ");
}
anyAttr = new XmlSchemaAnyAttribute();
anyAttr.setNamespace(nsAsString.toString());
anyAttr.setProcessContent(ext.getAnyAttribute().getProcessContent());
anyAttr.setAnnotation(ext.getAnyAttribute().getAnnotation());
anyAttr.setId(ext.getAnyAttribute().getId());
anyAttr.setLineNumber(ext.getAnyAttribute().getLineNumber());
anyAttr.setLinePosition(ext.getAnyAttribute().getLinePosition());
anyAttr.setMetaInfoMap(ext.getAnyAttribute().getMetaInfoMap());
anyAttr.setSourceURI(ext.getAnyAttribute().getSourceURI());
anyAttr.setUnhandledAttributes(ext.getUnhandledAttributes());
}
final XmlSchemaTypeInfo parentTypeInfo = (parentScope == null) ? null : parentScope.getTypeInfo();
if ((parentTypeInfo != null) && !parentTypeInfo.getType().equals(XmlSchemaTypeInfo.Type.COMPLEX)) {
typeInfo = parentScope.getTypeInfo();
} else {
typeInfo = new XmlSchemaTypeInfo(isMixed);
}
} else if (content instanceof XmlSchemaComplexContentRestriction) {
final XmlSchemaComplexContentRestriction rstr = (XmlSchemaComplexContentRestriction)content;
final XmlSchemaType baseType = schemasByNamespace.getTypeByName(rstr.getBaseTypeName());
XmlSchemaScope parentScope = null;
if (baseType != null) {
parentScope = getScope(baseType);
attributes = mergeAttributes(parentScope.attributes, createAttributeMap(rstr.getAttributes()));
child = parentScope.getParticle();
}
/*
* There is no inheritance when restricting particles. If the schema
* writer wishes to include elements in the parent type, (s)he must
* redefine them in the child.
*/
if (rstr.getParticle() != null) {
child = rstr.getParticle();
}
/*
* There is no inheritance when restricting attribute wildcards. The
* only requirement is that the namespaces of the restricted type is
* a subset of the namespaces of the base type. This will not be
* checked here (all schemas are assumed correct).
*/
anyAttr = rstr.getAnyAttribute();
final XmlSchemaTypeInfo parentTypeInfo = (parentScope == null) ? null : parentScope.getTypeInfo();
if ((parentTypeInfo != null) && !parentTypeInfo.getType().equals(XmlSchemaTypeInfo.Type.COMPLEX)) {
typeInfo = parentTypeInfo;
} else {
typeInfo = new XmlSchemaTypeInfo(isMixed);
}
} else if (content instanceof XmlSchemaSimpleContentExtension) {
XmlSchemaSimpleContentExtension ext = (XmlSchemaSimpleContentExtension)content;
attributes = createAttributeMap(ext.getAttributes());
XmlSchemaType baseType = schemasByNamespace.getTypeByName(ext.getBaseTypeName());
if (baseType != null) {
final XmlSchemaScope parentScope = getScope(baseType);
typeInfo = parentScope.getTypeInfo();
if (attributes == null) {
attributes = parentScope.attributes;
} else if (parentScope.attributes != null) {
attributes.putAll(parentScope.attributes);
}
}
anyAttr = ext.getAnyAttribute();
} else if (content instanceof XmlSchemaSimpleContentRestriction) {
XmlSchemaSimpleContentRestriction rstr = (XmlSchemaSimpleContentRestriction)content;
attributes = createAttributeMap(rstr.getAttributes());
XmlSchemaType baseType = null;
if (rstr.getBaseType() != null) {
baseType = rstr.getBaseType();
} else {
baseType = schemasByNamespace.getTypeByName(rstr.getBaseTypeName());
}
if (baseType != null) {
XmlSchemaScope parentScope = getScope(baseType);
typeInfo = restrictTypeInfo(parentScope.getTypeInfo(),
mergeFacets(parentScope.getTypeInfo().getFacets(),
rstr.getFacets()));
attributes = mergeAttributes(parentScope.attributes, attributes);
}
anyAttr = rstr.getAnyAttribute();
}
}
private ArrayList<XmlSchemaAttrInfo> getAttributesOf(XmlSchemaAttributeGroupRef groupRef) {
XmlSchemaAttributeGroup attrGroup = groupRef.getRef().getTarget();
if (attrGroup == null) {
attrGroup = schemasByNamespace.getAttributeGroupByName(groupRef.getTargetQName());
}
return getAttributesOf(attrGroup);
}
private ArrayList<XmlSchemaAttrInfo> getAttributesOf(XmlSchemaAttributeGroup attrGroup) {
ArrayList<XmlSchemaAttrInfo> attrs = new ArrayList<XmlSchemaAttrInfo>(attrGroup.getAttributes()
.size());
for (XmlSchemaAttributeGroupMember member : attrGroup.getAttributes()) {
if (member instanceof XmlSchemaAttribute) {
attrs.add(getAttribute((XmlSchemaAttribute)member, false));
} else if (member instanceof XmlSchemaAttributeGroup) {
attrs.addAll(getAttributesOf((XmlSchemaAttributeGroup)member));
} else if (member instanceof XmlSchemaAttributeGroupRef) {
attrs.addAll(getAttributesOf((XmlSchemaAttributeGroupRef)member));
} else {
throw new IllegalArgumentException("Attribute Group "
+ getName(attrGroup, "{Anonymous Attribute Group}")
+ " contains unrecognized attribute group memeber type "
+ member.getClass().getName());
}
}
return attrs;
}
private XmlSchemaAttrInfo getAttribute(XmlSchemaAttribute attribute, boolean forceCopy) {
if (!attribute.isRef() && (attribute.getSchemaType() != null) && !forceCopy) {
if (attribute.getUse().equals(XmlSchemaUse.NONE)) {
attribute.setUse(XmlSchemaUse.OPTIONAL);
}
return new XmlSchemaAttrInfo(attribute);
}
XmlSchemaAttribute globalAttr = null;
QName attrQName = null;
if (attribute.isRef()) {
attrQName = attribute.getRefBase().getTargetQName();
} else {
attrQName = attribute.getQName();
}
if (!attribute.isRef() && (forceCopy || (attribute.getSchemaType() == null))) {
// If we are forcing a copy, there is no reference to follow.
globalAttr = attribute;
} else {
if (attribute.getRef().getTarget() != null) {
globalAttr = attribute.getRef().getTarget();
} else {
globalAttr = schemasByNamespace.getAttributeByName(attrQName);
}
}
XmlSchemaSimpleType schemaType = globalAttr.getSchemaType();
if (schemaType == null) {
final QName typeQName = globalAttr.getSchemaTypeName();
if (typeQName != null) {
schemaType = (XmlSchemaSimpleType) schemasByNamespace.getTypeByName(typeQName);
}
}
/*
* The attribute reference defines the attribute use and overrides the
* ID, default, and fixed fields. Everything else is defined by the
* global attribute.
*/
String fixedValue = attribute.getFixedValue();
if ((fixedValue != null) && (attribute != globalAttr)) {
fixedValue = globalAttr.getFixedValue();
}
String defaultValue = attribute.getDefaultValue();
if ((defaultValue == null) && (fixedValue == null) && (attribute != globalAttr)) {
defaultValue = globalAttr.getDefaultValue();
}
String id = attribute.getId();
if ((id == null) && (attribute != globalAttr)) {
id = globalAttr.getId();
}
XmlSchemaUse attrUsage = attribute.getUse();
if (attrUsage.equals(XmlSchemaUse.NONE)) {
attrUsage = XmlSchemaUse.OPTIONAL;
}
XmlSchema schema = schemasByNamespace.getSchemaDefiningAttribute(attrQName);
if (schema == null) {
// TODO: is this correct? The previous code used whichever schema was stored in the schemasByNamespace HashMap
// for the attribute's namespace.
schema = attribute.getParent();
}
final XmlSchemaAttribute copy = new XmlSchemaAttribute(schema, false);
copy.setName(globalAttr.getName());
copy.setAnnotation(globalAttr.getAnnotation());
copy.setDefaultValue(defaultValue);
copy.setFixedValue(fixedValue);
copy.setForm(globalAttr.getForm());
copy.setId(id);
copy.setLineNumber(attribute.getLineNumber());
copy.setLinePosition(attribute.getLinePosition());
copy.setMetaInfoMap(globalAttr.getMetaInfoMap());
copy.setSchemaType(schemaType);
copy.setSchemaTypeName(globalAttr.getSchemaTypeName());
copy.setSourceURI(globalAttr.getSourceURI());
copy.setUnhandledAttributes(globalAttr.getUnhandledAttributes());
copy.setUse(attrUsage);
return new XmlSchemaAttrInfo(copy, globalAttr.isTopLevel());
}
private HashMap<QName, XmlSchemaAttrInfo> createAttributeMap(Collection<? extends XmlSchemaAttributeOrGroupRef> attrs) {
if ((attrs == null) || attrs.isEmpty()) {
return null;
}
HashMap<QName, XmlSchemaAttrInfo> attributes = new HashMap<QName, XmlSchemaAttrInfo>();
for (XmlSchemaAttributeOrGroupRef attr : attrs) {
if (attr instanceof XmlSchemaAttribute) {
XmlSchemaAttrInfo attribute = getAttribute((XmlSchemaAttribute)attr, false);
attributes.put(attribute.getAttribute().getQName(), attribute);
} else if (attr instanceof XmlSchemaAttributeGroupRef) {
final List<XmlSchemaAttrInfo> attrList = getAttributesOf((XmlSchemaAttributeGroupRef)attr);
for (XmlSchemaAttrInfo attribute : attrList) {
attributes.put(attribute.getAttribute().getQName(), attribute);
}
}
}
return attributes;
}
private HashMap<QName, XmlSchemaAttrInfo> mergeAttributes(HashMap<QName, XmlSchemaAttrInfo> parentAttrs,
HashMap<QName, XmlSchemaAttrInfo> childAttrs) {
if ((parentAttrs == null) || parentAttrs.isEmpty()) {
return childAttrs;
} else if ((childAttrs == null) || childAttrs.isEmpty()) {
return parentAttrs;
}
HashMap<QName, XmlSchemaAttrInfo> newAttrs = new HashMap<QName, XmlSchemaAttrInfo>(parentAttrs);
/*
* Child attributes inherit all parent attributes, but may change the
* type, usage, default value, or fixed value.
*/
for (Map.Entry<QName, XmlSchemaAttrInfo> parentAttrEntry : parentAttrs.entrySet()) {
XmlSchemaAttrInfo parentAttr = parentAttrEntry.getValue();
XmlSchemaAttrInfo childAttr = childAttrs.get(parentAttrEntry.getKey());
if (childAttr != null) {
XmlSchemaAttrInfo newAttr = getAttribute(parentAttr.getAttribute(), true);
if (childAttr.getAttribute().getSchemaType() != null) {
newAttr.getAttribute().setSchemaType(childAttr.getAttribute().getSchemaType());
}
if (childAttr.getAttribute().getUse() != XmlSchemaUse.NONE) {
newAttr.getAttribute().setUse(childAttr.getAttribute().getUse());
}
// Attribute values may be defaulted or fixed, but not both.
if (childAttr.getAttribute().getDefaultValue() != null) {
newAttr.getAttribute().setDefaultValue(childAttr.getAttribute().getDefaultValue());
newAttr.getAttribute().setFixedValue(null);
} else if (childAttr.getAttribute().getFixedValue() != null) {
newAttr.getAttribute().setFixedValue(childAttr.getAttribute().getFixedValue());
newAttr.getAttribute().setDefaultValue(null);
}
newAttrs.put(newAttr.getAttribute().getQName(), newAttr);
}
}
return newAttrs;
}
private XmlSchemaScope getScope(XmlSchemaType type) {
if ((type.getQName() != null) && scopeCache.containsKey(type.getQName())) {
return scopeCache.get(type.getQName());
} else {
XmlSchemaScope scope = new XmlSchemaScope(this, type);
if (type.getQName() != null) {
scopeCache.put(type.getQName(), scope);
}
return scope;
}
}
private QName getUserRecognizedType(QName simpleType, XmlSchemaTypeInfo parent) {
if (userRecognizedTypes == null) {
return null;
} else if (simpleType == null) {
return (parent == null) ? null : parent.getUserRecognizedType();
} else if (userRecognizedTypes.contains(simpleType)) {
return simpleType;
}
if (XmlSchemaBaseSimpleType.isBaseSimpleType(simpleType)) {
boolean checkAnyType = true;
boolean checkAnySimpleType = true;
switch (XmlSchemaBaseSimpleType.getBaseSimpleTypeFor(simpleType)) {
case ANYTYPE:
checkAnyType = false;
case ANYSIMPLETYPE:
checkAnySimpleType = false;
default:
}
if (checkAnySimpleType) {
final QName anySimpleType = XmlSchemaBaseSimpleType.ANYSIMPLETYPE.getQName();
if (userRecognizedTypes.contains(anySimpleType)) {
return anySimpleType;
}
}
if (checkAnyType) {
final QName anyType = XmlSchemaBaseSimpleType.ANYTYPE.getQName();
if (userRecognizedTypes.contains(anyType)) {
return anyType;
}
}
}
return (parent == null) ? null : parent.getUserRecognizedType();
}
private static String getName(XmlSchemaNamed name, String defaultName) {
if (name.isAnonymous()) {
return defaultName;
} else {
return name.getName();
}
}
private static HashMap<XmlSchemaRestriction.Type, List<XmlSchemaRestriction>> mergeFacets(HashMap<XmlSchemaRestriction.Type, List<XmlSchemaRestriction>> parentFacets,
List<XmlSchemaFacet> child) {
if ((child == null) || child.isEmpty()) {
return parentFacets;
}
HashMap<XmlSchemaRestriction.Type, List<XmlSchemaRestriction>> childFacets = new HashMap<XmlSchemaRestriction.Type, List<XmlSchemaRestriction>>(
child
.size());
for (XmlSchemaFacet facet : child) {
XmlSchemaRestriction rstr = new XmlSchemaRestriction(facet);
List<XmlSchemaRestriction> rstrList = childFacets.get(rstr.getType());
if (rstrList == null) {
// Only enumerations may have more than one value.
if (rstr.getType() == XmlSchemaRestriction.Type.ENUMERATION) {
rstrList = new ArrayList<XmlSchemaRestriction>(5);
} else {
rstrList = new ArrayList<XmlSchemaRestriction>(1);
}
childFacets.put(rstr.getType(), rstrList);
}
rstrList.add(rstr);
}
if (parentFacets == null) {
return childFacets;
}
HashMap<XmlSchemaRestriction.Type, List<XmlSchemaRestriction>> mergedFacets
= new HashMap<XmlSchemaRestriction.Type, List<XmlSchemaRestriction>>(parentFacets);
// Child facets override parent facets
for (Map.Entry<XmlSchemaRestriction.Type, List<XmlSchemaRestriction>> rstrEntry : childFacets
.entrySet()) {
mergedFacets.put(rstrEntry.getKey(), rstrEntry.getValue());
}
return mergedFacets;
}
private static XmlSchemaTypeInfo restrictTypeInfo(XmlSchemaTypeInfo parentTypeInfo,
HashMap<XmlSchemaRestriction.Type, List<XmlSchemaRestriction>> facets) {
XmlSchemaTypeInfo typeInfo = null;
switch (parentTypeInfo.getType()) {
case LIST:
typeInfo = new XmlSchemaTypeInfo(parentTypeInfo.getChildTypes().get(0), facets);
break;
case UNION:
typeInfo = new XmlSchemaTypeInfo(parentTypeInfo.getChildTypes(), facets);
break;
case ATOMIC:
typeInfo = new XmlSchemaTypeInfo(parentTypeInfo.getBaseType(), facets);
break;
default:
throw new IllegalStateException("Cannot restrict on a " + parentTypeInfo.getType() + " type.");
}
if (parentTypeInfo.getUserRecognizedType() != null) {
typeInfo.setUserRecognizedType(parentTypeInfo.getUserRecognizedType());
}
return typeInfo;
}
}