1:
37:
38: package ;
39:
40: import ;
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49:
50:
55: public final class Steps
56: extends Path
57: {
58:
59: final LinkedList path;
60:
61: public Steps()
62: {
63: this(new LinkedList());
64: }
65:
66: Steps(LinkedList path)
67: {
68: this.path = path;
69: }
70:
71: public boolean matches(Node context)
72: {
73:
74: return matches(context, path.size() - 1);
75: }
76:
77: boolean matches(Node context, int pos)
78: {
79: Pattern right = (Pattern) path.get(pos);
80: if (!right.matches(context))
81: {
82: return false;
83: }
84: if (pos > 0)
85: {
86: Pattern left = (Pattern) path.get(pos - 1);
87: Iterator j = possibleContexts(right, context).iterator();
88: while (j.hasNext())
89: {
90: Node candidate = (Node) j.next();
91: if (left.matches(candidate) &&
92: matches(candidate, pos - 1))
93: {
94: return true;
95: }
96:
97: }
98: return false;
99: }
100: return true;
101: }
102:
103:
107: Collection possibleContexts(Pattern pattern, Node context)
108: {
109: if (pattern instanceof Selector)
110: {
111: Selector s = (Selector) pattern;
112: Collection candidates = new LinkedHashSet();
113: switch (s.axis)
114: {
115: case Selector.PARENT:
116: s.addChildNodes(context, candidates, false);
117: break;
118: case Selector.ANCESTOR:
119: s.addChildNodes(context, candidates, true);
120: break;
121: case Selector.ANCESTOR_OR_SELF:
122: candidates.add (context);
123: s.addChildNodes(context, candidates, true);
124: break;
125: case Selector.CHILD:
126: s.addParentNode(context, candidates, false);
127: break;
128: case Selector.DESCENDANT:
129: s.addParentNode(context, candidates, true);
130: break;
131: case Selector.DESCENDANT_OR_SELF:
132: candidates.add(context);
133: s.addParentNode(context, candidates, true);
134: break;
135: case Selector.PRECEDING_SIBLING:
136: s.addFollowingNodes(context, candidates, false);
137: break;
138: case Selector.FOLLOWING_SIBLING:
139: s.addPrecedingNodes(context, candidates, false);
140: break;
141: case Selector.PRECEDING:
142: s.addFollowingNodes(context, candidates, true);
143: break;
144: case Selector.FOLLOWING:
145: s.addPrecedingNodes(context, candidates, true);
146: break;
147: case Selector.ATTRIBUTE:
148: case Selector.NAMESPACE:
149: if (context.getNodeType() == Node.ATTRIBUTE_NODE)
150: {
151: candidates.add(((Attr) context).getOwnerElement());
152: }
153: break;
154: case Selector.SELF:
155: candidates.add(context);
156: break;
157: }
158: return candidates;
159: }
160: return Collections.EMPTY_SET;
161: }
162:
163: public Object evaluate(Node context, int pos, int len)
164: {
165:
166:
167: Iterator i = path.iterator();
168: Expr lhs = (Expr) i.next();
169: Object val = lhs.evaluate(context, pos, len);
170:
171: while (val instanceof Collection && i.hasNext())
172: {
173: Path rhs = (Path) i.next();
174: val = rhs.evaluate(context, (Collection) val);
175:
176: }
177: return val;
178: }
179:
180: Collection evaluate(Node context, Collection ns)
181: {
182:
183: Iterator i = path.iterator();
184: Expr lhs = (Expr) i.next();
185: if (lhs instanceof Path)
186: {
187: ns = ((Path) lhs).evaluate(context, ns);
188: }
189: else
190: {
191: Set acc = new LinkedHashSet();
192: int pos = 1, len = ns.size();
193: for (Iterator j = ns.iterator(); j.hasNext(); )
194: {
195: Node node = (Node) j.next();
196: Object ret = lhs.evaluate(node, pos++, len);
197: if (ret instanceof Collection)
198: {
199: acc.addAll((Collection) ret);
200: }
201: }
202: ns = acc;
203: }
204: while (i.hasNext())
205: {
206: Path rhs = (Path) i.next();
207: ns = rhs.evaluate(context, ns);
208: }
209: return ns;
210: }
211:
212: public Expr clone(Object context)
213: {
214: int len = path.size();
215: LinkedList path2 = new LinkedList();
216: for (int i = 0; i < len; i++)
217: {
218: path2.add(((Expr) path.get(i)).clone(context));
219: }
220: return new Steps(path2);
221: }
222:
223: public boolean references(QName var)
224: {
225: for (Iterator i = path.iterator(); i.hasNext(); )
226: {
227: if (((Expr) i.next()).references(var))
228: {
229: return true;
230: }
231: }
232: return false;
233: }
234:
235: public String toString()
236: {
237: StringBuffer buf = new StringBuffer();
238: Iterator i = path.iterator();
239: Expr expr = (Expr) i.next();
240: if (!(expr instanceof Root))
241: {
242: buf.append(expr);
243: }
244: while (i.hasNext())
245: {
246: expr = (Expr) i.next();
247: buf.append('/');
248: buf.append(expr);
249: }
250: return buf.toString();
251: }
252:
253: }