com.sun.xml.xsom.impl.scd.Axis Maven / Gradle / Ivy
/*
* Copyright (c) 1997, 2022 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0, which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
package com.sun.xml.xsom.impl.scd;
import com.sun.xml.xsom.XSAttContainer;
import com.sun.xml.xsom.XSAttGroupDecl;
import com.sun.xml.xsom.XSAttributeDecl;
import com.sun.xml.xsom.XSAttributeUse;
import com.sun.xml.xsom.XSComplexType;
import com.sun.xml.xsom.XSComponent;
import com.sun.xml.xsom.XSElementDecl;
import com.sun.xml.xsom.XSFacet;
import com.sun.xml.xsom.XSIdentityConstraint;
import com.sun.xml.xsom.XSListSimpleType;
import com.sun.xml.xsom.XSModelGroup;
import com.sun.xml.xsom.XSModelGroup.Compositor;
import com.sun.xml.xsom.XSModelGroupDecl;
import com.sun.xml.xsom.XSNotation;
import com.sun.xml.xsom.XSParticle;
import com.sun.xml.xsom.XSRestrictionSimpleType;
import com.sun.xml.xsom.XSSchema;
import com.sun.xml.xsom.XSSimpleType;
import com.sun.xml.xsom.XSType;
import com.sun.xml.xsom.XSUnionSimpleType;
import com.sun.xml.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
* The kind of components that this axis may return.
*
* @author Kohsuke Kawaguchi
*/
public interface Axis {
Iterator iterator(XSComponent contextNode);
Iterator 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
*/
Axis ROOT = new Axis<>() {
public Iterator iterator(XSComponent contextNode) {
return contextNode.getRoot().iterateSchema();
}
public Iterator 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:
*
* - complex type reachable from element
*
- model groups
*
- combination of above.
*
*/
Axis INTERMEDIATE_SKIP = new AbstractAxisImpl<>() {
public Iterator 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<>(singleton(ct), complexType(ct));
}
}
public Iterator modelGroupDecl(XSModelGroupDecl decl) {
return descendants(decl.getModelGroup());
}
public Iterator particle(XSParticle particle) {
return descendants(particle.getTerm().asModelGroup());
}
/**
* Iterate all descendant model groups of the given model group, including itself.
*/
private Iterator descendants(XSModelGroup mg) {
// TODO: write a tree iterator
// for now, we do it eagerly because I'm lazy
List r = new ArrayList<>();
visit(mg, r);
return r.iterator();
}
private void visit(XSModelGroup mg, List 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!)
*/
Axis DESCENDANTS = new Axis<>() {
public Iterator iterator(XSComponent contextNode) {
return new Visitor().iterator(contextNode);
}
public Iterator 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 {
private final Set visited = new HashSet<>();
/**
* Recursively apply the {@link Axis#DESCENDANTS} axis.
*/
final class Recursion extends Iterators.Map {
public Recursion(Iterator extends XSComponent> core) {
super(core);
}
protected Iterator apply(XSComponent u) {
return DESCENDANTS.iterator(u);
}
}
public Iterator schema(XSSchema schema) {
if (visited.add(schema))
return ret(schema, new Recursion(schema.iterateElementDecls()));
else
return empty();
}
public Iterator elementDecl(XSElementDecl decl) {
if (visited.add(decl))
return ret(decl, iterator(decl.getType()));
else
return empty();
}
public Iterator simpleType(XSSimpleType type) {
if (visited.add(type))
return ret(type, FACET.iterator(type));
else
return empty();
}
public Iterator complexType(XSComplexType type) {
if (visited.add(type))
return ret(type, iterator(type.getContentType()));
else
return empty();
}
public Iterator particle(XSParticle particle) {
if (visited.add(particle))
return ret(particle, iterator(particle.getTerm()));
else
return empty();
}
public Iterator modelGroupDecl(XSModelGroupDecl decl) {
if (visited.add(decl))
return ret(decl, iterator(decl.getModelGroup()));
else
return empty();
}
public Iterator modelGroup(XSModelGroup group) {
if (visited.add(group))
return ret(group, new Recursion(group.iterator()));
else
return empty();
}
public Iterator attGroupDecl(XSAttGroupDecl decl) {
if (visited.add(decl))
return ret(decl, new Recursion(decl.iterateAttributeUses()));
else
return empty();
}
public Iterator attributeUse(XSAttributeUse use) {
if (visited.add(use))
return ret(use, iterator(use.getDecl()));
else
return empty();
}
public Iterator attributeDecl(XSAttributeDecl decl) {
if (visited.add(decl))
return ret(decl, iterator(decl.getType()));
else
return empty();
}
private Iterator ret(XSComponent one, Iterator extends XSComponent> rest) {
return union(singleton(one), rest);
}
}
public String toString() {
return "/";
}
};
Axis X_SCHEMA = new Axis<>() {
public Iterator iterator(XSComponent contextNode) {
return Iterators.singleton(contextNode.getOwnerSchema());
}
public Iterator iterator(Iterator extends XSComponent> contextNodes) {
return new Iterators.Adapter(contextNodes) {
protected XSSchema filter(XSComponent u) {
return u.getOwnerSchema();
}
};
}
public boolean isModelGroup() {
return false;
}
public String toString() {
return "x-schema::";
}
};
Axis SUBSTITUTION_GROUP = new AbstractAxisImpl<>() {
public Iterator elementDecl(XSElementDecl decl) {
return singleton(decl.getSubstAffiliation());
}
public String toString() {
return "substitutionGroup::";
}
};
Axis ATTRIBUTE = new AbstractAxisImpl<>() {
public Iterator complexType(XSComplexType type) {
return attributeHolder(type);
}
public Iterator attGroupDecl(XSAttGroupDecl decl) {
return attributeHolder(decl);
}
private Iterator attributeHolder(final XSAttContainer atts) {
// TODO: check spec. is this correct?
return new Iterators.Adapter(atts.iterateAttributeUses()) {
protected XSAttributeDecl filter(XSAttributeUse u) {
return u.getDecl();
}
};
}
public Iterator schema(XSSchema schema) {
return schema.iterateAttributeDecls();
}
public String toString() {
return "@";
}
};
Axis ELEMENT = new AbstractAxisImpl<>() {
public Iterator particle(XSParticle particle) {
return singleton(particle.getTerm().asElementDecl());
}
public Iterator schema(XSSchema schema) {
return schema.iterateElementDecls();
}
public Iterator modelGroupDecl(XSModelGroupDecl decl) {
return modelGroup(decl.getModelGroup());
}
//public Iterator modelGroup(XSModelGroup group) {
// return new Iterators.Map(group.iterator()) {
// protected Iterator apply(XSParticle p) {
// return particle(p);
// }
// };
//}
@Override
public String getName() {
return "";
}
public String toString() {
return "element::";
}
};
Axis TYPE_DEFINITION = new AbstractAxisImpl<>() {
public Iterator schema(XSSchema schema) {
return schema.iterateTypes();
}
public Iterator attributeDecl(XSAttributeDecl decl) {
return singleton(decl.getType());
}
public Iterator elementDecl(XSElementDecl decl) {
return singleton(decl.getType());
}
public String toString() {
return "~";
}
};
Axis BASETYPE = new AbstractAxisImpl<>() {
public Iterator simpleType(XSSimpleType type) {
return singleton(type.getBaseType());
}
public Iterator complexType(XSComplexType type) {
return singleton(type.getBaseType());
}
public String toString() {
return "baseType::";
}
};
Axis PRIMITIVE_TYPE = new AbstractAxisImpl<>() {
public Iterator simpleType(XSSimpleType type) {
return singleton(type.getPrimitiveType());
}
public String toString() {
return "primitiveType::";
}
};
Axis ITEM_TYPE = new AbstractAxisImpl<>() {
public Iterator simpleType(XSSimpleType type) {
XSListSimpleType baseList = type.getBaseListType();
if (baseList == null) return empty();
return singleton(baseList.getItemType());
}
public String toString() {
return "itemType::";
}
};
Axis MEMBER_TYPE = new AbstractAxisImpl<>() {
public Iterator simpleType(XSSimpleType type) {
XSUnionSimpleType baseUnion = type.getBaseUnionType();
if (baseUnion == null) return empty();
return baseUnion.iterator();
}
public String toString() {
return "memberType::";
}
};
Axis SCOPE = new AbstractAxisImpl<>() {
public Iterator 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::";
}
};
Axis ATTRIBUTE_GROUP = new AbstractAxisImpl<>() {
public Iterator schema(XSSchema schema) {
return schema.iterateAttGroupDecls();
}
public String toString() {
return "attributeGroup::";
}
};
Axis MODEL_GROUP_DECL = new AbstractAxisImpl<>() {
public Iterator schema(XSSchema schema) {
return schema.iterateModelGroupDecls();
}
public Iterator particle(XSParticle particle) {
return singleton(particle.getTerm().asModelGroupDecl());
}
public String toString() {
return "group::";
}
};
Axis IDENTITY_CONSTRAINT = new AbstractAxisImpl<>() {
public Iterator elementDecl(XSElementDecl decl) {
return decl.getIdentityConstraints().iterator();
}
public Iterator 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::";
}
};
Axis REFERENCED_KEY = new AbstractAxisImpl<>() {
public Iterator identityConstraint(XSIdentityConstraint decl) {
return singleton(decl.getReferencedKey());
}
public String toString() {
return "key::";
}
};
Axis NOTATION = new AbstractAxisImpl<>() {
public Iterator schema(XSSchema schema) {
return schema.iterateNotations();
}
public String toString() {
return "notation::";
}
};
Axis WILDCARD = new AbstractAxisImpl<>() {
public Iterator particle(XSParticle particle) {
return singleton(particle.getTerm().asWildcard());
}
public String toString() {
return "any::";
}
};
Axis ATTRIBUTE_WILDCARD = new AbstractAxisImpl<>() {
public Iterator complexType(XSComplexType type) {
return singleton(type.getAttributeWildcard());
}
public Iterator attGroupDecl(XSAttGroupDecl decl) {
return singleton(decl.getAttributeWildcard());
}
public String toString() {
return "anyAttribute::";
}
};
Axis FACET = new AbstractAxisImpl<>() {
public Iterator 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::";
}
};
Axis MODELGROUP_ALL = new ModelGroupAxis(Compositor.ALL);
Axis MODELGROUP_CHOICE = new ModelGroupAxis(Compositor.CHOICE);
Axis MODELGROUP_SEQUENCE = new ModelGroupAxis(Compositor.SEQUENCE);
Axis MODELGROUP_ANY = new ModelGroupAxis(null);
final class ModelGroupAxis extends AbstractAxisImpl {
private final XSModelGroup.Compositor compositor;
ModelGroupAxis(Compositor compositor) {
this.compositor = compositor;
}
@Override
public boolean isModelGroup() {
return true;
}
public Iterator particle(XSParticle particle) {
return filter(particle.getTerm().asModelGroup());
}
public Iterator modelGroupDecl(XSModelGroupDecl decl) {
return filter(decl.getModelGroup());
}
private Iterator 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;
}
}
}