001: /*
002: * Copyright 1999-2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.jxpath.ri.model.jdom;
017:
018: import java.util.Collections;
019: import java.util.List;
020:
021: import org.apache.commons.jxpath.ri.compiler.NodeTest;
022: import org.apache.commons.jxpath.ri.model.NodeIterator;
023: import org.apache.commons.jxpath.ri.model.NodePointer;
024: import org.jdom.Document;
025: import org.jdom.Element;
026:
027: /**
028: * An iterator of children of a JDOM Node.
029: *
030: * @author Dmitri Plotnikov
031: * @version $Revision: 1.6 $ $Date: 2004/02/29 14:17:40 $
032: */
033: public class JDOMNodeIterator implements NodeIterator {
034: private NodePointer parent;
035: private NodeTest nodeTest;
036:
037: private boolean reverse;
038: private int position = 0;
039: private int index = 0;
040: private List children;
041: private Object child;
042:
043: public JDOMNodeIterator(NodePointer parent, NodeTest nodeTest,
044: boolean reverse, NodePointer startWith) {
045: this .parent = parent;
046: if (startWith != null) {
047: this .child = startWith.getNode();
048: }
049: // TBD: optimize me for different node tests
050: Object node = parent.getNode();
051: if (node instanceof Document) {
052: this .children = ((Document) node).getContent();
053: } else if (node instanceof Element) {
054: this .children = ((Element) node).getContent();
055: } else {
056: this .children = Collections.EMPTY_LIST;
057: }
058: this .nodeTest = nodeTest;
059: this .reverse = reverse;
060: }
061:
062: public NodePointer getNodePointer() {
063: if (child == null) {
064: if (!setPosition(1)) {
065: return null;
066: }
067: position = 0;
068: }
069:
070: return new JDOMNodePointer(parent, child);
071: }
072:
073: public int getPosition() {
074: return position;
075: }
076:
077: public boolean setPosition(int position) {
078: while (this .position < position) {
079: if (!next()) {
080: return false;
081: }
082: }
083: while (this .position > position) {
084: if (!previous()) {
085: return false;
086: }
087: }
088: return true;
089: }
090:
091: /**
092: * This is actually never invoked during the normal evaluation
093: * of xpaths - an iterator is always going forward, never backwards.
094: * So, this is implemented only for completeness and perhaps for
095: * those who use these iterators outside of XPath evaluation.
096: */
097: private boolean previous() {
098: position--;
099: if (!reverse) {
100: while (--index >= 0) {
101: child = children.get(index);
102: if (testChild()) {
103: return true;
104: }
105: }
106: } else {
107: for (; index < children.size(); index++) {
108: child = children.get(index);
109: if (testChild()) {
110: return true;
111: }
112: }
113: }
114: return false;
115: }
116:
117: private boolean next() {
118: position++;
119: if (!reverse) {
120: if (position == 1) {
121: index = 0;
122: if (child != null) {
123: index = children.indexOf(child) + 1;
124: }
125: } else {
126: index++;
127: }
128: for (; index < children.size(); index++) {
129: child = children.get(index);
130: if (testChild()) {
131: return true;
132: }
133: }
134: return false;
135: } else {
136: if (position == 1) {
137: index = children.size() - 1;
138: if (child != null) {
139: index = children.indexOf(child) - 1;
140: }
141: } else {
142: index--;
143: }
144: for (; index >= 0; index--) {
145: child = children.get(index);
146: if (testChild()) {
147: return true;
148: }
149: }
150: return false;
151: }
152: }
153:
154: private boolean testChild() {
155: return JDOMNodePointer.testNode(parent, child, nodeTest);
156: }
157: }
|