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.xml;
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:
064: if (_predicate != null && next != null
065: && _predicate.isMatch(next))
066: i = 0;
067: else
068: i = -1;
069: }
070:
071: QAbstractNode end = getEnd();
072: while (i < index && next != end) {
073: next = next.getNextPreorder();
074: if (next != end && _predicate.isMatch(next)) {
075: i++;
076: }
077: }
078:
079: if (next == end) {
080: next = null;
081: i = -1;
082: }
083: _index = i;
084: _node = next;
085:
086: return i == _index ? next : null;
087: }
088:
089: public int getLength() {
090: if (_changeCount != _top._owner._changeCount)
091: _length = -1;
092:
093: if (_length >= 0)
094: return _length;
095:
096: QAbstractNode end = getEnd();
097: _length = 0;
098: for (QAbstractNode ptr = _first; ptr != end; ptr = ptr
099: .getNextPreorder()) {
100: if (_predicate.isMatch(ptr))
101: _length++;
102: }
103:
104: return _length;
105: }
106:
107: /**
108: * Returns the final node in the preorder.
109: */
110: QAbstractNode getEnd() {
111: QAbstractNode end = _top;
112:
113: if (_first == null)
114: return null;
115:
116: while (end != null && end._next == null)
117: end = end._parent;
118:
119: return end == null ? null : end._next;
120: }
121:
122: // for quercus
123: public Iterator<Node> iterator() {
124: return new NodeListIterator(null, this);
125: }
126: }
|