You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by dk...@apache.org on 2014/09/17 17:32:46 UTC
svn commit: r1625632 [4/9] - in /webservices/xmlschema/trunk: ./
xmlschema-walker/ xmlschema-walker/src/ xmlschema-walker/src/main/
xmlschema-walker/src/main/java/ xmlschema-walker/src/main/java/org/
xmlschema-walker/src/main/java/org/apache/ xmlschema...
Added: webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaScope.java
URL: http://svn.apache.org/viewvc/webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaScope.java?rev=1625632&view=auto
==============================================================================
--- webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaScope.java (added)
+++ webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaScope.java Wed Sep 17 15:32:44 2014
@@ -0,0 +1,821 @@
+/**
+ * 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 Map<String, XmlSchema> 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.
+ *
+ * @param element The base element to build the scope from.
+ * @param substitutions The master list of substitution groups to pull from.
+ * @param userRecognizedTypes The set of types recognized by the caller.
+ */
+ XmlSchemaScope(XmlSchemaType type, Map<String, XmlSchema> 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) {
+ XmlSchema schema = schemasByNamespace.get(list.getItemTypeName().getNamespaceURI());
+
+ listType = (XmlSchemaSimpleType)schema.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) {
+ XmlSchema schema = schemasByNamespace.get(namedBaseType.getNamespaceURI());
+ XmlSchemaSimpleType baseType = (XmlSchemaSimpleType)schema.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) {
+ XmlSchema schema = schemasByNamespace.get(restr.getBaseTypeName().getNamespaceURI());
+ baseType = (XmlSchemaSimpleType)schema.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);
+
+ } 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;
+
+ XmlSchema schema = schemasByNamespace.get(ext.getBaseTypeName().getNamespaceURI());
+ XmlSchemaType baseType = schema.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 XmlSchema schema = schemasByNamespace.get(rstr.getBaseTypeName().getNamespaceURI());
+
+ final XmlSchemaType baseType = schema.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());
+
+ XmlSchema schema = schemasByNamespace.get(ext.getBaseTypeName().getNamespaceURI());
+ XmlSchemaType baseType = schema.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 {
+ XmlSchema schema = schemasByNamespace.get(rstr.getBaseTypeName().getNamespaceURI());
+ baseType = schema.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) {
+ XmlSchema schema = schemasByNamespace.get(groupRef.getTargetQName().getNamespaceURI());
+ attrGroup = schema.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();
+ }
+ final XmlSchema schema = schemasByNamespace.get(attrQName.getNamespaceURI());
+
+ 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 = schema.getAttributeByName(attrQName);
+ }
+ }
+
+ XmlSchemaSimpleType schemaType = globalAttr.getSchemaType();
+ if (schemaType == null) {
+ final QName typeQName = globalAttr.getSchemaTypeName();
+ XmlSchema typeSchema = schemasByNamespace.get(typeQName.getNamespaceURI());
+ schemaType = (XmlSchemaSimpleType)typeSchema.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;
+ }
+
+ 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;
+ }
+}
Propchange: webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaScope.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaTypeInfo.java
URL: http://svn.apache.org/viewvc/webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaTypeInfo.java?rev=1625632&view=auto
==============================================================================
--- webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaTypeInfo.java (added)
+++ webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaTypeInfo.java Wed Sep 17 15:32:44 2014
@@ -0,0 +1,254 @@
+/**
+ * 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.HashMap;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+/**
+ * Represents an element's or attribute's type, meaning either a
+ * {@link XmlSchemaBaseSimpleType} with facets, a union or list of them, or a
+ * complex type.
+ * <p>
+ * Also maintains a {@link QName} representing a type the user recognizes. Users
+ * attempting to convert from one schema to another may use this to track which
+ * types in XML Schema map to their own schema types.
+ * </p>
+ */
+public final class XmlSchemaTypeInfo {
+
+ private Type type;
+ private HashMap<XmlSchemaRestriction.Type, List<XmlSchemaRestriction>> facets;
+ private boolean isMixed;
+ private XmlSchemaBaseSimpleType baseSimpleType;
+ private QName userRecognizedType;
+ private List<XmlSchemaTypeInfo> childTypes;
+
+ /**
+ * What the data in this <code>XmlSchemaTypeInfo</code> represents. It may
+ * be a simple type ({@link XmlSchemaBaseSimpleType}), a list or union of
+ * simple types, or a complex type.
+ * <p>
+ * Complex types are reserved for when an element only contains attributes,
+ * or the element's children are mixed with text.
+ * </p>
+ */
+ public enum Type {
+ LIST, UNION, ATOMIC, COMPLEX;
+ }
+
+ /**
+ * Constructs a new <code>XmlSchemaTypeInfo</code> representing a list of
+ * other <code>XmlSchemaTypeInfo</code>s. Lists are homogeneous, so only one
+ * type is necessary.
+ * <p>
+ * Lists may be either of atomic types or unions of atomic types. Lists of
+ * lists are not allowed.
+ * </p>
+ *
+ * @param listType The list's type.
+ */
+ public XmlSchemaTypeInfo(XmlSchemaTypeInfo listType) {
+ type = Type.LIST;
+ childTypes = new ArrayList<XmlSchemaTypeInfo>(1);
+ childTypes.add(listType);
+
+ isMixed = false;
+ facets = null;
+ userRecognizedType = null;
+ }
+
+ /**
+ * Constructs a list with facets. Lists may be constrained by their length;
+ * meaning they may have a {@link XmlSchemaRestriction.Type#LENGTH} facet, a
+ * {@link XmlSchemaRestriction.Type#LENGTH_MIN} facet, or a
+ * {@link XmlSchemaRestriction.Type#LENGTH_MAX} facet (or both
+ * <code>LENGTH_MIN</code> and <code>LENGTH_MAX</code>).
+ *
+ * @param listType The list type.
+ * @param facets Constraining facets on the list itself.
+ */
+ public XmlSchemaTypeInfo(XmlSchemaTypeInfo listType,
+ HashMap<XmlSchemaRestriction.Type, List<XmlSchemaRestriction>> facets) {
+ this(listType);
+ this.facets = facets;
+ }
+
+ /**
+ * Constructs a union with the set of valid types a value adhering to the
+ * union must conform to.
+ * <p>
+ * A union may either be of a set of atomic types or a set of list types,
+ * but not mixed between the two. A union of list types cannot be a type of
+ * a list.
+ * </p>
+ *
+ * @param unionTypes The set of types that a value may adhere to in order to
+ * conform to the union.
+ */
+ public XmlSchemaTypeInfo(List<XmlSchemaTypeInfo> unionTypes) {
+ type = Type.UNION;
+ childTypes = unionTypes;
+
+ isMixed = false;
+ facets = null;
+ userRecognizedType = null;
+ }
+
+ /**
+ * Constructs a union with the set of valid types the a value adhering to
+ * the union must conform to, along with any constraining facets on the
+ * union itself.
+ *
+ * @param unionTypes The set of types that a value must adhere to.
+ * @param facets Constraining facets on the union.
+ */
+ public XmlSchemaTypeInfo(List<XmlSchemaTypeInfo> unionTypes,
+ HashMap<XmlSchemaRestriction.Type, List<XmlSchemaRestriction>> facets) {
+ this(unionTypes);
+ this.facets = facets;
+ }
+
+ /**
+ * Constructs an atomic type with the {@link XmlSchemaBaseSimpleType}
+ * conforming values must adhere to.
+ *
+ * @param baseSimpleType The value type.
+ */
+ public XmlSchemaTypeInfo(XmlSchemaBaseSimpleType baseSimpleType) {
+ if (baseSimpleType.equals(XmlSchemaBaseSimpleType.ANYTYPE)) {
+ type = Type.COMPLEX;
+ } else {
+ type = Type.ATOMIC;
+ }
+
+ this.baseSimpleType = baseSimpleType;
+
+ isMixed = false;
+ facets = null;
+ childTypes = null;
+ userRecognizedType = null;
+ }
+
+ /**
+ * Constructs an atomic type with the {@link XmlSchemaBaseSimpleType}
+ * conforming values must adhere to, along with any additional constraining
+ * facets.
+ *
+ * @param baseSimpleType The value type.
+ * @param facets The constraining facets on the value.
+ */
+ public XmlSchemaTypeInfo(XmlSchemaBaseSimpleType baseSimpleType,
+ HashMap<XmlSchemaRestriction.Type, List<XmlSchemaRestriction>> facets) {
+
+ this(baseSimpleType);
+ this.facets = facets;
+ }
+
+ /**
+ * Constructs a complex type whose value may or may not be mixed.
+ *
+ * @param isMixed Whether the element is a mixed type.
+ */
+ public XmlSchemaTypeInfo(boolean isMixed) {
+ type = Type.COMPLEX;
+ baseSimpleType = XmlSchemaBaseSimpleType.ANYTYPE;
+ this.isMixed = isMixed;
+
+ facets = null;
+ childTypes = null;
+ userRecognizedType = null;
+ }
+
+ /**
+ * The set of constraining facets on the value, or <code>null</code> if
+ * none.
+ */
+ public HashMap<XmlSchemaRestriction.Type, List<XmlSchemaRestriction>> getFacets() {
+ return facets;
+ }
+
+ /**
+ * If this represents an atomic type, returns the type. If this is a complex
+ * type, returns {@link XmlSchemaBaseSimpleType#ANYTYPE}.
+ */
+ public XmlSchemaBaseSimpleType getBaseType() {
+ return baseSimpleType;
+ }
+
+ /**
+ * The type represented by this <code>XmlSchemaTypeInfo</code>.
+ */
+ public Type getType() {
+ return type;
+ }
+
+ /**
+ * If this represents a list or a union, returns the set of children types.
+ * (Lists will only have one child type.)
+ * <p>
+ * Otherwise, returns <code>null</code>.
+ * </p>
+ */
+ public List<XmlSchemaTypeInfo> getChildTypes() {
+ return childTypes;
+ }
+
+ /**
+ * The corresponding user-defined type, or <code>null</code> if none.
+ */
+ public QName getUserRecognizedType() {
+ return userRecognizedType;
+ }
+
+ /**
+ * If this is a complex type, returns whether its value is mixed. Otherwise,
+ * returns <code>false</code>.
+ */
+ public boolean isMixed() {
+ return isMixed;
+ }
+
+ /**
+ * Sets the user-recognized type.
+ *
+ * @param userRecType The user-recognized type.
+ */
+ public void setUserRecognizedType(QName userRecType) {
+ userRecognizedType = userRecType;
+ }
+
+ /**
+ * A {@link String} representation of this <code>XmlSchemaTypeInfo</code>.
+ */
+ @Override
+ public String toString() {
+ StringBuilder str = new StringBuilder("XmlSchemaTypeInfo [");
+ str.append(type).append("] Base Type: ").append(baseSimpleType);
+ str.append(" User Recognized Type: ").append(userRecognizedType);
+ str.append(" Is Mixed: ").append(isMixed);
+ str.append(" Num Children: ");
+ str.append((childTypes == null) ? 0 : childTypes.size());
+ return str.toString();
+ }
+}
Propchange: webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaTypeInfo.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaVisitor.java
URL: http://svn.apache.org/viewvc/webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaVisitor.java?rev=1625632&view=auto
==============================================================================
--- webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaVisitor.java (added)
+++ webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaVisitor.java Wed Sep 17 15:32:44 2014
@@ -0,0 +1,194 @@
+/**
+ * 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 org.apache.ws.commons.schema.XmlSchemaAll;
+import org.apache.ws.commons.schema.XmlSchemaAny;
+import org.apache.ws.commons.schema.XmlSchemaAnyAttribute;
+import org.apache.ws.commons.schema.XmlSchemaChoice;
+import org.apache.ws.commons.schema.XmlSchemaElement;
+import org.apache.ws.commons.schema.XmlSchemaSequence;
+
+/**
+ * Defines a visitor interface for notifications when walking an
+ * {@link org.apache.ws.commons.schema.XmlSchema} using the
+ * {@link XmlSchemaWalker}.
+ * <p>
+ * Use this interface in conjunction with <code>XmlSchemaWalker</code> to
+ * receive events as an {@link org.apache.ws.commons.schema.XmlSchema} is
+ * traversed.
+ * </p>
+ */
+public interface XmlSchemaVisitor {
+
+ /**
+ * A notification that an {@link XmlSchemaElement} has been entered. The
+ * element returned will be a true representation of the element at that
+ * point in the schema: if the schema defines a reference, the reference is
+ * followed and merged with its global definition.
+ * <p>
+ * The first time this element is reached, all of its attributes will be
+ * visited (if any). Once the attributes have been visited,
+ * {@link #onEndAttributes(XmlSchemaElement, XmlSchemaTypeInfo)} will be
+ * called. The only exception is when the element has no type information,
+ * at which point the next call will be to
+ * {@link #onExitElement(XmlSchemaElement, XmlSchemaTypeInfo, boolean)}.
+ * </p>
+ * <p>
+ * On all subsequent visits to this element, <code>previouslyVisited</code>
+ * will be set to <code>true</code> and the attributes will not be
+ * revisited. The next call will be to
+ * {@link #onExitElement(XmlSchemaElement, XmlSchemaTypeInfo, boolean)}, as
+ * all of the element's attributes and children have already been provided.
+ * </p>
+ *
+ * @param element The element the walker is currently entering.
+ * @param typeInfo The type information of that element.
+ * @param previouslyVisited Whether the element was previously visited.
+ */
+ void onEnterElement(XmlSchemaElement element, XmlSchemaTypeInfo typeInfo, boolean previouslyVisited);
+
+ /**
+ * Signifies the end of the element that was previously entered. Provides
+ * the same information about the element as was provided in
+ * {@link #onEnterElement(XmlSchemaElement, XmlSchemaTypeInfo, boolean)} in
+ * the event it is easier to process on exit.
+ *
+ * @param element The element the walker is currently exiting.
+ * @param typeInfo The type information of that element.
+ * @param previouslyVisited Whether the element was previously visited.
+ */
+ void onExitElement(XmlSchemaElement element, XmlSchemaTypeInfo typeInfo, boolean previouslyVisited);
+
+ /**
+ * This method is called for each attribute associated with the element,
+ * providing the {@link XmlSchemaAttrInfo} representing that attribute.
+ *
+ * @param element The element owing the attribute.
+ * @param attrInfo The attribute information.
+ */
+ void onVisitAttribute(XmlSchemaElement element, XmlSchemaAttrInfo attrInfo);
+
+ /**
+ * This method is called when all of the attributes have been processed
+ * (provided the element has a type defined). This is a convenience method
+ * to allow the visitor to be notified when no more attributes are coming,
+ * and the walker will be traversing the element's children.
+ *
+ * @param element The element the walker is traversing.
+ * @param typeInfo Type information about the element, if it is easier to
+ * process here.
+ */
+ void onEndAttributes(XmlSchemaElement element, XmlSchemaTypeInfo typeInfo);
+
+ /**
+ * This method is called when the walker enters a substitution group. This
+ * method is called providing the base type, and then
+ * {@link #onEnterElement(XmlSchemaElement, XmlSchemaTypeInfo, boolean)} is
+ * called for all types in the substitution group, starting with the base
+ * type.
+ * <p>
+ * The only exception is when the base type of the substitution group is
+ * abstract ({@link XmlSchemaElement#isAbstract()} returns <code>true</code>
+ * ). When this happens,
+ * {@link #onEnterElement(XmlSchemaElement, XmlSchemaTypeInfo, boolean)} is
+ * not called with the abstract type, as there is no information to provide.
+ * </p>
+ * <p>
+ * If the root element is the base of a substitution group, this method will
+ * be the first one called. Otherwise,
+ * {@link #onEnterElement(XmlSchemaElement, XmlSchemaTypeInfo, boolean)}
+ * will be called with the root element.
+ * </p>
+ *
+ * @param base The {@link XmlSchemaElement} representing the base of the
+ * substitution group.
+ */
+ void onEnterSubstitutionGroup(XmlSchemaElement base);
+
+ /**
+ * Called when the end of the substitution group is reached. The base
+ * element of the substitution group is provided for convenience.
+ *
+ * @param base The base element of the subtitution group.
+ */
+ void onExitSubstitutionGroup(XmlSchemaElement base);
+
+ /**
+ * Called when an all group is entered.
+ *
+ * @param all The {@link XmlSchemaAll} representing the all group.
+ */
+ void onEnterAllGroup(XmlSchemaAll all);
+
+ /**
+ * Called when an all group is exited.
+ *
+ * @param all The {@link XmlSchemaAll} representing the all group.
+ */
+ void onExitAllGroup(XmlSchemaAll all);
+
+ /**
+ * Called when a choice group is entered.
+ *
+ * @param all The {@link XmlSchemaChoice} representing the choice group.
+ */
+ void onEnterChoiceGroup(XmlSchemaChoice choice);
+
+ /**
+ * Called when a choice group is exited.
+ *
+ * @param all The {@link XmlSchemaChoice} representing the choice group.
+ */
+ void onExitChoiceGroup(XmlSchemaChoice choice);
+
+ /**
+ * Called when a sequence is entered.
+ *
+ * @param seq The {@link XmlSchemaSequence} representing the sequence.
+ */
+ void onEnterSequenceGroup(XmlSchemaSequence seq);
+
+ /**
+ * Called when a sequence is exited.
+ *
+ * @param seq The {@link XmlSchemaSequence} representing the sequence.
+ */
+ void onExitSequenceGroup(XmlSchemaSequence seq);
+
+ /**
+ * Called when a wildcard element is entered.
+ *
+ * @param any The {@link XmlSchemaAny} representing the wildcard element.
+ */
+ void onVisitAny(XmlSchemaAny any);
+
+ /**
+ * Called when a wildcard attribute is visited. If an element has a wildcard
+ * element, this will be called after all other attributes have been
+ * visited, and before the call to
+ * {@link #onEndAttributes(XmlSchemaElement, XmlSchemaTypeInfo)}.
+ *
+ * @param element The owning element.
+ * @param anyAttr The {@link XmlSchemaAnyAttribute} representing the
+ * wildcard attribute.
+ */
+ void onVisitAnyAttribute(XmlSchemaElement element, XmlSchemaAnyAttribute anyAttr);
+}
Propchange: webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaVisitor.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaWalker.java
URL: http://svn.apache.org/viewvc/webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaWalker.java?rev=1625632&view=auto
==============================================================================
--- webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaWalker.java (added)
+++ webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaWalker.java Wed Sep 17 15:32:44 2014
@@ -0,0 +1,559 @@
+/**
+ * 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.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.XmlSchemaAll;
+import org.apache.ws.commons.schema.XmlSchemaAny;
+import org.apache.ws.commons.schema.XmlSchemaChoice;
+import org.apache.ws.commons.schema.XmlSchemaCollection;
+import org.apache.ws.commons.schema.XmlSchemaElement;
+import org.apache.ws.commons.schema.XmlSchemaGroup;
+import org.apache.ws.commons.schema.XmlSchemaGroupParticle;
+import org.apache.ws.commons.schema.XmlSchemaGroupRef;
+import org.apache.ws.commons.schema.XmlSchemaObject;
+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.XmlSchemaType;
+
+/**
+ * Walks an {@link XmlSchema} from a starting {@link XmlSchemaElement},
+ * notifying attached visitors as it descends.
+ */
+public final class XmlSchemaWalker {
+
+ private Set<QName> userRecognizedTypes;
+
+ private final XmlSchemaCollection schemas;
+ private final ArrayList<XmlSchemaVisitor> visitors;
+ private final Map<QName, List<XmlSchemaElement>> elemsBySubstGroup;
+ private final Map<String, XmlSchema> schemasByNamespace;
+ private final Map<QName, XmlSchemaScope> scopeCache;
+ private final Set<QName> visitedElements;
+
+ /**
+ * Initializes the {@link XmlSchemaWalker} with the
+ * {@link XmlScheamCollection} to reference when following an
+ * {@link XmlSchemaElement}.
+ */
+ public XmlSchemaWalker(XmlSchemaCollection xmlSchemas) {
+ if (xmlSchemas == null) {
+ throw new IllegalArgumentException("Input XmlSchemaCollection cannot be null.");
+ }
+
+ schemas = xmlSchemas;
+ visitors = new ArrayList<XmlSchemaVisitor>(1);
+
+ schemasByNamespace = new HashMap<String, XmlSchema>();
+ elemsBySubstGroup = new HashMap<QName, List<XmlSchemaElement>>();
+
+ for (XmlSchema schema : schemas.getXmlSchemas()) {
+ schemasByNamespace.put(schema.getTargetNamespace(), schema);
+
+ for (XmlSchemaElement elem : schema.getElements().values()) {
+ if (elem.getSubstitutionGroup() != null) {
+ List<XmlSchemaElement> elems = elemsBySubstGroup.get(elem.getSubstitutionGroup());
+ if (elems == null) {
+ elems = new ArrayList<XmlSchemaElement>();
+ elemsBySubstGroup.put(elem.getSubstitutionGroup(), elems);
+ }
+ elems.add(elem);
+ }
+ }
+ }
+
+ scopeCache = new HashMap<QName, XmlSchemaScope>();
+ visitedElements = new java.util.HashSet<QName>();
+ userRecognizedTypes = null;
+ }
+
+ /**
+ * Initializes the <code>XmlSchemaWalker</code> with an
+ * {@link XmlSchemaVisitor} to notify as the schema is walked.
+ * <p>
+ * (Other visitors may continue to be added after this one.)
+ * </p>
+ *
+ * @param xmlSchemas The set of schemas to walk.
+ * @param visitor The visitor to visit during the walk.
+ */
+ public XmlSchemaWalker(XmlSchemaCollection xmlSchemas, XmlSchemaVisitor visitor) {
+
+ this(xmlSchemas);
+ if (visitor != null) {
+ visitors.add(visitor);
+ }
+ }
+
+ /**
+ * Adds a new visitor to be notified as the XML Schemas are walked.
+ *
+ * @param visitor The visitor to be notified.
+ * @return This <code>XmlSchemaWalker</code> instance for method chaining.
+ */
+ public XmlSchemaWalker addVisitor(XmlSchemaVisitor visitor) {
+ visitors.add(visitor);
+ return this;
+ }
+
+ /**
+ * Removes the visitor to be notified as the XML Schemas are walked.
+ *
+ * @param visitor The visitor to remove.
+ * @return This <code>XmlSchemaWalker</code> instance for method chaining.
+ */
+ public XmlSchemaWalker removeVisitor(XmlSchemaVisitor visitor) {
+ if (visitor != null) {
+ visitors.remove(visitor);
+ }
+ return this;
+ }
+
+ /**
+ * Clears the internal state in preparation for another walk through the
+ * schema.
+ */
+ public void clear() {
+ scopeCache.clear();
+ visitedElements.clear();
+ }
+
+ /**
+ * Defines the set of types the calling code recognizes. If one of the types
+ * are found during the walk through the XML Schema, it is attached to the
+ * relevant {@link XmlSchemaTypeInfo} that is passed to the
+ * {@link XmlSchemaVisitor}s, with lower types in the hierarchy taking
+ * precedence over higher types.
+ * <p>
+ * This information is useful when translating from XML Schema to another
+ * schema, as this automatically associates the destination type with the
+ * source XML Schema type.
+ * </p>
+ *
+ * @param userRecognizedTypes The set of types the user recognizes and would
+ * like recognized when traversed.
+ */
+ public void setUserRecognizedTypes(Set<QName> userRecognizedTypes) {
+ this.userRecognizedTypes = userRecognizedTypes;
+ }
+
+ /**
+ * The user-defined types set with the call to
+ * {@link #setUserRecognizedTypes(Set)}, or <code>null</code> if none.
+ */
+ public Set<QName> getUserRecognizedTypes() {
+ return userRecognizedTypes;
+ }
+
+ /**
+ * Initiates a walk through the {@link XmlSchemaCollection} starting with
+ * the provided root {@link XmlSchemaElement}. Any visitors will be notified
+ * as the walk progresses.
+ * <p>
+ * Once this method completes, call {@link #clear()} before starting another
+ * walk through the XML Schemas.
+ * </p>
+ *
+ * @param element The root element to start the walk from.
+ */
+ public void walk(XmlSchemaElement element) {
+ element = getElement(element, false);
+
+ final XmlSchemaElement substGroupElem = element;
+
+ /*
+ * If this element is the root of a substitution group, notify the
+ * visitors.
+ */
+ List<XmlSchemaElement> substitutes = null;
+ if (elemsBySubstGroup.containsKey(getElementQName(element))) {
+ substitutes = elemsBySubstGroup.get(element.getQName());
+
+ for (XmlSchemaVisitor visitor : visitors) {
+ visitor.onEnterSubstitutionGroup(substGroupElem);
+ }
+
+ // Force a copy to change the min & max occurs.
+ element = getElement(element, true);
+ element.setMinOccurs(XmlSchemaParticle.DEFAULT_MIN_OCCURS);
+ element.setMaxOccurs(XmlSchemaParticle.DEFAULT_MAX_OCCURS);
+ }
+
+ XmlSchemaType schemaType = element.getSchemaType();
+ if (schemaType == null) {
+ final QName typeQName = element.getSchemaTypeName();
+ if (typeQName != null) {
+ XmlSchema schema = schemasByNamespace.get(typeQName.getNamespaceURI());
+ schemaType = schema.getTypeByName(typeQName);
+ }
+ }
+
+ if (schemaType != null) {
+ XmlSchemaScope scope = null;
+ if ((schemaType.getQName() != null) && scopeCache.containsKey(schemaType.getQName())) {
+ scope = scopeCache.get(schemaType.getQName());
+ } else {
+ scope = new XmlSchemaScope(schemaType, schemasByNamespace, scopeCache, userRecognizedTypes);
+ if (schemaType.getQName() != null) {
+ scopeCache.put(schemaType.getQName(), scope);
+ }
+ }
+
+ // 1. Fetch all attributes as a List<XmlSchemaAttribute>.
+ final Collection<XmlSchemaAttrInfo> attrs = scope.getAttributesInScope();
+ final XmlSchemaTypeInfo typeInfo = scope.getTypeInfo();
+
+ // 2. for each visitor, call visitor.startElement(element, type);
+ final boolean previouslyVisited = (!element.isAnonymous() && visitedElements.contains(element
+ .getQName()));
+
+ for (XmlSchemaVisitor visitor : visitors) {
+ visitor.onEnterElement(element, typeInfo, previouslyVisited);
+ }
+
+ if (!element.isAnonymous() && !previouslyVisited) {
+ visitedElements.add(element.getQName());
+ }
+
+ // If we already visited this element, skip the attributes and
+ // child.
+ if (!previouslyVisited) {
+
+ // 3. Walk the attributes in the element, retrieving type
+ // information.
+ if (attrs != null) {
+ for (XmlSchemaAttrInfo attr : attrs) {
+ XmlSchemaType attrType = attr.getAttribute().getSchemaType();
+ XmlSchemaScope attrScope = null;
+ if ((attrType.getQName() != null) && scopeCache.containsKey(attrType.getQName())) {
+ attrScope = scopeCache.get(attrType.getQName());
+ } else {
+ attrScope = new XmlSchemaScope(attr.getAttribute().getSchemaType(),
+ schemasByNamespace, scopeCache,
+ userRecognizedTypes);
+
+ if (attrType.getName() != null) {
+ scopeCache.put(attrType.getQName(), attrScope);
+ }
+ }
+
+ final XmlSchemaTypeInfo attrTypeInfo = attrScope.getTypeInfo();
+ attr.setType(attrTypeInfo);
+
+ for (XmlSchemaVisitor visitor : visitors) {
+ visitor.onVisitAttribute(element, attr);
+ }
+ }
+ }
+
+ // 4. Visit the anyAttribute, if any.
+ if (scope.getAnyAttribute() != null) {
+ for (XmlSchemaVisitor visitor : visitors) {
+ visitor.onVisitAnyAttribute(element, scope.getAnyAttribute());
+ }
+ }
+
+ /*
+ * 5. Notify that we visited all of the attributes (even if
+ * there weren't any).
+ */
+ for (XmlSchemaVisitor visitor : visitors) {
+ visitor.onEndAttributes(element, typeInfo);
+ }
+
+ // 6. Walk the child groups and elements (if any), depth-first.
+ final XmlSchemaParticle child = scope.getParticle();
+ if (child != null) {
+ walk(child);
+ }
+ }
+
+ /*
+ * 7. On the way back up, call visitor.endElement(element, type,
+ * attributes);
+ */
+ for (XmlSchemaVisitor visitor : visitors) {
+ visitor.onExitElement(element, typeInfo, previouslyVisited);
+ }
+
+ } else if (!element.isAbstract()) {
+ throw new IllegalStateException("Element " + element.getQName()
+ + " is not abstract and has no type.");
+ }
+
+ // 8. Now handle substitute elements, if any.
+ if (substitutes != null) {
+ for (XmlSchemaElement substitute : substitutes) {
+ walk(substitute);
+ }
+
+ for (XmlSchemaVisitor visitor : visitors) {
+ visitor.onExitSubstitutionGroup(substGroupElem);
+ }
+ }
+ }
+
+ private void walk(XmlSchemaParticle particle) {
+ if (particle instanceof XmlSchemaGroupRef) {
+ XmlSchemaGroupRef groupRef = (XmlSchemaGroupRef)particle;
+ XmlSchemaGroupParticle group = groupRef.getParticle();
+ if (group == null) {
+ XmlSchema schema = schemasByNamespace.get(groupRef.getRefName().getNamespaceURI());
+
+ group = schema.getGroupByName(groupRef.getRefName()).getParticle();
+ }
+ walk(group, groupRef.getMinOccurs(), groupRef.getMaxOccurs());
+
+ } else if (particle instanceof XmlSchemaGroupParticle) {
+ walk((XmlSchemaGroupParticle)particle, particle.getMinOccurs(), particle.getMaxOccurs());
+
+ } else if (particle instanceof XmlSchemaElement) {
+ walk((XmlSchemaElement)particle);
+
+ } else if (particle instanceof XmlSchemaAny) {
+ for (XmlSchemaVisitor visitor : visitors) {
+ visitor.onVisitAny((XmlSchemaAny)particle);
+ }
+
+ } else {
+ throw new IllegalArgumentException("Unknown particle type " + particle.getClass().getName());
+ }
+
+ }
+
+ private void walk(XmlSchemaGroupParticle group, long minOccurs, long maxOccurs) {
+
+ // Only make a copy of the particle if the minOccurs or maxOccurs was
+ // set.
+ final boolean forceCopy = ((minOccurs != group.getMinOccurs()) || (maxOccurs != group.getMaxOccurs()));
+
+ // 1. Determine the group particle type.
+ XmlSchemaAll all = null;
+ XmlSchemaChoice choice = null;
+ XmlSchemaSequence seq = null;
+
+ ArrayList<XmlSchemaParticle> children = null;
+
+ if (group instanceof XmlSchemaAll) {
+ all = (XmlSchemaAll)group;
+
+ } else if (group instanceof XmlSchemaChoice) {
+ choice = (XmlSchemaChoice)group;
+
+ } else if (group instanceof XmlSchemaSequence) {
+ seq = (XmlSchemaSequence)group;
+
+ } else {
+ throw new IllegalArgumentException("Unrecognized XmlSchemaGroupParticle of type "
+ + group.getClass().getName());
+ }
+
+ // 2. Make a copy if necessary.
+ if (forceCopy) {
+ if (all != null) {
+ XmlSchemaAll copy = new XmlSchemaAll();
+ copy.setAnnotation(all.getAnnotation());
+ copy.setId(all.getId());
+ copy.setLineNumber(all.getLineNumber());
+ copy.setLinePosition(all.getLinePosition());
+ copy.setMetaInfoMap(all.getMetaInfoMap());
+ copy.setMinOccurs(minOccurs);
+ copy.setMaxOccurs(maxOccurs);
+ copy.setSourceURI(all.getSourceURI());
+ copy.setUnhandledAttributes(all.getUnhandledAttributes());
+ copy.getItems().addAll(all.getItems());
+
+ all = copy;
+
+ } else if (choice != null) {
+ XmlSchemaChoice copy = new XmlSchemaChoice();
+ copy.setAnnotation(choice.getAnnotation());
+ copy.setId(choice.getId());
+ copy.setLineNumber(choice.getLineNumber());
+ copy.setLinePosition(choice.getLinePosition());
+ copy.setMinOccurs(minOccurs);
+ copy.setMaxOccurs(maxOccurs);
+ copy.setMetaInfoMap(choice.getMetaInfoMap());
+ copy.setSourceURI(choice.getSourceURI());
+ copy.setUnhandledAttributes(choice.getUnhandledAttributes());
+ copy.getItems().addAll(choice.getItems());
+
+ choice = copy;
+
+ } else if (seq != null) {
+ XmlSchemaSequence copy = new XmlSchemaSequence();
+ copy.setAnnotation(seq.getAnnotation());
+ copy.setId(seq.getId());
+ copy.setLineNumber(seq.getLineNumber());
+ copy.setLinePosition(seq.getLinePosition());
+ copy.setMinOccurs(minOccurs);
+ copy.setMaxOccurs(maxOccurs);
+ copy.setMetaInfoMap(seq.getMetaInfoMap());
+ copy.setSourceURI(seq.getSourceURI());
+ copy.setUnhandledAttributes(seq.getUnhandledAttributes());
+
+ seq = copy;
+ }
+ }
+
+ // 3. Notify the visitors.
+ for (XmlSchemaVisitor visitor : visitors) {
+ if (all != null) {
+ visitor.onEnterAllGroup(all);
+ } else if (choice != null) {
+ visitor.onEnterChoiceGroup(choice);
+ } else if (seq != null) {
+ visitor.onEnterSequenceGroup(seq);
+ }
+ }
+
+ // 4. Walk the children.
+ if (all != null) {
+ children = new ArrayList<XmlSchemaParticle>(all.getItems().size());
+ children.addAll(all.getItems());
+
+ } else if (choice != null) {
+ children = new ArrayList<XmlSchemaParticle>(choice.getItems().size());
+ for (XmlSchemaObject item : choice.getItems()) {
+ if (item instanceof XmlSchemaGroup) {
+ children.add(((XmlSchemaGroup)item).getParticle());
+ } else if (item instanceof XmlSchemaParticle) {
+ children.add((XmlSchemaParticle)item);
+ } else {
+ throw new IllegalArgumentException(
+ "Choice child is not an XmlSchemaGroup or XmlSchemaParticle; "
+ + "it is a " + item.getClass().getName());
+ }
+ }
+
+ } else if (seq != null) {
+ children = new ArrayList<XmlSchemaParticle>(seq.getItems().size());
+ for (XmlSchemaSequenceMember item : seq.getItems()) {
+ if (item instanceof XmlSchemaGroup) {
+ children.add(((XmlSchemaGroup)item).getParticle());
+ } else if (item instanceof XmlSchemaParticle) {
+ children.add((XmlSchemaParticle)item);
+ } else {
+ throw new IllegalArgumentException(
+ "Sequence child is not an XmlSchemaGroup or XmlSchemaParticle; "
+ + "it is a " + item.getClass().getName());
+ }
+ }
+ }
+
+ if (children == null) {
+ throw new IllegalStateException("Could not process group of type " + group.getClass().getName());
+ }
+
+ for (XmlSchemaParticle child : children) {
+ walk(child);
+ }
+
+ // 5. Notify the visitors we are exiting the group.
+ for (XmlSchemaVisitor visitor : visitors) {
+ if (all != null) {
+ visitor.onExitAllGroup(all);
+ } else if (choice != null) {
+ visitor.onExitChoiceGroup(choice);
+ } else if (seq != null) {
+ visitor.onExitSequenceGroup(seq);
+ }
+ }
+ }
+
+ /**
+ * If the provided {@link XmlSchemaElement} is a reference, track down the
+ * original and add the minimum and maximum occurrence fields. Otherwise,
+ * just return the provided <code>element</code>.
+ *
+ * @param element The element to get the definition of.
+ * @return The real {@link XmlSchemaElement}.
+ */
+ private XmlSchemaElement getElement(XmlSchemaElement element, boolean isSubstitutionGroup) {
+
+ if (!element.isRef() && !isSubstitutionGroup) {
+ return element;
+ }
+
+ final QName elemQName = getElementQName(element);
+ final XmlSchema schema = schemasByNamespace.get(elemQName.getNamespaceURI());
+
+ XmlSchemaElement globalElem = null;
+ if (!element.isRef()) {
+ globalElem = element;
+ } else if (element.getRef().getTarget() != null) {
+ globalElem = element.getRef().getTarget();
+ } else {
+ globalElem = schema.getElementByName(elemQName);
+ }
+
+ /*
+ * An XML Schema element reference defines the id, minOccurs, and
+ * maxOccurs attributes, while the global element definition defines id
+ * and all other attributes. This combines the two together.
+ */
+ String id = element.getId();
+ if (id == null) {
+ id = globalElem.getId();
+ }
+
+ final XmlSchemaElement copy = new XmlSchemaElement(schema, false);
+ copy.setName(globalElem.getName());
+ copy.setAbstract(globalElem.isAbstract());
+ copy.setAnnotation(globalElem.getAnnotation());
+ copy.setBlock(globalElem.getBlock());
+ copy.setDefaultValue(globalElem.getDefaultValue());
+ copy.setFinal(globalElem.getFinal());
+ copy.setFixedValue(globalElem.getFixedValue());
+ copy.setForm(globalElem.getForm());
+ copy.setId(id);
+ copy.setLineNumber(element.getLineNumber());
+ copy.setLinePosition(element.getLinePosition());
+ copy.setMaxOccurs(element.getMaxOccurs());
+ copy.setMinOccurs(element.getMinOccurs());
+ copy.setMetaInfoMap(globalElem.getMetaInfoMap());
+ copy.setNillable(globalElem.isNillable());
+ copy.setType(globalElem.getSchemaType());
+ copy.setSchemaTypeName(globalElem.getSchemaTypeName());
+ copy.setSourceURI(globalElem.getSourceURI());
+ copy.setSubstitutionGroup(globalElem.getSubstitutionGroup());
+ copy.setUnhandledAttributes(globalElem.getUnhandledAttributes());
+
+ return copy;
+ }
+
+ private static QName getElementQName(XmlSchemaElement element) {
+ if (element.isRef()) {
+ return element.getRefBase().getTargetQName();
+ } else {
+ return element.getQName();
+ }
+ }
+}
Propchange: webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaWalker.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/package-info.java
URL: http://svn.apache.org/viewvc/webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/package-info.java?rev=1625632&view=auto
==============================================================================
--- webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/package-info.java (added)
+++ webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/package-info.java Wed Sep 17 15:32:44 2014
@@ -0,0 +1,35 @@
+/**
+ * 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.
+ */
+
+/**
+ * <h1>Walking XML Schemas</h1>
+ *
+ * This package simplifies walking over an
+ * {@link org.apache.ws.commons.schema.XmlSchemaCollection}.
+ *
+ * <h2>Walking an XML Schema</h2>
+ *
+ * {@link org.apache.ws.commons.schema.walker.XmlSchemaWalker} walks through an
+ * {@link org.apache.ws.commons.schema.XmlSchemaCollection} given a starting
+ * {@link org.apache.ws.commons.schema.XmlSchemaElement} representing the root.
+ * Instances of {@link org.apache.ws.commons.schema.walker.XmlSchemaVisitor}
+ * can be attached to receive notifications when each element, attribute, and
+ * group (subsitution group, choice group, all group, or sequence) is reached.
+ */
+package org.apache.ws.commons.schema.walker;
\ No newline at end of file
Propchange: webservices/xmlschema/trunk/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/package-info.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: webservices/xmlschema/trunk/xmlschema-walker/src/test/java/org/apache/ws/commons/schema/docpath/ExpectedElement.java
URL: http://svn.apache.org/viewvc/webservices/xmlschema/trunk/xmlschema-walker/src/test/java/org/apache/ws/commons/schema/docpath/ExpectedElement.java?rev=1625632&view=auto
==============================================================================
--- webservices/xmlschema/trunk/xmlschema-walker/src/test/java/org/apache/ws/commons/schema/docpath/ExpectedElement.java (added)
+++ webservices/xmlschema/trunk/xmlschema-walker/src/test/java/org/apache/ws/commons/schema/docpath/ExpectedElement.java Wed Sep 17 15:32:44 2014
@@ -0,0 +1,52 @@
+/**
+ * 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.docpath;
+
+import org.apache.ws.commons.schema.walker.XmlSchemaTypeInfo;
+
+import static org.junit.Assert.*;
+
+/**
+ * This is a simpler representation of an XML element to facilitate easier
+ * testing.
+ */
+class ExpectedElement {
+
+ private XmlSchemaTypeInfo typeInfo;
+
+ ExpectedElement(XmlSchemaTypeInfo typeInfo) {
+ this.typeInfo = typeInfo;
+ }
+
+ void validate(XmlSchemaDocumentNode docNode) {
+ String qName = docNode.getStateMachineNode().getElement().getQName().toString();
+
+ XmlSchemaTypeInfo actType = docNode.getStateMachineNode().getElementType();
+
+ validate(qName, actType);
+ }
+
+ void validate(String qName, XmlSchemaTypeInfo actType) {
+ assertEquals(qName, typeInfo.getType(), actType.getType());
+ assertEquals(qName, typeInfo.getBaseType(), actType.getBaseType());
+
+ assertEquals(qName, typeInfo.getUserRecognizedType(), actType.getUserRecognizedType());
+ }
+}
Propchange: webservices/xmlschema/trunk/xmlschema-walker/src/test/java/org/apache/ws/commons/schema/docpath/ExpectedElement.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: webservices/xmlschema/trunk/xmlschema-walker/src/test/java/org/apache/ws/commons/schema/docpath/ExpectedNode.java
URL: http://svn.apache.org/viewvc/webservices/xmlschema/trunk/xmlschema-walker/src/test/java/org/apache/ws/commons/schema/docpath/ExpectedNode.java?rev=1625632&view=auto
==============================================================================
--- webservices/xmlschema/trunk/xmlschema-walker/src/test/java/org/apache/ws/commons/schema/docpath/ExpectedNode.java (added)
+++ webservices/xmlschema/trunk/xmlschema-walker/src/test/java/org/apache/ws/commons/schema/docpath/ExpectedNode.java Wed Sep 17 15:32:44 2014
@@ -0,0 +1,95 @@
+/**
+ * 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.docpath;
+
+import static org.junit.Assert.*;
+
+import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+
+import javax.xml.namespace.QName;
+
+/**
+ * Describes an expected element or group in the document tree.
+ */
+public class ExpectedNode {
+
+ XmlSchemaStateMachineNode.Type nodeType;
+ long minOccurs;
+ long maxOccurs;
+ List<SortedMap<Integer, ExpectedNode>> children;
+ QName elemQName;
+
+ ExpectedNode(XmlSchemaStateMachineNode.Type nodeType, long minOccurs, long maxOccurs,
+ List<SortedMap<Integer, ExpectedNode>> children) {
+
+ this.nodeType = nodeType;
+ this.minOccurs = minOccurs;
+ this.maxOccurs = maxOccurs;
+ this.children = children;
+ }
+
+ void setElemQName(QName elemQName) {
+ this.elemQName = elemQName;
+ }
+
+ static void validate(String msg, ExpectedNode exp, XmlSchemaDocumentNode docNode,
+ Map<QName, ExpectedElement> expElements) {
+
+ assertEquals(msg, exp.nodeType, docNode.getStateMachineNode().getNodeType());
+
+ assertEquals(msg, exp.minOccurs, docNode.getMinOccurs());
+ assertEquals(msg, exp.maxOccurs, docNode.getMaxOccurs());
+ assertEquals(msg, exp.children.size(), docNode.getIteration());
+
+ if (docNode.getStateMachineNode().getNodeType().equals(XmlSchemaStateMachineNode.Type.ELEMENT)) {
+
+ QName actQName = docNode.getStateMachineNode().getElement().getQName();
+ assertEquals(msg, exp.elemQName, actQName);
+
+ if (expElements != null) {
+ ExpectedElement expElem = expElements.get(actQName);
+ assertNotNull(msg, expElem);
+ expElem.validate(docNode);
+ }
+ }
+
+ for (int iteration = 1; iteration <= docNode.getIteration(); ++iteration) {
+ SortedMap<Integer, ExpectedNode> expected = exp.children.get(iteration - 1);
+
+ SortedMap<Integer, XmlSchemaDocumentNode> actual = docNode.getChildren(iteration);
+
+ assertEquals(msg + ", iteration=" + iteration + "; " + exp.nodeType, expected.size(),
+ (actual == null) ? 0 : actual.size());
+
+ if (actual != null) {
+ for (Map.Entry<Integer, XmlSchemaDocumentNode> actEntry : actual.entrySet()) {
+ ExpectedNode expNode = expected.get(actEntry.getKey());
+ assertNotNull(msg + ", iteration=" + iteration + ", child = " + actEntry.getKey()
+ + ": entry " + actEntry.getKey() + " is not expected.", expNode);
+
+ validate(msg + "\titeration=" + iteration + "child=" + actEntry.getKey() + " ("
+ + exp.nodeType + ")", expNode, actEntry.getValue(), expElements);
+ }
+ }
+ }
+ }
+}
Propchange: webservices/xmlschema/trunk/xmlschema-walker/src/test/java/org/apache/ws/commons/schema/docpath/ExpectedNode.java
------------------------------------------------------------------------------
svn:eol-style = native