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.xml2;
030:
031: import com.caucho.xpath.pattern.NodeListIterator;
032:
033: import org.w3c.dom.Node;
034: import org.w3c.dom.NodeList;
035:
036: import java.util.Iterator;
037:
038: public class QDeepNodeList implements NodeList {
039: QNode _top;
040: QNodePredicate _predicate;
041: QAbstractNode _first;
042: QAbstractNode _node;
043: int _index = -2;
044: int _length = -2;
045: int _changeCount;
046:
047: QDeepNodeList(QNode top, QAbstractNode first,
048: QNodePredicate predicate) {
049: _top = top;
050: _first = first;
051: _predicate = predicate;
052: }
053:
054: public Node item(int index) {
055: QAbstractNode next = _node;
056:
057: int i = _index;
058:
059: if (next == null || index < i
060: || _changeCount != _top._owner._changeCount) {
061: _changeCount = _top._owner._changeCount;
062: next = _first;
063: i = _predicate != null && _predicate.isMatch(next) ? 0 : -1;
064: }
065:
066: QAbstractNode end = getEnd();
067: while (i < index && next != end) {
068: next = next.getNextPreorder();
069: if (next != end && _predicate.isMatch(next)) {
070: i++;
071: }
072: }
073:
074: if (next == end) {
075: next = null;
076: i = -1;
077: }
078: _index = i;
079: _node = next;
080:
081: return i == _index ? next : null;
082: }
083:
084: public int getLength() {
085: if (_changeCount != _top._owner._changeCount)
086: _length = -1;
087:
088: if (_length >= 0)
089: return _length;
090:
091: QAbstractNode end = getEnd();
092: _length = 0;
093: for (QAbstractNode ptr = _first; ptr != end; ptr = ptr
094: .getNextPreorder()) {
095: if (_predicate.isMatch(ptr))
096: _length++;
097: }
098:
099: return _length;
100: }
101:
102: /**
103: * Returns the final node in the preorder.
104: */
105: QAbstractNode getEnd() {
106: QAbstractNode end = _top;
107:
108: if (_first == null)
109: return null;
110:
111: while (end != null && end._next == null)
112: end = end._parent;
113:
114: return end == null ? null : end._next;
115: }
116:
117: // for quercus
118: public Iterator<Node> iterator() {
119: return new NodeListIterator(null, this);
120: }
121: }
|