1. /*
  2. * Copyright 2001-2004 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*
  17. * $Id: MultipleNodeCounter.java,v 1.4 2004/02/16 22:54:59 minchau Exp $
  18. */
  19. package com.sun.org.apache.xalan.internal.xsltc.dom;
  20. import com.sun.org.apache.xalan.internal.xsltc.DOM;
  21. import com.sun.org.apache.xalan.internal.xsltc.Translet;
  22. import com.sun.org.apache.xalan.internal.xsltc.util.IntegerArray;
  23. import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
  24. /**
  25. * @author Jacek Ambroziak
  26. * @author Santiago Pericas-Geertsen
  27. */
  28. public abstract class MultipleNodeCounter extends NodeCounter {
  29. private DTMAxisIterator _precSiblings = null;
  30. public MultipleNodeCounter(Translet translet,
  31. DOM document, DTMAxisIterator iterator) {
  32. super(translet, document, iterator);
  33. }
  34. public NodeCounter setStartNode(int node) {
  35. _node = node;
  36. _nodeType = _document.getExpandedTypeID(node);
  37. _precSiblings = _document.getAxisIterator(PRECEDINGSIBLING);
  38. return this;
  39. }
  40. public String getCounter() {
  41. if (_value != Integer.MIN_VALUE) {
  42. return formatNumbers(_value);
  43. }
  44. IntegerArray ancestors = new IntegerArray();
  45. // Gather all ancestors that do not match from pattern
  46. int next = _node;
  47. ancestors.add(next); // include self
  48. while ((next = _document.getParent(next)) > END &&
  49. !matchesFrom(next)) {
  50. ancestors.add(next);
  51. }
  52. // Create an array of counters
  53. final int nAncestors = ancestors.cardinality();
  54. final int[] counters = new int[nAncestors];
  55. for (int i = 0; i < nAncestors; i++) {
  56. counters[i] = Integer.MIN_VALUE;
  57. }
  58. // Increment array of counters according to semantics
  59. for (int j = 0, i = nAncestors - 1; i >= 0 ; i--, j++) {
  60. final int counter = counters[j];
  61. final int ancestor = ancestors.at(i);
  62. if (matchesCount(ancestor)) {
  63. _precSiblings.setStartNode(ancestor);
  64. while ((next = _precSiblings.next()) != END) {
  65. if (matchesCount(next)) {
  66. counters[j] = (counters[j] == Integer.MIN_VALUE) ? 1
  67. : counters[j] + 1;
  68. }
  69. }
  70. // Count the node itself
  71. counters[j] = counters[j] == Integer.MIN_VALUE
  72. ? 1
  73. : counters[j] + 1;
  74. }
  75. }
  76. return formatNumbers(counters);
  77. }
  78. public static NodeCounter getDefaultNodeCounter(Translet translet,
  79. DOM document,
  80. DTMAxisIterator iterator) {
  81. return new DefaultMultipleNodeCounter(translet, document, iterator);
  82. }
  83. static class DefaultMultipleNodeCounter extends MultipleNodeCounter {
  84. public DefaultMultipleNodeCounter(Translet translet,
  85. DOM document,
  86. DTMAxisIterator iterator) {
  87. super(translet, document, iterator);
  88. }
  89. }
  90. }