1/*
2 * reserved comment block
3 * DO NOT REMOVE OR ALTER!
4 */
5/*
6 * Licensed to the Apache Software Foundation (ASF) under one or more
7 * contributor license agreements.  See the NOTICE file distributed with
8 * this work for additional information regarding copyright ownership.
9 * The ASF licenses this file to You under the Apache License, Version 2.0
10 * (the "License"); you may not use this file except in compliance with
11 * the License.  You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 */
21
22package com.sun.org.apache.xalan.internal.xsltc.dom;
23
24import com.sun.org.apache.xalan.internal.xsltc.runtime.BasisLibrary;
25import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
26import com.sun.org.apache.xml.internal.dtm.ref.DTMAxisIteratorBase;
27
28/**
29 * This is a special kind of iterator that takes a source iterator and a
30 * node N. If initialized with a node M (the parent of N) it computes the
31 * position of N amongst the children of M. This position can be obtained
32 * by calling getPosition().
33 * It is an iterator even though next() will never be called. It is used to
34 * match patterns with a single predicate like:
35 *
36 *    BOOK[position() = last()]
37 *
38 * In this example, the source iterator will return elements of type BOOK,
39 * a call to position() will return the position of N. Notice that because
40 * of the way the pattern matching is implemented, N will always be a node
41 * in the source since (i) it is a BOOK or the test sequence would not be
42 * considered and (ii) the source iterator is initialized with M which is
43 * the parent of N. Also, and still in this example, a call to last() will
44 * return the number of elements in the source (i.e. the number of BOOKs).
45 * @author Jacek Ambroziak
46 * @author Santiago Pericas-Geertsen
47 */
48public final class MatchingIterator extends DTMAxisIteratorBase {
49
50    /**
51     * A reference to a source iterator.
52     */
53    private DTMAxisIterator _source;
54
55    /**
56     * The node to match.
57     */
58    private final int _match;
59
60    public MatchingIterator(int match, DTMAxisIterator source) {
61        _source = source;
62        _match = match;
63    }
64
65
66    public void setRestartable(boolean isRestartable) {
67        _isRestartable = isRestartable;
68        _source.setRestartable(isRestartable);
69    }
70
71    public DTMAxisIterator cloneIterator() {
72
73        try {
74            final MatchingIterator clone = (MatchingIterator) super.clone();
75            clone._source = _source.cloneIterator();
76            clone._isRestartable = false;
77            return clone.reset();
78        }
79        catch (CloneNotSupportedException e) {
80            BasisLibrary.runTimeError(BasisLibrary.ITERATOR_CLONE_ERR,
81                                      e.toString());
82            return null;
83        }
84    }
85
86    public DTMAxisIterator setStartNode(int node) {
87        if (_isRestartable) {
88            // iterator is not a clone
89            _source.setStartNode(node);
90
91            // Calculate the position of the node in the set
92            _position = 1;
93            while ((node = _source.next()) != END && node != _match) {
94                _position++;
95            }
96        }
97        return this;
98    }
99
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}
128