KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > xpath > pattern > FromPrevious


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  * Free SoftwareFoundation, Inc.
23  * 59 Temple Place, Suite 330
24  * Boston, MA 02111-1307 USA
25  *
26  * @author Scott Ferguson
27  */

28
29 package com.caucho.xpath.pattern;
30
31 import com.caucho.xml.XmlUtil;
32 import com.caucho.xpath.Env;
33 import com.caucho.xpath.ExprEnvironment;
34 import com.caucho.xpath.XPathException;
35
36 import org.w3c.dom.Node JavaDoc;
37
38 /**
39  * Matches nodes preceding the current node, not counting descendants.
40  */

41 public class FromPrevious extends Axis {
42   public FromPrevious(AbstractPattern parent)
43   {
44     super(parent);
45
46     if (parent == null)
47       throw new RuntimeException JavaDoc();
48   }
49
50   /**
51    * matches if we can find a following node matching the parent pattern.
52    */

53   public boolean match(Node JavaDoc node, ExprEnvironment env)
54     throws XPathException
55   {
56     if (node == null)
57       return false;
58
59     return getAxisContext(node, env, node) != null;
60   }
61
62   /**
63    * The iterator is in reverse document order.
64    */

65   public boolean isAscending()
66   {
67     return false;
68   }
69
70   /**
71    * Calculates position by counting next nodes matching the pattern.
72    *
73    * The axis is a previous node matching the parent pattern.
74    */

75   public int position(Node JavaDoc node, Env env, AbstractPattern pattern)
76     throws XPathException
77   {
78     int index = env.getPositionIndex();
79
80     boolean hasMatch = true;
81     Node JavaDoc axis = XmlUtil.getNext(node);
82     
83     for (; axis != null; axis = XmlUtil.getNext(axis)) {
84       if (hasMatch && _parent.match(axis, env)) {
85         boolean hasParent = false;
86         for (Node JavaDoc ptr = node.getParentNode();
87              ptr != null;
88              ptr = ptr.getParentNode()) {
89           if (ptr == axis) {
90             hasParent = true;
91             break;
92           }
93         }
94         
95         if (! hasParent && --index < 0) {
96           hasMatch = false;
97           break;
98         }
99       }
100       
101       if (! hasMatch && pattern.match(axis, env))
102         hasMatch = true;
103     }
104     
105     int count = 1;
106     Node JavaDoc ptr;
107     for (ptr = axis;
108          ptr != null && ptr.getNextSibling() == null;
109          ptr = ptr.getParentNode()) {
110     }
111     
112     for (ptr = XmlUtil.getPrevious(axis);
113          ptr != null && ptr != node;
114          ptr = XmlUtil.getPrevious(ptr)) {
115       if (pattern.match(ptr, env)) {
116         boolean hasParent = false;
117         for (Node JavaDoc n = node; n != null; n = n.getParentNode()) {
118           if (n == ptr) {
119             hasParent = true;
120             break;
121           }
122         }
123
124         if (! hasParent)
125           count++;
126       }
127     }
128
129     for (; axis != null; axis = XmlUtil.getNext(axis)) {
130       if (_parent.match(axis, env)) {
131         env.setMorePositions(true);
132         break;
133       }
134     }
135
136     return count;
137   }
138
139   /**
140    * counts matching nodes preceding the axis context.
141    *
142    * count() walks backwards from the axis context.
143    */

144   public int count(Node JavaDoc node, Env env, AbstractPattern pattern)
145     throws XPathException
146   {
147     int index = env.getPositionIndex();
148
149     Node JavaDoc axis = getAxisContext(node, env, node);
150     for (; index > 0; index--)
151       axis = getAxisContext(axis, env, node);
152
153     if (getAxisContext(axis, env, node) != null)
154       env.setMorePositions(true);
155
156     int count = 0;
157     for (Node JavaDoc ptr = axis;
158      ptr != null;
159      ptr = XmlUtil.getPrevious(ptr)) {
160       if (pattern.match(ptr, env) && ! isDescendant(ptr, axis))
161     count++;
162     }
163
164     return count;
165   }
166   
167   /**
168    * Returns true if the pattern is strictly ascending.
169    */

170   public boolean isUnique()
171   {
172     if (_parent == null)
173       return true;
174     else
175       return _parent.isSingleSelect();
176   }
177
178   /**
179    * Returns the first node in the selection order.
180    *
181    * @param node the current node
182    *
183    * @return the first node
184    */

185   public Node JavaDoc firstNode(Node JavaDoc node, ExprEnvironment env)
186   {
187     return XmlUtil.getPrevious(node);
188   }
189
190   /**
191    * Returns the next node in the selection order.
192    *
193    * @param node the current node
194    * @param lastNode the original node (for checking ancestors)
195    *
196    * @return the next node
197    */

198   public Node JavaDoc nextNode(Node JavaDoc node, Node JavaDoc lastNode)
199   {
200     loop:
201     while (node != null) {
202       node = XmlUtil.getPrevious(node);
203
204       for (Node JavaDoc ptr = lastNode; ptr != null; ptr = ptr.getParentNode()) {
205         if (ptr == node)
206           continue loop;
207       }
208
209       return node;
210     }
211
212     return null;
213   }
214
215   /**
216    * Returns the last node in the selection order.
217    *
218    * @param node the current node
219    *
220    * @return the last node
221    */

222   public Node JavaDoc lastNode(Node JavaDoc node)
223   {
224     return node;
225   }
226
227   /**
228    * Returns the next AxisContext. The axis context is the first following
229    * node matching the parent pattern.
230    */

231   private Node JavaDoc getAxisContext(Node JavaDoc axis, ExprEnvironment env, Node JavaDoc node)
232     throws XPathException
233   {
234     if (axis == null)
235       return null;
236
237     while ((axis = XmlUtil.getNext(axis)) != null) {
238       if (! isDescendant(axis, node) && _parent.match(axis, env))
239     return axis;
240     }
241     
242     return null;
243   }
244
245   private boolean isDescendant(Node JavaDoc descendant, Node JavaDoc node)
246   {
247     for (;
248      descendant != node && descendant != null;
249      descendant = descendant.getParentNode()) {
250     }
251
252     return descendant != null;
253   }
254
255   public String JavaDoc toString()
256   {
257     return getPrefix() + "preceding::";
258   }
259 }
260
261
Popular Tags