| /* |
| * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package com.sun.xml.internal.xsom.impl.scd; |
| |
| import com.sun.xml.internal.xsom.XSAttContainer; |
| import com.sun.xml.internal.xsom.XSAttGroupDecl; |
| import com.sun.xml.internal.xsom.XSAttributeDecl; |
| import com.sun.xml.internal.xsom.XSAttributeUse; |
| import com.sun.xml.internal.xsom.XSComplexType; |
| import com.sun.xml.internal.xsom.XSComponent; |
| import com.sun.xml.internal.xsom.XSElementDecl; |
| import com.sun.xml.internal.xsom.XSFacet; |
| import com.sun.xml.internal.xsom.XSIdentityConstraint; |
| import com.sun.xml.internal.xsom.XSListSimpleType; |
| import com.sun.xml.internal.xsom.XSModelGroup; |
| import com.sun.xml.internal.xsom.XSModelGroup.Compositor; |
| import com.sun.xml.internal.xsom.XSModelGroupDecl; |
| import com.sun.xml.internal.xsom.XSNotation; |
| import com.sun.xml.internal.xsom.XSParticle; |
| import com.sun.xml.internal.xsom.XSRestrictionSimpleType; |
| import com.sun.xml.internal.xsom.XSSchema; |
| import com.sun.xml.internal.xsom.XSSimpleType; |
| import com.sun.xml.internal.xsom.XSType; |
| import com.sun.xml.internal.xsom.XSUnionSimpleType; |
| import com.sun.xml.internal.xsom.XSWildcard; |
| |
| import java.util.ArrayList; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Set; |
| |
| /** |
| * Axis of traversal. |
| * |
| * @param <T> |
| * The kind of components that this axis may return. |
| * |
| * @author Kohsuke Kawaguchi |
| */ |
| public interface Axis<T extends XSComponent> { |
| Iterator<T> iterator(XSComponent contextNode); |
| |
| Iterator<T> iterator(Iterator<? extends XSComponent> contextNodes); |
| |
| /** |
| * Returns true if this is one of the model group axis. |
| */ |
| boolean isModelGroup(); |
| |
| |
| /** |
| * Pseudo-axis that selects all the {@link XSSchema}s in the current set. |
| * Used to implement the absolute path expression |
| */ |
| public static final Axis<XSSchema> ROOT = new Axis<XSSchema>() { |
| public Iterator<XSSchema> iterator(XSComponent contextNode) { |
| return contextNode.getRoot().iterateSchema(); |
| } |
| |
| public Iterator<XSSchema> iterator(Iterator<? extends XSComponent> contextNodes) { |
| if(!contextNodes.hasNext()) |
| return Iterators.empty(); |
| else |
| // this assumes that all current nodes belong to the same owner. |
| return iterator(contextNodes.next()); |
| } |
| |
| public boolean isModelGroup() { |
| return false; |
| } |
| |
| public String toString() { |
| return "root::"; |
| } |
| }; |
| |
| /** |
| * Pseudo-axis that visits all skipped intermediate steps. |
| * Those are: |
| * <ol> |
| * <li>complex type reachable from element |
| * <li>model groups |
| * <li>combination of above. |
| * </ol> |
| */ |
| public static final Axis<XSComponent> INTERMEDIATE_SKIP = new AbstractAxisImpl<XSComponent>() { |
| public Iterator<XSComponent> elementDecl(XSElementDecl decl) { |
| XSComplexType ct = decl.getType().asComplexType(); |
| if(ct==null) |
| return empty(); |
| else { |
| // also pick up model groups inside this complex type |
| return new Iterators.Union<XSComponent>(singleton(ct),complexType(ct)); |
| } |
| } |
| |
| public Iterator<XSComponent> modelGroupDecl(XSModelGroupDecl decl) { |
| return descendants(decl.getModelGroup()); |
| } |
| |
| public Iterator<XSComponent> particle(XSParticle particle) { |
| return descendants(particle.getTerm().asModelGroup()); |
| } |
| |
| /** |
| * Iterate all descendant model groups of the given model group, including itself. |
| */ |
| private Iterator<XSComponent> descendants(XSModelGroup mg) { |
| // TODO: write a tree iterator |
| // for now, we do it eagerly because I'm lazy |
| List<XSComponent> r = new ArrayList<XSComponent>(); |
| visit(mg,r); |
| return r.iterator(); |
| } |
| |
| private void visit(XSModelGroup mg, List<XSComponent> r) { |
| // since model groups never form a cycle, no cycle check is needed |
| r.add(mg); |
| for (XSParticle p : mg) { |
| XSModelGroup child = p.getTerm().asModelGroup(); |
| if(child!=null) |
| visit(child,r); |
| } |
| } |
| |
| public String toString() { |
| return "(intermediateSkip)"; |
| } |
| }; |
| |
| /** |
| * All descendants reachable via default axes. Used to implement the "//" semantics. |
| * |
| * So far the default axes together are guaranteed not to cause any cycle, so |
| * no cycle check is needed (if it's needed, the life would be much harder!) |
| */ |
| public static final Axis<XSComponent> DESCENDANTS = new Axis<XSComponent>() { |
| public Iterator<XSComponent> iterator(XSComponent contextNode) { |
| return new Visitor().iterator(contextNode); |
| } |
| public Iterator<XSComponent> iterator(Iterator<? extends XSComponent> contextNodes) { |
| return new Visitor().iterator(contextNodes); |
| } |
| |
| public boolean isModelGroup() { |
| return false; |
| } |
| |
| /** |
| * Stateful visitor that remembers what's already traversed, to reduce the search space. |
| */ |
| final class Visitor extends AbstractAxisImpl<XSComponent> { |
| private final Set<XSComponent> visited = new HashSet<XSComponent>(); |
| |
| /** |
| * Recursively apply the {@link Axis#DESCENDANTS} axis. |
| */ |
| final class Recursion extends Iterators.Map<XSComponent,XSComponent> { |
| public Recursion(Iterator<? extends XSComponent> core) { |
| super(core); |
| } |
| |
| protected Iterator<XSComponent> apply(XSComponent u) { |
| return DESCENDANTS.iterator(u); |
| } |
| } |
| public Iterator<XSComponent> schema(XSSchema schema) { |
| if(visited.add(schema)) |
| return ret( schema, new Recursion(schema.iterateElementDecls())); |
| else |
| return empty(); |
| } |
| |
| public Iterator<XSComponent> elementDecl(XSElementDecl decl) { |
| if(visited.add(decl)) |
| return ret(decl, iterator(decl.getType()) ); |
| else |
| return empty(); |
| } |
| |
| public Iterator<XSComponent> simpleType(XSSimpleType type) { |
| if(visited.add(type)) |
| return ret(type, FACET.iterator(type)); |
| else |
| return empty(); |
| } |
| |
| public Iterator<XSComponent> complexType(XSComplexType type) { |
| if(visited.add(type)) |
| return ret(type, iterator(type.getContentType())); |
| else |
| return empty(); |
| } |
| |
| public Iterator<XSComponent> particle(XSParticle particle) { |
| if(visited.add(particle)) |
| return ret(particle, iterator(particle.getTerm())); |
| else |
| return empty(); |
| } |
| |
| public Iterator<XSComponent> modelGroupDecl(XSModelGroupDecl decl) { |
| if(visited.add(decl)) |
| return ret(decl, iterator(decl.getModelGroup())); |
| else |
| return empty(); |
| } |
| |
| public Iterator<XSComponent> modelGroup(XSModelGroup group) { |
| if(visited.add(group)) |
| return ret(group, new Recursion(group.iterator())); |
| else |
| return empty(); |
| } |
| |
| public Iterator<XSComponent> attGroupDecl(XSAttGroupDecl decl) { |
| if(visited.add(decl)) |
| return ret(decl, new Recursion(decl.iterateAttributeUses())); |
| else |
| return empty(); |
| } |
| |
| public Iterator<XSComponent> attributeUse(XSAttributeUse use) { |
| if(visited.add(use)) |
| return ret(use, iterator(use.getDecl())); |
| else |
| return empty(); |
| } |
| |
| public Iterator<XSComponent> attributeDecl(XSAttributeDecl decl) { |
| if(visited.add(decl)) |
| return ret(decl, iterator(decl.getType())); |
| else |
| return empty(); |
| } |
| |
| private Iterator<XSComponent> ret( XSComponent one, Iterator<? extends XSComponent> rest ) { |
| return union(singleton(one),rest); |
| } |
| } |
| |
| public String toString() { |
| return "/"; |
| } |
| }; |
| |
| public static final Axis<XSSchema> X_SCHEMA = new Axis<XSSchema>() { |
| public Iterator<XSSchema> iterator(XSComponent contextNode) { |
| return Iterators.singleton(contextNode.getOwnerSchema()); |
| } |
| |
| public Iterator<XSSchema> iterator(Iterator<? extends XSComponent> contextNodes) { |
| return new Iterators.Adapter<XSSchema,XSComponent>(contextNodes) { |
| protected XSSchema filter(XSComponent u) { |
| return u.getOwnerSchema(); |
| } |
| }; |
| } |
| |
| public boolean isModelGroup() { |
| return false; |
| } |
| |
| public String toString() { |
| return "x-schema::"; |
| } |
| }; |
| |
| public static final Axis<XSElementDecl> SUBSTITUTION_GROUP = new AbstractAxisImpl<XSElementDecl>() { |
| public Iterator<XSElementDecl> elementDecl(XSElementDecl decl) { |
| return singleton(decl.getSubstAffiliation()); |
| } |
| |
| public String toString() { |
| return "substitutionGroup::"; |
| } |
| }; |
| |
| public static final Axis<XSAttributeDecl> ATTRIBUTE = new AbstractAxisImpl<XSAttributeDecl>() { |
| public Iterator<XSAttributeDecl> complexType(XSComplexType type) { |
| return attributeHolder(type); |
| } |
| |
| public Iterator<XSAttributeDecl> attGroupDecl(XSAttGroupDecl decl) { |
| return attributeHolder(decl); |
| } |
| |
| private Iterator<XSAttributeDecl> attributeHolder(final XSAttContainer atts) { |
| // TODO: check spec. is this correct? |
| return new Iterators.Adapter<XSAttributeDecl,XSAttributeUse>(atts.iterateAttributeUses()) { |
| protected XSAttributeDecl filter(XSAttributeUse u) { |
| return u.getDecl(); |
| } |
| }; |
| } |
| |
| public Iterator<XSAttributeDecl> schema(XSSchema schema) { |
| return schema.iterateAttributeDecls(); |
| } |
| |
| public String toString() { |
| return "@"; |
| } |
| }; |
| |
| public static final Axis<XSElementDecl> ELEMENT = new AbstractAxisImpl<XSElementDecl>() { |
| public Iterator<XSElementDecl> particle(XSParticle particle) { |
| return singleton(particle.getTerm().asElementDecl()); |
| } |
| |
| public Iterator<XSElementDecl> schema(XSSchema schema) { |
| return schema.iterateElementDecls(); |
| } |
| |
| public Iterator<XSElementDecl> modelGroupDecl(XSModelGroupDecl decl) { |
| return modelGroup(decl.getModelGroup()); |
| } |
| |
| //public Iterator<XSElementDecl> modelGroup(XSModelGroup group) { |
| // return new Iterators.Map<XSElementDecl,XSParticle>(group.iterator()) { |
| // protected Iterator<XSElementDecl> apply(XSParticle p) { |
| // return particle(p); |
| // } |
| // }; |
| //} |
| |
| @Override |
| public String getName() { |
| return ""; |
| } |
| |
| public String toString() { |
| return "element::"; |
| } |
| }; |
| |
| |
| public static final Axis<XSType> TYPE_DEFINITION = new AbstractAxisImpl<XSType>() { |
| public Iterator<XSType> schema(XSSchema schema) { |
| return schema.iterateTypes(); |
| } |
| |
| public Iterator<XSType> attributeDecl(XSAttributeDecl decl) { |
| return singleton(decl.getType()); |
| } |
| |
| public Iterator<XSType> elementDecl(XSElementDecl decl) { |
| return singleton(decl.getType()); |
| } |
| |
| public String toString() { |
| return "~"; |
| } |
| }; |
| |
| public static final Axis<XSType> BASETYPE = new AbstractAxisImpl<XSType>() { |
| public Iterator<XSType> simpleType(XSSimpleType type) { |
| return singleton(type.getBaseType()); |
| } |
| |
| public Iterator<XSType> complexType(XSComplexType type) { |
| return singleton(type.getBaseType()); |
| } |
| |
| public String toString() { |
| return "baseType::"; |
| } |
| }; |
| |
| public static final Axis<XSSimpleType> PRIMITIVE_TYPE = new AbstractAxisImpl<XSSimpleType>() { |
| public Iterator<XSSimpleType> simpleType(XSSimpleType type) { |
| return singleton(type.getPrimitiveType()); |
| } |
| |
| public String toString() { |
| return "primitiveType::"; |
| } |
| }; |
| |
| public static final Axis<XSSimpleType> ITEM_TYPE = new AbstractAxisImpl<XSSimpleType>() { |
| public Iterator<XSSimpleType> simpleType(XSSimpleType type) { |
| XSListSimpleType baseList = type.getBaseListType(); |
| if(baseList==null) return empty(); |
| return singleton(baseList.getItemType()); |
| } |
| |
| public String toString() { |
| return "itemType::"; |
| } |
| }; |
| |
| public static final Axis<XSSimpleType> MEMBER_TYPE = new AbstractAxisImpl<XSSimpleType>() { |
| public Iterator<XSSimpleType> simpleType(XSSimpleType type) { |
| XSUnionSimpleType baseUnion = type.getBaseUnionType(); |
| if(baseUnion ==null) return empty(); |
| return baseUnion.iterator(); |
| } |
| |
| public String toString() { |
| return "memberType::"; |
| } |
| }; |
| |
| public static final Axis<XSComponent> SCOPE = new AbstractAxisImpl<XSComponent>() { |
| public Iterator<XSComponent> complexType(XSComplexType type) { |
| return singleton(type.getScope()); |
| } |
| // TODO: attribute declaration has a scope, too. |
| // TODO: element declaration has a scope |
| |
| public String toString() { |
| return "scope::"; |
| } |
| }; |
| |
| public static final Axis<XSAttGroupDecl> ATTRIBUTE_GROUP = new AbstractAxisImpl<XSAttGroupDecl>() { |
| public Iterator<XSAttGroupDecl> schema(XSSchema schema) { |
| return schema.iterateAttGroupDecls(); |
| } |
| |
| public String toString() { |
| return "attributeGroup::"; |
| } |
| }; |
| |
| public static final Axis<XSModelGroupDecl> MODEL_GROUP_DECL = new AbstractAxisImpl<XSModelGroupDecl>() { |
| public Iterator<XSModelGroupDecl> schema(XSSchema schema) { |
| return schema.iterateModelGroupDecls(); |
| } |
| |
| public Iterator<XSModelGroupDecl> particle(XSParticle particle) { |
| return singleton(particle.getTerm().asModelGroupDecl()); |
| } |
| |
| public String toString() { |
| return "group::"; |
| } |
| }; |
| |
| public static final Axis<XSIdentityConstraint> IDENTITY_CONSTRAINT = new AbstractAxisImpl<XSIdentityConstraint>() { |
| public Iterator<XSIdentityConstraint> elementDecl(XSElementDecl decl) { |
| return decl.getIdentityConstraints().iterator(); |
| } |
| |
| public Iterator<XSIdentityConstraint> schema(XSSchema schema) { |
| // TODO: iterate all elements in this schema (local or global!) and its identity constraints |
| return super.schema(schema); |
| } |
| |
| public String toString() { |
| return "identityConstraint::"; |
| } |
| }; |
| |
| public static final Axis<XSIdentityConstraint> REFERENCED_KEY = new AbstractAxisImpl<XSIdentityConstraint>() { |
| public Iterator<XSIdentityConstraint> identityConstraint(XSIdentityConstraint decl) { |
| return singleton(decl.getReferencedKey()); |
| } |
| |
| public String toString() { |
| return "key::"; |
| } |
| }; |
| |
| public static final Axis<XSNotation> NOTATION = new AbstractAxisImpl<XSNotation>() { |
| public Iterator<XSNotation> schema(XSSchema schema) { |
| return schema.iterateNotations(); |
| } |
| |
| public String toString() { |
| return "notation::"; |
| } |
| }; |
| |
| public static final Axis<XSWildcard> WILDCARD = new AbstractAxisImpl<XSWildcard>() { |
| public Iterator<XSWildcard> particle(XSParticle particle) { |
| return singleton(particle.getTerm().asWildcard()); |
| } |
| |
| public String toString() { |
| return "any::"; |
| } |
| }; |
| |
| public static final Axis<XSWildcard> ATTRIBUTE_WILDCARD = new AbstractAxisImpl<XSWildcard>() { |
| public Iterator<XSWildcard> complexType(XSComplexType type) { |
| return singleton(type.getAttributeWildcard()); |
| } |
| |
| public Iterator<XSWildcard> attGroupDecl(XSAttGroupDecl decl) { |
| return singleton(decl.getAttributeWildcard()); |
| } |
| |
| public String toString() { |
| return "anyAttribute::"; |
| } |
| }; |
| |
| public static final Axis<XSFacet> FACET = new AbstractAxisImpl<XSFacet>() { |
| public Iterator<XSFacet> simpleType(XSSimpleType type) { |
| // TODO: it's not clear if "facets" mean all inherited facets or just declared facets |
| XSRestrictionSimpleType r = type.asRestriction(); |
| if(r!=null) |
| return r.iterateDeclaredFacets(); |
| else |
| return empty(); |
| } |
| |
| public String toString() { |
| return "facet::"; |
| } |
| }; |
| |
| public static final Axis<XSModelGroup> MODELGROUP_ALL = new ModelGroupAxis(Compositor.ALL); |
| public static final Axis<XSModelGroup> MODELGROUP_CHOICE = new ModelGroupAxis(Compositor.CHOICE); |
| public static final Axis<XSModelGroup> MODELGROUP_SEQUENCE = new ModelGroupAxis(Compositor.SEQUENCE); |
| public static final Axis<XSModelGroup> MODELGROUP_ANY = new ModelGroupAxis(null); |
| |
| static final class ModelGroupAxis extends AbstractAxisImpl<XSModelGroup> { |
| private final XSModelGroup.Compositor compositor; |
| |
| ModelGroupAxis(Compositor compositor) { |
| this.compositor = compositor; |
| } |
| |
| @Override |
| public boolean isModelGroup() { |
| return true; |
| } |
| |
| public Iterator<XSModelGroup> particle(XSParticle particle) { |
| return filter(particle.getTerm().asModelGroup()); |
| } |
| |
| public Iterator<XSModelGroup> modelGroupDecl(XSModelGroupDecl decl) { |
| return filter(decl.getModelGroup()); |
| } |
| |
| private Iterator<XSModelGroup> filter(XSModelGroup mg) { |
| if(mg==null) |
| return empty(); |
| if(mg.getCompositor() == compositor || compositor == null) |
| return singleton(mg); |
| else |
| return empty(); |
| } |
| |
| public String toString() { |
| if(compositor==null) |
| return "model::*"; |
| else |
| return "model::"+compositor; |
| } |
| } |
| } |