View Javadoc
1   /*
2    * Copyright (c) 1997, 2010, 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.XSComponent;
29  import com.sun.xml.internal.xsom.XSDeclaration;
30  import com.sun.xml.internal.xsom.XSFacet;
31  import com.sun.xml.internal.xsom.XSType;
32  import com.sun.xml.internal.xsom.SCD;
33  import com.sun.xml.internal.xsom.XSSchema;
34  import com.sun.xml.internal.xsom.impl.UName;
35  
36  import java.util.Iterator;
37  
38  /**
39   * Building block of {@link SCD}.
40   *
41   * @author Kohsuke Kawaguchi
42   */
43  public abstract class Step<T extends XSComponent> {
44      public final Axis<? extends T> axis;
45  
46      /**
47       * 'Predicate' in SCD designates the index of the item. -1 if there's no predicate.
48       * Predicate starts from 1.
49       *
50       * <p>
51       * Because of the parsing order this parameter cannot be marked
52       * final, even though it's immutable once it's parsed.
53       */
54      int predicate = -1;
55  
56      protected Step(Axis<? extends T> axis) {
57          this.axis = axis;
58      }
59  
60      /**
61       * Perform filtering (which is different depending on the kind of step.)
62       */
63      protected abstract Iterator<? extends T> filter( Iterator<? extends T> base );
64  
65      /**
66       * Evaluate this step against the current node set
67       * and returns matched nodes.
68       */
69      public final Iterator<T> evaluate(Iterator<XSComponent> nodeSet) {
70          // list up the whole thing
71          Iterator<T> r = new Iterators.Map<T,XSComponent>(nodeSet) {
72              protected Iterator<? extends T> apply(XSComponent contextNode) {
73                  return filter(axis.iterator(contextNode));
74              }
75          };
76  
77          // avoid duplicates
78          r = new Iterators.Unique<T>(r);
79  
80          if(predicate>=0) {
81              T item=null;
82              for( int i=predicate; i>0; i-- ) {
83                  if(!r.hasNext())
84                      return Iterators.empty();
85                  item = r.next();
86              }
87              return new Iterators.Singleton<T>(item);
88          }
89  
90          return r;
91      }
92  
93      /**
94       * Matches any name.
95       */
96      static final class Any extends Step<XSComponent> {
97          public Any(Axis<? extends XSComponent> axis) {
98              super(axis);
99          }
100 
101         // no filtering.
102         protected Iterator<? extends XSComponent> filter(Iterator<? extends XSComponent> base) {
103             return base;
104         }
105     }
106 
107     private static abstract class Filtered<T extends XSComponent> extends Step<T> {
108         protected Filtered(Axis<? extends T> axis) {
109             super(axis);
110         }
111 
112         protected Iterator<T> filter(Iterator<? extends T> base) {
113             return new Iterators.Filter<T>(base) {
114                 protected boolean matches(T d) {
115                     return match(d);
116                 }
117             };
118         }
119 
120         protected abstract boolean match(T d);
121     }
122 
123     /**
124      * Matches a particular name.
125      */
126     static final class Named extends Filtered<XSDeclaration> {
127         private final String nsUri;
128         private final String localName;
129 
130         public Named(Axis<? extends XSDeclaration> axis, UName n) {
131             this(axis,n.getNamespaceURI(),n.getName());
132         }
133 
134         public Named(Axis<? extends XSDeclaration> axis, String nsUri, String localName) {
135             super(axis);
136             this.nsUri = nsUri;
137             this.localName = localName;
138         }
139 
140         protected boolean match(XSDeclaration d) {
141             return d.getName().equals(localName) && d.getTargetNamespace().equals(nsUri);
142         }
143     }
144 
145     /**
146      * Matches anonymous types.
147      */
148     static final class AnonymousType extends Filtered<XSType> {
149         public AnonymousType(Axis<? extends XSType> axis) {
150             super(axis);
151         }
152 
153         protected boolean match(XSType node) {
154             return node.isLocal();
155         }
156     }
157 
158     /**
159      * Matches a particular kind of facets.
160      */
161     static final class Facet extends Filtered<XSFacet> {
162         private final String name;
163         public Facet(Axis<XSFacet> axis, String facetName) {
164             super(axis);
165             this.name = facetName;
166         }
167 
168         protected boolean match(XSFacet f) {
169             return f.getName().equals(name);
170         }
171     }
172 
173     /**
174      * Matches a schema in a particular namespace.
175      */
176     static final class Schema extends Filtered<XSSchema> {
177         private final String uri;
178         public Schema(Axis<XSSchema> axis, String uri) {
179             super(axis);
180             this.uri = uri;
181         }
182 
183         protected boolean match(XSSchema d) {
184             return d.getTargetNamespace().equals(uri);
185         }
186     }
187 }