001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.xpath.pattern;
030:
031: import com.caucho.xpath.ExprEnvironment;
032: import com.caucho.xpath.XPathException;
033:
034: import org.w3c.dom.Node;
035:
036: import java.util.logging.Level;
037:
038: /**
039: * Uses the axis to select new nodes.
040: */
041: public class AxisIterator extends NodeIterator {
042: protected NodeIterator _parentIter;
043: protected AbstractPattern _axis;
044: protected Node _node;
045: protected Node _next;
046: protected Node _lastNode;
047: protected AbstractPattern _match;
048:
049: protected AxisIterator(ExprEnvironment env) {
050: super (env);
051: }
052:
053: /**
054: * Creates the new AxisIterator.
055: *
056: * @param parentIter the parent iterator
057: * @param axis the owning axis
058: * @param node the first node
059: * @param env the variable environment
060: * @param match the node matching pattern
061: */
062: public AxisIterator(NodeIterator parentIter, AbstractPattern axis,
063: Node node, ExprEnvironment env, AbstractPattern match)
064: throws XPathException {
065: super (env);
066:
067: _parentIter = parentIter;
068: _axis = axis;
069: _match = match;
070:
071: if (parentIter != null && parentIter.hasNext()) {
072: node = parentIter.nextNode();
073: }
074:
075: if (node != null) {
076: _lastNode = axis.lastNode(node);
077: _node = findFirstMatchingNode(axis.firstNode(node, _env));
078: }
079:
080: _next = _node;
081: }
082:
083: /**
084: * True if there's more data.
085: */
086: public boolean hasNext() {
087: if (_next == null) {
088: try {
089: _next = nextNode();
090: } catch (XPathException e) {
091: log.log(Level.FINE, e.toString(), e);
092: }
093: }
094:
095: return _next != null;
096: }
097:
098: /**
099: * Returns the next selected node.
100: */
101: public Node nextNode() throws XPathException {
102: if (_next != null) {
103: _node = _next;
104: _next = null;
105:
106: return _node;
107: }
108:
109: if (_node != null)
110: _node = findFirstMatchingNode(_axis.nextNode(_node,
111: _lastNode));
112:
113: _next = null;
114:
115: return _node;
116: }
117:
118: /**
119: * Finds the next matching node.
120: */
121: private Node findFirstMatchingNode(Node node) throws XPathException {
122: while (true) {
123: if (node != null) {
124: if (_match == null || _match.match(node, _env)) {
125: _position++;
126: return node;
127: } else {
128: node = _axis.nextNode(node, _lastNode);
129: continue;
130: }
131: }
132:
133: else if (_parentIter == null
134: || (node = _parentIter.nextNode()) == null)
135: return null;
136: else {
137: _position = 0;
138: _size = 0;
139: _lastNode = _axis.lastNode(node);
140: node = _axis.firstNode(node, _env);
141: }
142: }
143: }
144:
145: /**
146: * Returns the number of nodes in the context list.
147: */
148: public int getContextSize() {
149: if (_size == 0) {
150: _size = _position;
151:
152: try {
153: Node ptr = _node == null ? null : _axis.nextNode(_node,
154: _lastNode);
155:
156: for (; ptr != null; ptr = _axis
157: .nextNode(ptr, _lastNode)) {
158: if (_match == null || _match.match(ptr, _env))
159: _size++;
160: }
161: } catch (XPathException e) {
162: log.log(Level.FINE, e.toString(), e);
163: }
164: }
165:
166: return _size;
167: }
168:
169: public Object clone() {
170: AxisIterator iter = new AxisIterator(_env);
171:
172: iter.copy(this );
173:
174: if (_parentIter != null)
175: iter._parentIter = (NodeIterator) _parentIter.clone();
176:
177: iter._axis = _axis;
178: iter._node = _node;
179: iter._match = _match;
180:
181: return iter;
182: }
183:
184: public String toString() {
185: return "AxisIterator[axis:" + _axis + ",match:" + _match + "]";
186: }
187: }
|