1 /*
2  * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package com.sun.xml.internal.xsom.impl.scd;
27 
28 import com.sun.xml.internal.xsom.XSAttContainer;
29 import com.sun.xml.internal.xsom.XSAttGroupDecl;
30 import com.sun.xml.internal.xsom.XSAttributeDecl;
31 import com.sun.xml.internal.xsom.XSAttributeUse;
32 import com.sun.xml.internal.xsom.XSComplexType;
33 import com.sun.xml.internal.xsom.XSComponent;
34 import com.sun.xml.internal.xsom.XSElementDecl;
35 import com.sun.xml.internal.xsom.XSFacet;
36 import com.sun.xml.internal.xsom.XSIdentityConstraint;
37 import com.sun.xml.internal.xsom.XSListSimpleType;
38 import com.sun.xml.internal.xsom.XSModelGroup;
39 import com.sun.xml.internal.xsom.XSModelGroup.Compositor;
40 import com.sun.xml.internal.xsom.XSModelGroupDecl;
41 import com.sun.xml.internal.xsom.XSNotation;
42 import com.sun.xml.internal.xsom.XSParticle;
43 import com.sun.xml.internal.xsom.XSRestrictionSimpleType;
44 import com.sun.xml.internal.xsom.XSSchema;
45 import com.sun.xml.internal.xsom.XSSimpleType;
46 import com.sun.xml.internal.xsom.XSType;
47 import com.sun.xml.internal.xsom.XSUnionSimpleType;
48 import com.sun.xml.internal.xsom.XSWildcard;
49 
50 import java.util.ArrayList;
51 import java.util.HashSet;
52 import java.util.Iterator;
53 import java.util.List;
54 import java.util.Set;
55 
56 /**
57  * Axis of traversal.
58  *
59  * @param <T>
60  *      The kind of components that this axis may return.
61  *
62  * @author Kohsuke Kawaguchi
63  */
64 public interface Axis<T extends XSComponent> {
iterator(XSComponent contextNode)65     Iterator<T> iterator(XSComponent contextNode);
66 
iterator(Iterator<? extends XSComponent> contextNodes)67     Iterator<T> iterator(Iterator<? extends XSComponent> contextNodes);
68 
69     /**
70      * Returns true if this is one of the model group axis.
71      */
isModelGroup()72     boolean isModelGroup();
73 
74 
75     /**
76      * Pseudo-axis that selects all the {@link XSSchema}s in the current set.
77      * Used to implement the absolute path expression
78      */
79     public static final Axis<XSSchema> ROOT = new Axis<XSSchema>() {
80         public Iterator<XSSchema> iterator(XSComponent contextNode) {
81             return contextNode.getRoot().iterateSchema();
82         }
83 
84         public Iterator<XSSchema> iterator(Iterator<? extends XSComponent> contextNodes) {
85             if(!contextNodes.hasNext())
86                 return Iterators.empty();
87             else
88                 // this assumes that all current nodes belong to the same owner.
89                 return iterator(contextNodes.next());
90         }
91 
92         public boolean isModelGroup() {
93             return false;
94         }
95 
96         public String toString() {
97             return "root::";
98         }
99     };
100 
101     /**
102      * Pseudo-axis that visits all skipped intermediate steps.
103      * Those are:
104      * <ol>
105      *  <li>complex type reachable from element
106      *  <li>model groups
107      *  <li>combination of above.
108      * </ol>
109      */
110     public static final Axis<XSComponent> INTERMEDIATE_SKIP = new AbstractAxisImpl<XSComponent>() {
111         public Iterator<XSComponent> elementDecl(XSElementDecl decl) {
112             XSComplexType ct = decl.getType().asComplexType();
113             if(ct==null)
114                 return empty();
115             else {
116                 // also pick up model groups inside this complex type
117                 return new Iterators.Union<XSComponent>(singleton(ct),complexType(ct));
118             }
119         }
120 
121         public Iterator<XSComponent> modelGroupDecl(XSModelGroupDecl decl) {
122             return descendants(decl.getModelGroup());
123         }
124 
125         public Iterator<XSComponent> particle(XSParticle particle) {
126             return descendants(particle.getTerm().asModelGroup());
127         }
128 
129         /**
130          * Iterate all descendant model groups of the given model group, including itself.
131          */
132         private Iterator<XSComponent> descendants(XSModelGroup mg) {
133             // TODO: write a tree iterator
134             // for now, we do it eagerly because I'm lazy
135             List<XSComponent> r = new ArrayList<XSComponent>();
136             visit(mg,r);
137             return r.iterator();
138         }
139 
140         private void visit(XSModelGroup mg, List<XSComponent> r) {
141             // since model groups never form a cycle, no cycle check is needed
142             r.add(mg);
143             for (XSParticle p : mg) {
144                 XSModelGroup child = p.getTerm().asModelGroup();
145                 if(child!=null)
146                     visit(child,r);
147             }
148         }
149 
150         public String toString() {
151             return "(intermediateSkip)";
152         }
153     };
154 
155     /**
156      * All descendants reachable via default axes. Used to implement the "//" semantics.
157      *
158      * So far the default axes together are guaranteed not to cause any cycle, so
159      * no cycle check is needed (if it's needed, the life would be much harder!)
160      */
161     public static final Axis<XSComponent> DESCENDANTS = new Axis<XSComponent>() {
162         public Iterator<XSComponent> iterator(XSComponent contextNode) {
163             return new Visitor().iterator(contextNode);
164         }
165         public Iterator<XSComponent> iterator(Iterator<? extends XSComponent> contextNodes) {
166             return new Visitor().iterator(contextNodes);
167         }
168 
169         public boolean isModelGroup() {
170             return false;
171         }
172 
173         /**
174          * Stateful visitor that remembers what's already traversed, to reduce the search space.
175          */
176         final class Visitor extends AbstractAxisImpl<XSComponent> {
177             private final Set<XSComponent> visited = new HashSet<XSComponent>();
178 
179             /**
180              * Recursively apply the {@link Axis#DESCENDANTS} axis.
181              */
182             final class Recursion extends Iterators.Map<XSComponent,XSComponent> {
183                 public Recursion(Iterator<? extends XSComponent> core) {
184                     super(core);
185                 }
186 
187                 protected Iterator<XSComponent> apply(XSComponent u) {
188                     return DESCENDANTS.iterator(u);
189                 }
190             }
191             public Iterator<XSComponent> schema(XSSchema schema) {
192                 if(visited.add(schema))
193                     return ret( schema, new Recursion(schema.iterateElementDecls()));
194                 else
195                     return empty();
196             }
197 
198             public Iterator<XSComponent> elementDecl(XSElementDecl decl) {
199                 if(visited.add(decl))
200                     return ret(decl, iterator(decl.getType()) );
201                 else
202                     return empty();
203             }
204 
205             public Iterator<XSComponent> simpleType(XSSimpleType type) {
206                 if(visited.add(type))
207                     return ret(type, FACET.iterator(type));
208                 else
209                     return empty();
210             }
211 
212             public Iterator<XSComponent> complexType(XSComplexType type) {
213                 if(visited.add(type))
214                     return ret(type, iterator(type.getContentType()));
215                 else
216                     return empty();
217             }
218 
219             public Iterator<XSComponent> particle(XSParticle particle) {
220                 if(visited.add(particle))
221                     return ret(particle, iterator(particle.getTerm()));
222                 else
223                     return empty();
224             }
225 
226             public Iterator<XSComponent> modelGroupDecl(XSModelGroupDecl decl) {
227                 if(visited.add(decl))
228                     return ret(decl, iterator(decl.getModelGroup()));
229                 else
230                     return empty();
231             }
232 
233             public Iterator<XSComponent> modelGroup(XSModelGroup group) {
234                 if(visited.add(group))
235                     return ret(group, new Recursion(group.iterator()));
236                 else
237                     return empty();
238             }
239 
240             public Iterator<XSComponent> attGroupDecl(XSAttGroupDecl decl) {
241                 if(visited.add(decl))
242                     return ret(decl, new Recursion(decl.iterateAttributeUses()));
243                 else
244                     return empty();
245             }
246 
247             public Iterator<XSComponent> attributeUse(XSAttributeUse use) {
248                 if(visited.add(use))
249                     return ret(use, iterator(use.getDecl()));
250                 else
251                     return empty();
252             }
253 
254             public Iterator<XSComponent> attributeDecl(XSAttributeDecl decl) {
255                 if(visited.add(decl))
256                     return ret(decl, iterator(decl.getType()));
257                 else
258                     return empty();
259             }
260 
261             private Iterator<XSComponent> ret( XSComponent one, Iterator<? extends XSComponent> rest ) {
262                 return union(singleton(one),rest);
263             }
264         }
265 
266         public String toString() {
267             return "/";
268         }
269     };
270 
271     public static final Axis<XSSchema> X_SCHEMA = new Axis<XSSchema>() {
272         public Iterator<XSSchema> iterator(XSComponent contextNode) {
273             return Iterators.singleton(contextNode.getOwnerSchema());
274         }
275 
276         public Iterator<XSSchema> iterator(Iterator<? extends XSComponent> contextNodes) {
277             return new Iterators.Adapter<XSSchema,XSComponent>(contextNodes) {
278                 protected XSSchema filter(XSComponent u) {
279                     return u.getOwnerSchema();
280                 }
281             };
282         }
283 
284         public boolean isModelGroup() {
285             return false;
286         }
287 
288         public String toString() {
289             return "x-schema::";
290         }
291     };
292 
293     public static final Axis<XSElementDecl> SUBSTITUTION_GROUP = new AbstractAxisImpl<XSElementDecl>() {
294         public Iterator<XSElementDecl> elementDecl(XSElementDecl decl) {
295             return singleton(decl.getSubstAffiliation());
296         }
297 
298         public String toString() {
299             return "substitutionGroup::";
300         }
301     };
302 
303     public static final Axis<XSAttributeDecl> ATTRIBUTE = new AbstractAxisImpl<XSAttributeDecl>() {
304         public Iterator<XSAttributeDecl> complexType(XSComplexType type) {
305             return attributeHolder(type);
306         }
307 
308         public Iterator<XSAttributeDecl> attGroupDecl(XSAttGroupDecl decl) {
309             return attributeHolder(decl);
310         }
311 
312         private Iterator<XSAttributeDecl> attributeHolder(final XSAttContainer atts) {
313             // TODO: check spec. is this correct?
314             return new Iterators.Adapter<XSAttributeDecl,XSAttributeUse>(atts.iterateAttributeUses()) {
315                 protected XSAttributeDecl filter(XSAttributeUse u) {
316                     return u.getDecl();
317                 }
318             };
319         }
320 
321         public Iterator<XSAttributeDecl> schema(XSSchema schema) {
322             return schema.iterateAttributeDecls();
323         }
324 
325         public String toString() {
326             return "@";
327         }
328     };
329 
330     public static final Axis<XSElementDecl> ELEMENT = new AbstractAxisImpl<XSElementDecl>() {
331         public Iterator<XSElementDecl> particle(XSParticle particle) {
332             return singleton(particle.getTerm().asElementDecl());
333         }
334 
335         public Iterator<XSElementDecl> schema(XSSchema schema) {
336             return schema.iterateElementDecls();
337         }
338 
339         public Iterator<XSElementDecl> modelGroupDecl(XSModelGroupDecl decl) {
340             return modelGroup(decl.getModelGroup());
341         }
342 
343         //public Iterator<XSElementDecl> modelGroup(XSModelGroup group) {
344         //    return new Iterators.Map<XSElementDecl,XSParticle>(group.iterator()) {
345         //        protected Iterator<XSElementDecl> apply(XSParticle p) {
346         //            return particle(p);
347         //        }
348         //    };
349         //}
350 
351         @Override
352         public String getName() {
353             return "";
354         }
355 
356         public String toString() {
357             return "element::";
358         }
359     };
360 
361 
362     public static final Axis<XSType> TYPE_DEFINITION = new AbstractAxisImpl<XSType>() {
363         public Iterator<XSType> schema(XSSchema schema) {
364             return schema.iterateTypes();
365         }
366 
367         public Iterator<XSType> attributeDecl(XSAttributeDecl decl) {
368             return singleton(decl.getType());
369         }
370 
371         public Iterator<XSType> elementDecl(XSElementDecl decl) {
372             return singleton(decl.getType());
373         }
374 
375         public String toString() {
376             return "~";
377         }
378     };
379 
380     public static final Axis<XSType> BASETYPE = new AbstractAxisImpl<XSType>() {
381         public Iterator<XSType> simpleType(XSSimpleType type) {
382             return singleton(type.getBaseType());
383         }
384 
385         public Iterator<XSType> complexType(XSComplexType type) {
386             return singleton(type.getBaseType());
387         }
388 
389         public String toString() {
390             return "baseType::";
391         }
392     };
393 
394     public static final Axis<XSSimpleType> PRIMITIVE_TYPE = new AbstractAxisImpl<XSSimpleType>() {
395         public Iterator<XSSimpleType> simpleType(XSSimpleType type) {
396             return singleton(type.getPrimitiveType());
397         }
398 
399         public String toString() {
400             return "primitiveType::";
401         }
402     };
403 
404     public static final Axis<XSSimpleType> ITEM_TYPE = new AbstractAxisImpl<XSSimpleType>() {
405         public Iterator<XSSimpleType> simpleType(XSSimpleType type) {
406             XSListSimpleType baseList = type.getBaseListType();
407             if(baseList==null)      return empty();
408             return singleton(baseList.getItemType());
409         }
410 
411         public String toString() {
412             return "itemType::";
413         }
414     };
415 
416     public static final Axis<XSSimpleType> MEMBER_TYPE = new AbstractAxisImpl<XSSimpleType>() {
417         public Iterator<XSSimpleType> simpleType(XSSimpleType type) {
418             XSUnionSimpleType baseUnion = type.getBaseUnionType();
419             if(baseUnion ==null)      return empty();
420             return baseUnion.iterator();
421         }
422 
423         public String toString() {
424             return "memberType::";
425         }
426     };
427 
428     public static final Axis<XSComponent> SCOPE = new AbstractAxisImpl<XSComponent>() {
429         public Iterator<XSComponent> complexType(XSComplexType type) {
430             return singleton(type.getScope());
431         }
432         // TODO: attribute declaration has a scope, too.
433         // TODO: element declaration has a scope
434 
435         public String toString() {
436             return "scope::";
437         }
438     };
439 
440     public static final Axis<XSAttGroupDecl> ATTRIBUTE_GROUP = new AbstractAxisImpl<XSAttGroupDecl>() {
441         public Iterator<XSAttGroupDecl> schema(XSSchema schema) {
442             return schema.iterateAttGroupDecls();
443         }
444 
445         public String toString() {
446             return "attributeGroup::";
447         }
448     };
449 
450     public static final Axis<XSModelGroupDecl> MODEL_GROUP_DECL = new AbstractAxisImpl<XSModelGroupDecl>() {
451         public Iterator<XSModelGroupDecl> schema(XSSchema schema) {
452             return schema.iterateModelGroupDecls();
453         }
454 
455         public Iterator<XSModelGroupDecl> particle(XSParticle particle) {
456             return singleton(particle.getTerm().asModelGroupDecl());
457         }
458 
459         public String toString() {
460             return "group::";
461         }
462     };
463 
464     public static final Axis<XSIdentityConstraint> IDENTITY_CONSTRAINT = new AbstractAxisImpl<XSIdentityConstraint>() {
465         public Iterator<XSIdentityConstraint> elementDecl(XSElementDecl decl) {
466             return decl.getIdentityConstraints().iterator();
467         }
468 
469         public Iterator<XSIdentityConstraint> schema(XSSchema schema) {
470             // TODO: iterate all elements in this schema (local or global!) and its identity constraints
471             return super.schema(schema);
472         }
473 
474         public String toString() {
475             return "identityConstraint::";
476         }
477     };
478 
479     public static final Axis<XSIdentityConstraint> REFERENCED_KEY = new AbstractAxisImpl<XSIdentityConstraint>() {
480         public Iterator<XSIdentityConstraint> identityConstraint(XSIdentityConstraint decl) {
481             return singleton(decl.getReferencedKey());
482         }
483 
484         public String toString() {
485             return "key::";
486         }
487     };
488 
489     public static final Axis<XSNotation> NOTATION = new AbstractAxisImpl<XSNotation>() {
490         public Iterator<XSNotation> schema(XSSchema schema) {
491             return schema.iterateNotations();
492         }
493 
494         public String toString() {
495             return "notation::";
496         }
497     };
498 
499     public static final Axis<XSWildcard> WILDCARD = new AbstractAxisImpl<XSWildcard>() {
500         public Iterator<XSWildcard> particle(XSParticle particle) {
501             return singleton(particle.getTerm().asWildcard());
502         }
503 
504         public String toString() {
505             return "any::";
506         }
507     };
508 
509     public static final Axis<XSWildcard> ATTRIBUTE_WILDCARD = new AbstractAxisImpl<XSWildcard>() {
510         public Iterator<XSWildcard> complexType(XSComplexType type) {
511             return singleton(type.getAttributeWildcard());
512         }
513 
514         public Iterator<XSWildcard> attGroupDecl(XSAttGroupDecl decl) {
515             return singleton(decl.getAttributeWildcard());
516         }
517 
518         public String toString() {
519             return "anyAttribute::";
520         }
521     };
522 
523     public static final Axis<XSFacet> FACET = new AbstractAxisImpl<XSFacet>() {
524         public Iterator<XSFacet> simpleType(XSSimpleType type) {
525             // TODO: it's not clear if "facets" mean all inherited facets or just declared facets
526             XSRestrictionSimpleType r = type.asRestriction();
527             if(r!=null)
528                 return r.iterateDeclaredFacets();
529             else
530                 return empty();
531         }
532 
533         public String toString() {
534             return "facet::";
535         }
536     };
537 
538     public static final Axis<XSModelGroup> MODELGROUP_ALL = new ModelGroupAxis(Compositor.ALL);
539     public static final Axis<XSModelGroup> MODELGROUP_CHOICE = new ModelGroupAxis(Compositor.CHOICE);
540     public static final Axis<XSModelGroup> MODELGROUP_SEQUENCE = new ModelGroupAxis(Compositor.SEQUENCE);
541     public static final Axis<XSModelGroup> MODELGROUP_ANY = new ModelGroupAxis(null);
542 
543     static final class ModelGroupAxis extends AbstractAxisImpl<XSModelGroup> {
544         private final XSModelGroup.Compositor compositor;
545 
ModelGroupAxis(Compositor compositor)546         ModelGroupAxis(Compositor compositor) {
547             this.compositor = compositor;
548         }
549 
550         @Override
isModelGroup()551         public boolean isModelGroup() {
552             return true;
553         }
554 
particle(XSParticle particle)555         public Iterator<XSModelGroup> particle(XSParticle particle) {
556             return filter(particle.getTerm().asModelGroup());
557         }
558 
modelGroupDecl(XSModelGroupDecl decl)559         public Iterator<XSModelGroup> modelGroupDecl(XSModelGroupDecl decl) {
560             return filter(decl.getModelGroup());
561         }
562 
filter(XSModelGroup mg)563         private Iterator<XSModelGroup> filter(XSModelGroup mg) {
564             if(mg==null)
565                 return empty();
566             if(mg.getCompositor() == compositor || compositor == null)
567                 return singleton(mg);
568             else
569                 return empty();
570         }
571 
toString()572         public String toString() {
573             if(compositor==null)
574                 return "model::*";
575             else
576                 return "model::"+compositor;
577         }
578     }
579 }
580