| /** |
| * 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; |
| } |
| } |