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.DOM;
25import com.sun.org.apache.xalan.internal.xsltc.Translet;
26import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
27import com.sun.org.apache.xml.internal.dtm.Axis;
28
29
30/**
31 * @author Jacek Ambroziak
32 * @author Santiago Pericas-Geertsen
33 */
34public abstract class SingleNodeCounter extends NodeCounter {
35    static private final int[] EmptyArray = new int[] { };
36    DTMAxisIterator _countSiblings = null;
37
38    public SingleNodeCounter(Translet translet,
39                             DOM document,
40                             DTMAxisIterator iterator) {
41        super(translet, document, iterator);
42    }
43
44    public SingleNodeCounter(Translet translet,
45                             DOM document,
46                             DTMAxisIterator iterator,
47                             boolean hasFrom) {
48        super(translet, document, iterator, hasFrom);
49    }
50
51    public NodeCounter setStartNode(int node) {
52        _node = node;
53        _nodeType = _document.getExpandedTypeID(node);
54    _countSiblings = _document.getAxisIterator(Axis.PRECEDINGSIBLING);
55        return this;
56    }
57
58    public String getCounter() {
59        int result;
60        if (_value != Integer.MIN_VALUE) {
61                //See Errata E24
62                if (_value == 0) return "0";
63                else if (Double.isNaN(_value)) return "NaN";
64                else if (_value < 0 && Double.isInfinite(_value)) return "-Infinity";
65                else if (Double.isInfinite(_value)) return "Infinity";
66                else result = (int) _value;
67        }
68        else {
69            int next = _node;
70            result = 0;
71            boolean matchesCount = matchesCount(next);
72
73            if (!matchesCount) {
74                while ((next = _document.getParent(next)) > END) {
75                    if (matchesCount(next)) {
76                        break;          // found target
77                    }
78                    if (matchesFrom(next)) {
79                        next = END;
80                        break;          // no target found
81                    }
82                }
83            }
84
85            if (next != END) {
86                int from = next;
87
88                if (!matchesCount && _hasFrom) {
89                    // Target found, but need to check if ancestor matches from
90                    while ((from = _document.getParent(from)) > END) {
91                        if (matchesFrom(from)) {
92                            break;          // found from
93                        }
94                    }
95                }
96
97                // Have we found ancestor matching from?
98                if (from != END) {
99                    _countSiblings.setStartNode(next);
100                    do {
101                        if (matchesCount(next)) result++;
102                    } while ((next = _countSiblings.next()) != END);
103
104                    return formatNumbers(result);
105                }
106            }
107
108            // If no target found then pass the empty list
109            return formatNumbers(EmptyArray);
110        }
111        return formatNumbers(result);
112    }
113
114    public static NodeCounter getDefaultNodeCounter(Translet translet,
115                                                    DOM document,
116                                                    DTMAxisIterator iterator) {
117        return new DefaultSingleNodeCounter(translet, document, iterator);
118    }
119
120    static class DefaultSingleNodeCounter extends SingleNodeCounter {
121        public DefaultSingleNodeCounter(Translet translet,
122                                        DOM document, DTMAxisIterator iterator) {
123            super(translet, document, iterator);
124        }
125
126        public NodeCounter setStartNode(int node) {
127            _node = node;
128            _nodeType = _document.getExpandedTypeID(node);
129            _countSiblings =
130        _document.getTypedAxisIterator(Axis.PRECEDINGSIBLING,
131                                               _document.getExpandedTypeID(node));
132            return this;
133        }
134
135        public String getCounter() {
136            int result;
137            if (_value != Integer.MIN_VALUE) {
138                //See Errata E24
139                if (_value == 0) return "0";
140                else if (Double.isNaN(_value)) return "NaN";
141                else if (_value < 0 && Double.isInfinite(_value)) return "-Infinity";
142                else if (Double.isInfinite(_value)) return "Infinity";
143                else result = (int) _value;
144            }
145            else {
146                int next;
147                result = 1;
148                _countSiblings.setStartNode(_node);
149                while ((next = _countSiblings.next()) != END) {
150                    result++;
151                }
152            }
153            return formatNumbers(result);
154        }
155    }
156}
157