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: MultipleNodeCounter.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.DOM;
025    import org.apache.xalan.xsltc.Translet;
026    import org.apache.xalan.xsltc.util.IntegerArray;
027    import org.apache.xml.dtm.DTMAxisIterator;
028    import org.apache.xml.dtm.Axis;
029    
030    /**
031     * @author Jacek Ambroziak
032     * @author Santiago Pericas-Geertsen
033     */
034    public abstract class MultipleNodeCounter extends NodeCounter {
035        private DTMAxisIterator _precSiblings = null;
036    
037        public MultipleNodeCounter(Translet translet,
038                                   DOM document, DTMAxisIterator iterator) {
039            super(translet, document, iterator);
040        }
041            
042        public NodeCounter setStartNode(int node) {
043            _node = node;
044            _nodeType = _document.getExpandedTypeID(node);
045        _precSiblings = _document.getAxisIterator(Axis.PRECEDINGSIBLING);
046            return this;
047        }
048    
049        public String getCounter() {
050            if (_value != Integer.MIN_VALUE) {
051                //See Errata E24
052                if (_value == 0) return "0";
053                else if (Double.isNaN(_value)) return "NaN";
054                else if (_value < 0 && Double.isInfinite(_value)) return "-Infinity";
055                else if (Double.isInfinite(_value)) return "Infinity";
056                else return formatNumbers((int)_value);
057            }
058    
059            IntegerArray ancestors = new IntegerArray();
060    
061            // Gather all ancestors that do not match from pattern
062            int next = _node;
063            ancestors.add(next);            // include self
064            while ((next = _document.getParent(next)) > END && 
065                   !matchesFrom(next)) {
066                ancestors.add(next);
067            }
068    
069            // Create an array of counters
070            final int nAncestors = ancestors.cardinality();
071            final int[] counters = new int[nAncestors]; 
072            for (int i = 0; i < nAncestors; i++) {
073                counters[i] = Integer.MIN_VALUE;
074            }
075    
076            // Increment array of counters according to semantics
077            for (int j = 0, i = nAncestors - 1; i >= 0 ; i--, j++) {
078                final int counter = counters[j];
079                final int ancestor = ancestors.at(i);
080    
081                if (matchesCount(ancestor)) {
082                    _precSiblings.setStartNode(ancestor);
083                    while ((next = _precSiblings.next()) != END) {
084                        if (matchesCount(next)) {
085                            counters[j] = (counters[j] == Integer.MIN_VALUE) ? 1 
086                                : counters[j] + 1;          
087                        }
088                    }
089                    // Count the node itself
090                    counters[j] = counters[j] == Integer.MIN_VALUE
091                        ? 1 
092                        : counters[j] + 1;  
093                }
094            }
095            return formatNumbers(counters);
096        }
097    
098        public static NodeCounter getDefaultNodeCounter(Translet translet,
099                                                        DOM document,
100                                                        DTMAxisIterator iterator) {
101            return new DefaultMultipleNodeCounter(translet, document, iterator);
102        }
103    
104        static class DefaultMultipleNodeCounter extends MultipleNodeCounter {
105            public DefaultMultipleNodeCounter(Translet translet,
106                                              DOM document,
107                                              DTMAxisIterator iterator) {
108                super(translet, document, iterator);
109            }
110        }
111    }