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: MatchingIterator.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 * This is a special kind of iterator that takes a source iterator and a 030 * node N. If initialized with a node M (the parent of N) it computes the 031 * position of N amongst the children of M. This position can be obtained 032 * by calling getPosition(). 033 * It is an iterator even though next() will never be called. It is used to 034 * match patterns with a single predicate like: 035 * 036 * BOOK[position() = last()] 037 * 038 * In this example, the source iterator will return elements of type BOOK, 039 * a call to position() will return the position of N. Notice that because 040 * of the way the pattern matching is implemented, N will always be a node 041 * in the source since (i) it is a BOOK or the test sequence would not be 042 * considered and (ii) the source iterator is initialized with M which is 043 * the parent of N. Also, and still in this example, a call to last() will 044 * return the number of elements in the source (i.e. the number of BOOKs). 045 * @author Jacek Ambroziak 046 * @author Santiago Pericas-Geertsen 047 */ 048 public final class MatchingIterator extends DTMAxisIteratorBase { 049 050 /** 051 * A reference to a source iterator. 052 */ 053 private DTMAxisIterator _source; 054 055 /** 056 * The node to match. 057 */ 058 private final int _match; 059 060 public MatchingIterator(int match, DTMAxisIterator source) { 061 _source = source; 062 _match = match; 063 } 064 065 066 public void setRestartable(boolean isRestartable) { 067 _isRestartable = isRestartable; 068 _source.setRestartable(isRestartable); 069 } 070 071 public DTMAxisIterator cloneIterator() { 072 073 try { 074 final MatchingIterator clone = (MatchingIterator) super.clone(); 075 clone._source = _source.cloneIterator(); 076 clone._isRestartable = false; 077 return clone.reset(); 078 } 079 catch (CloneNotSupportedException e) { 080 BasisLibrary.runTimeError(BasisLibrary.ITERATOR_CLONE_ERR, 081 e.toString()); 082 return null; 083 } 084 } 085 086 public DTMAxisIterator setStartNode(int node) { 087 if (_isRestartable) { 088 // iterator is not a clone 089 _source.setStartNode(node); 090 091 // Calculate the position of the node in the set 092 _position = 1; 093 while ((node = _source.next()) != END && node != _match) { 094 _position++; 095 } 096 } 097 return this; 098 } 099 100 public DTMAxisIterator reset() { 101 _source.reset(); 102 return resetPosition(); 103 } 104 105 public int next() { 106 return _source.next(); 107 } 108 109 public int getLast() { 110 if (_last == -1) { 111 _last = _source.getLast(); 112 } 113 return _last; 114 } 115 116 public int getPosition() { 117 return _position; 118 } 119 120 public void setMark() { 121 _source.setMark(); 122 } 123 124 public void gotoMark() { 125 _source.gotoMark(); 126 } 127 }