KickJava   Java API By Example, From Geeks To Geeks.

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


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 any descendant.
40  */

41 public class FromDescendants extends Axis {
42   private boolean _self;
43
44   public FromDescendants(AbstractPattern parent, boolean self)
45   {
46     super(parent);
47     
48     _self = self;
49
50     if (parent == null)
51       throw new RuntimeException JavaDoc();
52   }
53
54   /**
55    * Matches the current node if it can find a parent node matching the
56    * parent pattern.
57    *
58    * @param node the node to test
59    * @param env the variable environment
60    *
61    * @return true if it matches.
62    */

63   public boolean match(Node JavaDoc node, ExprEnvironment env)
64     throws XPathException
65   {
66     if (node == null)
67       return false;
68
69     if (! _self)
70       node = node.getParentNode();
71     
72     for (; node != null; node = node.getParentNode()) {
73       if (_parent.match(node, env))
74     return true;
75     }
76
77     return false;
78   }
79
80   /**
81    * Counts matching nodes between the axis-context and the node
82    *
83    * @param node the starting node
84    * @param env the xpath environment
85    * @param pattern the axis match pattern
86    *
87    * @return the index of the position
88    */

89   public int position(Node JavaDoc node, Env env, AbstractPattern pattern)
90     throws XPathException
91   {
92     int index = env.getPositionIndex();
93
94     int pos = 0;
95
96     Node JavaDoc parentNode = node;
97     Node JavaDoc ptr = node;
98
99     for (; index >= 0; index--) {
100       for (; parentNode != null; parentNode = parentNode.getParentNode()) {
101         if (_parent.match(parentNode, env))
102           break;
103       }
104       
105       for (; ptr != null; ptr = XmlUtil.getPrevious(ptr)) {
106         if (ptr == parentNode && ! _self)
107           break;
108         
109         if (pattern.match(ptr, env))
110           pos++;
111
112         if (ptr == parentNode)
113           break;
114       }
115       
116       if (index > 0 && parentNode != null) {
117         parentNode = parentNode.getParentNode();
118         if (_self)
119           ptr = XmlUtil.getPrevious(ptr);
120       }
121       else
122         break;
123     }
124
125     if (parentNode != null)
126       parentNode = parentNode.getParentNode();
127     
128     for (; parentNode != null; parentNode = parentNode.getParentNode()) {
129       if (_parent.match(parentNode, env)) {
130         env.setMorePositions(true);
131         break;
132       }
133     }
134
135     return pos;
136   }
137
138   /**
139    * Counts the descendant nodes matching the pattern.
140    *
141    * @param node the starting node
142    * @param env the xpath environment
143    * @param pattern the axis match pattern
144    *
145    * @return the count of nodes
146    */

147   public int count(Node JavaDoc node, Env env, AbstractPattern pattern)
148     throws XPathException
149   {
150     int index = env.getPositionIndex();
151     
152     Node JavaDoc axis;
153     if (_self)
154       axis = getAxisContext(node, env);
155     else
156       axis = getAxisContext(node.getParentNode(), env);
157
158     for (; index > 0; index--)
159       axis = getAxisContext(axis.getParentNode(), env);
160
161     if (getAxisContext(axis.getParentNode(), env) != null)
162       env.setMorePositions(true);
163
164     int count = 0;
165     for (Node JavaDoc ptr = axis;
166      ptr != null;
167      ptr = XmlUtil.getNext(ptr)) {
168       if (pattern.match(ptr, env))
169     count++;
170     }
171
172     return count;
173   }
174
175   /**
176    * The axis context is any ancestor matching the parent pattern.
177    */

178   private Node JavaDoc getAxisContext(Node JavaDoc node, ExprEnvironment env)
179     throws XPathException
180   {
181     for (; node != null; node = node.getParentNode()) {
182       if (_parent.match(node, env))
183     return node;
184     }
185
186     return node;
187   }
188
189   /**
190    * Returns true if the pattern is strictly ascending.
191    */

192   public boolean isStrictlyAscending()
193   {
194     if (_parent == null)
195       return true;
196     else
197       return _parent.isSingleLevel();
198   }
199
200   /**
201    * Returns the first node in the selection order.
202    *
203    * @param node the current node
204    *
205    * @return the first node
206    */

207   public Node JavaDoc firstNode(Node JavaDoc node, ExprEnvironment env)
208   {
209     if (_self)
210       return node;
211     else
212       return node.getFirstChild();
213   }
214
215   /**
216    * Returns the next node in the selection order.
217    *
218    * @param node the current node
219    * @param ndoe the last node
220    *
221    * @return the next node
222    */

223   public Node JavaDoc nextNode(Node JavaDoc node, Node JavaDoc lastNode)
224   {
225     Node JavaDoc next = XmlUtil.getNext(node);
226     
227     return next == lastNode ? null : next;
228   }
229
230   /**
231    * Returns the last node in the selection order.
232    *
233    * @param node the current node
234    *
235    * @return the last node
236    */

237   public Node JavaDoc lastNode(Node JavaDoc node)
238   {
239     Node JavaDoc last = node;
240
241     for (;
242          last != null && last.getNextSibling() == null;
243          last = last.getParentNode()) {
244     }
245
246     return last != null ? last.getNextSibling() : null;
247   }
248
249   public String JavaDoc toString()
250   {
251     if (_self)
252       return getPrefix() + "descendant-or-self::";
253     else
254       return getPrefix() + "descendant::";
255   }
256 }
257
Popular Tags