View Javadoc

1   /*
2    * Copyright 1999-2004 The Apache Software Foundation
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.commons.jxpath.ri.axes;
17  
18  import org.apache.commons.jxpath.Pointer;
19  import org.apache.commons.jxpath.ri.EvalContext;
20  import org.apache.commons.jxpath.ri.compiler.NodeTest;
21  import org.apache.commons.jxpath.ri.model.NodeIterator;
22  import org.apache.commons.jxpath.ri.model.NodePointer;
23  
24  /***
25   * EvalContext that can walk the "child::", "following-sibling::" and
26   * "preceding-sibling::" axes.
27   *
28   * @author Dmitri Plotnikov
29   * @version $Revision: 1.16 $ $Date: 2004/03/25 03:49:50 $
30   */
31  public class ChildContext extends EvalContext {
32      private NodeTest nodeTest;
33      private boolean startFromParentLocation;
34      private boolean reverse;
35      private NodeIterator iterator;
36  
37      public ChildContext(
38          EvalContext parentContext,
39          NodeTest nodeTest,
40          boolean startFromParentLocation,
41          boolean reverse) 
42      {
43          super(parentContext);
44          this.nodeTest = nodeTest;
45          this.startFromParentLocation = startFromParentLocation;
46          this.reverse = reverse;
47      }
48  
49      public NodePointer getCurrentNodePointer() {
50          if (position == 0) {
51              if (!setPosition(1)) {
52                  return null;
53              }
54          }
55          if (iterator != null) {
56              return iterator.getNodePointer();
57          }
58          else {
59              return null;
60          }
61      }
62  
63      /***
64       * This method is called on the last context on the path when only
65       * one value is needed.  Note that this will return the whole property,
66       * even if it is a collection. It will not extract the first element
67       * of the collection.  For example, "books" will return the collection
68       * of books rather than the first book from that collection.
69       */
70      public Pointer getSingleNodePointer() {
71          if (position == 0) {
72              while (nextSet()) {
73                  prepare();
74                  if (iterator == null) {
75                      return null;
76                  }
77                  // See if there is a property there, singular or collection
78                  NodePointer pointer = iterator.getNodePointer();
79                  if (pointer != null) {
80                      return pointer;
81                  }
82              }
83              return null;
84          }
85          return getCurrentNodePointer();
86      }
87  
88      public boolean nextNode() {
89          return setPosition(getCurrentPosition() + 1);
90      }
91  
92      public void reset() {
93          super.reset();
94          iterator = null;
95      }
96  
97      public boolean setPosition(int position) {
98          int oldPosition = getCurrentPosition();
99          super.setPosition(position);
100         if (oldPosition == 0) {
101             prepare();
102         }
103         if (iterator == null) {
104             return false;
105         }
106         return iterator.setPosition(position);
107     }
108 
109     /***
110      * Allocates a PropertyIterator.
111      */
112     private void prepare() {
113         NodePointer parent = parentContext.getCurrentNodePointer();
114         if (parent == null) {
115             return;
116         }
117         if (startFromParentLocation) {
118             NodePointer pointer = parent.getParent();
119             iterator = pointer.childIterator(nodeTest, reverse, parent);
120         }
121         else {
122             iterator = parent.childIterator(nodeTest, reverse, null);
123         }
124     }
125 }