001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 /* 019 * $Id: StepIterator.java 468651 2006-10-28 07:04:25Z minchau $ 020 */ 021 022 package org.apache.xalan.xsltc.dom; 023 024 import org.apache.xalan.xsltc.runtime.BasisLibrary; 025 import org.apache.xml.dtm.DTMAxisIterator; 026 import org.apache.xml.dtm.ref.DTMAxisIteratorBase; 027 028 /** 029 * A step iterator is used to evaluate expressions like "BOOK/TITLE". 030 * A better name for this iterator would have been ParentIterator since 031 * both "BOOK" and "TITLE" are steps in XPath lingo. Step iterators are 032 * constructed from two other iterators which we are going to refer to 033 * as "outer" and "inner". Every node from the outer iterator (the one 034 * for BOOK in our example) is used to initialize the inner iterator. 035 * After this initialization, every node from the inner iterator is 036 * returned (in essence, implementing a "nested loop"). 037 * @author Jacek Ambroziak 038 * @author Santiago Pericas-Geertsen 039 * @author Erwin Bolwidt <ejb@klomp.org> 040 * @author Morten Jorgensen 041 */ 042 public class StepIterator extends DTMAxisIteratorBase { 043 044 /** 045 * A reference to the "outer" iterator. 046 */ 047 protected DTMAxisIterator _source; 048 049 /** 050 * A reference to the "inner" iterator. 051 */ 052 protected DTMAxisIterator _iterator; 053 054 /** 055 * Temp variable to store a marked position. 056 */ 057 private int _pos = -1; 058 059 public StepIterator(DTMAxisIterator source, DTMAxisIterator iterator) { 060 _source = source; 061 _iterator = iterator; 062 // System.out.println("SI source = " + source + " this = " + this); 063 // System.out.println("SI iterator = " + iterator + " this = " + this); 064 } 065 066 067 public void setRestartable(boolean isRestartable) { 068 _isRestartable = isRestartable; 069 _source.setRestartable(isRestartable); 070 _iterator.setRestartable(true); // must be restartable 071 } 072 073 public DTMAxisIterator cloneIterator() { 074 _isRestartable = false; 075 try { 076 final StepIterator clone = (StepIterator) super.clone(); 077 clone._source = _source.cloneIterator(); 078 clone._iterator = _iterator.cloneIterator(); 079 clone._iterator.setRestartable(true); // must be restartable 080 clone._isRestartable = false; 081 return clone.reset(); 082 } 083 catch (CloneNotSupportedException e) { 084 BasisLibrary.runTimeError(BasisLibrary.ITERATOR_CLONE_ERR, 085 e.toString()); 086 return null; 087 } 088 } 089 090 public DTMAxisIterator setStartNode(int node) { 091 if (_isRestartable) { 092 // Set start node for left-hand iterator... 093 _source.setStartNode(_startNode = node); 094 095 // ... and get start node for right-hand iterator from left-hand, 096 // with special case for //* path - see ParentLocationPath 097 _iterator.setStartNode(_includeSelf ? _startNode : _source.next()); 098 return resetPosition(); 099 } 100 return this; 101 } 102 103 public DTMAxisIterator reset() { 104 _source.reset(); 105 // Special case for //* path - see ParentLocationPath 106 _iterator.setStartNode(_includeSelf ? _startNode : _source.next()); 107 return resetPosition(); 108 } 109 110 public int next() { 111 for (int node;;) { 112 // Try to get another node from the right-hand iterator 113 if ((node = _iterator.next()) != END) { 114 return returnNode(node); 115 } 116 // If not, get the next starting point from left-hand iterator... 117 else if ((node = _source.next()) == END) { 118 return END; 119 } 120 // ...and pass it on to the right-hand iterator 121 else { 122 _iterator.setStartNode(node); 123 } 124 } 125 } 126 127 public void setMark() { 128 _source.setMark(); 129 _iterator.setMark(); 130 //_pos = _position; 131 } 132 133 public void gotoMark() { 134 _source.gotoMark(); 135 _iterator.gotoMark(); 136 //_position = _pos; 137 } 138 }