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.axes;
017:
018: import org.apache.commons.jxpath.Pointer;
019: import org.apache.commons.jxpath.ri.EvalContext;
020: import org.apache.commons.jxpath.ri.compiler.NodeTest;
021: import org.apache.commons.jxpath.ri.model.NodeIterator;
022: import org.apache.commons.jxpath.ri.model.NodePointer;
023:
024: /**
025: * EvalContext that can walk the "child::", "following-sibling::" and
026: * "preceding-sibling::" axes.
027: *
028: * @author Dmitri Plotnikov
029: * @version $Revision: 1.16 $ $Date: 2004/03/25 03:49:50 $
030: */
031: public class ChildContext extends EvalContext {
032: private NodeTest nodeTest;
033: private boolean startFromParentLocation;
034: private boolean reverse;
035: private NodeIterator iterator;
036:
037: public ChildContext(EvalContext parentContext, NodeTest nodeTest,
038: boolean startFromParentLocation, boolean reverse) {
039: super (parentContext);
040: this .nodeTest = nodeTest;
041: this .startFromParentLocation = startFromParentLocation;
042: this .reverse = reverse;
043: }
044:
045: public NodePointer getCurrentNodePointer() {
046: if (position == 0) {
047: if (!setPosition(1)) {
048: return null;
049: }
050: }
051: if (iterator != null) {
052: return iterator.getNodePointer();
053: } else {
054: return null;
055: }
056: }
057:
058: /**
059: * This method is called on the last context on the path when only
060: * one value is needed. Note that this will return the whole property,
061: * even if it is a collection. It will not extract the first element
062: * of the collection. For example, "books" will return the collection
063: * of books rather than the first book from that collection.
064: */
065: public Pointer getSingleNodePointer() {
066: if (position == 0) {
067: while (nextSet()) {
068: prepare();
069: if (iterator == null) {
070: return null;
071: }
072: // See if there is a property there, singular or collection
073: NodePointer pointer = iterator.getNodePointer();
074: if (pointer != null) {
075: return pointer;
076: }
077: }
078: return null;
079: }
080: return getCurrentNodePointer();
081: }
082:
083: public boolean nextNode() {
084: return setPosition(getCurrentPosition() + 1);
085: }
086:
087: public void reset() {
088: super .reset();
089: iterator = null;
090: }
091:
092: public boolean setPosition(int position) {
093: int oldPosition = getCurrentPosition();
094: super .setPosition(position);
095: if (oldPosition == 0) {
096: prepare();
097: }
098: if (iterator == null) {
099: return false;
100: }
101: return iterator.setPosition(position);
102: }
103:
104: /**
105: * Allocates a PropertyIterator.
106: */
107: private void prepare() {
108: NodePointer parent = parentContext.getCurrentNodePointer();
109: if (parent == null) {
110: return;
111: }
112: if (startFromParentLocation) {
113: NodePointer pointer = parent.getParent();
114: iterator = pointer.childIterator(nodeTest, reverse, parent);
115: } else {
116: iterator = parent.childIterator(nodeTest, reverse, null);
117: }
118: }
119: }
|