View Javadoc
1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   /*
6    * Copyright 2001-2004 The Apache Software Foundation.
7    *
8    * Licensed under the Apache License, Version 2.0 (the "License");
9    * you may not use this file except in compliance with the License.
10   * You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  /*
21   * $Id: StepIterator.java,v 1.2.4.1 2005/09/06 10:26:47 pvedula Exp $
22   */
23  
24  package com.sun.org.apache.xalan.internal.xsltc.dom;
25  
26  import com.sun.org.apache.xalan.internal.xsltc.runtime.BasisLibrary;
27  import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
28  import com.sun.org.apache.xml.internal.dtm.ref.DTMAxisIteratorBase;
29  
30  /**
31   * A step iterator is used to evaluate expressions like "BOOK/TITLE".
32   * A better name for this iterator would have been ParentIterator since
33   * both "BOOK" and "TITLE" are steps in XPath lingo. Step iterators are
34   * constructed from two other iterators which we are going to refer to
35   * as "outer" and "inner". Every node from the outer iterator (the one
36   * for BOOK in our example) is used to initialize the inner iterator.
37   * After this initialization, every node from the inner iterator is
38   * returned (in essence, implementing a "nested loop").
39   * @author Jacek Ambroziak
40   * @author Santiago Pericas-Geertsen
41   * @author Erwin Bolwidt <ejb@klomp.org>
42   * @author Morten Jorgensen
43   */
44  public class StepIterator extends DTMAxisIteratorBase {
45  
46      /**
47       * A reference to the "outer" iterator.
48       */
49      protected DTMAxisIterator _source;
50  
51      /**
52       * A reference to the "inner" iterator.
53       */
54      protected DTMAxisIterator _iterator;
55  
56      /**
57       * Temp variable to store a marked position.
58       */
59      private int _pos = -1;
60  
61      public StepIterator(DTMAxisIterator source, DTMAxisIterator iterator) {
62          _source = source;
63          _iterator = iterator;
64  // System.out.println("SI source = " + source + " this = " + this);
65  // System.out.println("SI iterator = " + iterator + " this = " + this);
66      }
67  
68  
69      public void setRestartable(boolean isRestartable) {
70          _isRestartable = isRestartable;
71          _source.setRestartable(isRestartable);
72          _iterator.setRestartable(true);         // must be restartable
73      }
74  
75      public DTMAxisIterator cloneIterator() {
76          _isRestartable = false;
77          try {
78              final StepIterator clone = (StepIterator) super.clone();
79              clone._source = _source.cloneIterator();
80              clone._iterator = _iterator.cloneIterator();
81              clone._iterator.setRestartable(true);       // must be restartable
82              clone._isRestartable = false;
83              return clone.reset();
84          }
85          catch (CloneNotSupportedException e) {
86              BasisLibrary.runTimeError(BasisLibrary.ITERATOR_CLONE_ERR,
87                                        e.toString());
88              return null;
89          }
90      }
91  
92      public DTMAxisIterator setStartNode(int node) {
93          if (_isRestartable) {
94              // Set start node for left-hand iterator...
95              _source.setStartNode(_startNode = node);
96  
97              // ... and get start node for right-hand iterator from left-hand,
98              // with special case for //* path - see ParentLocationPath
99              _iterator.setStartNode(_includeSelf ? _startNode : _source.next());
100             return resetPosition();
101         }
102         return this;
103     }
104 
105     public DTMAxisIterator reset() {
106         _source.reset();
107         // Special case for //* path - see ParentLocationPath
108         _iterator.setStartNode(_includeSelf ? _startNode : _source.next());
109         return resetPosition();
110     }
111 
112     public int next() {
113         for (int node;;) {
114             // Try to get another node from the right-hand iterator
115             if ((node = _iterator.next()) != END) {
116                 return returnNode(node);
117             }
118             // If not, get the next starting point from left-hand iterator...
119             else if ((node = _source.next()) == END) {
120                 return END;
121             }
122             // ...and pass it on to the right-hand iterator
123             else {
124                 _iterator.setStartNode(node);
125             }
126         }
127     }
128 
129     public void setMark() {
130         _source.setMark();
131         _iterator.setMark();
132         //_pos = _position;
133     }
134 
135     public void gotoMark() {
136         _source.gotoMark();
137         _iterator.gotoMark();
138         //_position = _pos;
139     }
140 }