1. /*
  2. * @(#)TagStack.java 1.10 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing.text.html.parser;
  8. import java.util.BitSet;
  9. import java.util.Vector;
  10. import java.io.*;
  11. /**
  12. * A stack of tags. Used while parsing an HTML document.
  13. * It, together with the ContentModelStates, defines the
  14. * complete state of the parser while reading a document.
  15. * When a start tag is encountered an element is pushed onto
  16. * the stack, when an end tag is enountered an element is popped
  17. * of the stack.
  18. *
  19. * @see Parser
  20. * @see DTD
  21. * @see ContentModelState
  22. * @version 1.10, 12/19/03
  23. * @author Arthur van Hoff
  24. */
  25. final
  26. class TagStack implements DTDConstants {
  27. TagElement tag;
  28. Element elem;
  29. ContentModelState state;
  30. TagStack next;
  31. BitSet inclusions;
  32. BitSet exclusions;
  33. boolean net;
  34. boolean pre;
  35. /**
  36. * Construct a stack element.
  37. */
  38. TagStack(TagElement tag, TagStack next) {
  39. this.tag = tag;
  40. this.elem = tag.getElement();
  41. this.next = next;
  42. Element elem = tag.getElement();
  43. if (elem.getContent() != null) {
  44. this.state = new ContentModelState(elem.getContent());
  45. }
  46. if (next != null) {
  47. inclusions = next.inclusions;
  48. exclusions = next.exclusions;
  49. pre = next.pre;
  50. }
  51. if (tag.isPreformatted()) {
  52. pre = true;
  53. }
  54. if (elem.inclusions != null) {
  55. if (inclusions != null) {
  56. inclusions = (BitSet)inclusions.clone();
  57. inclusions.or(elem.inclusions);
  58. } else {
  59. inclusions = elem.inclusions;
  60. }
  61. }
  62. if (elem.exclusions != null) {
  63. if (exclusions != null) {
  64. exclusions = (BitSet)exclusions.clone();
  65. exclusions.or(elem.exclusions);
  66. } else {
  67. exclusions = elem.exclusions;
  68. }
  69. }
  70. }
  71. /**
  72. * Return the element that must come next in the
  73. * input stream.
  74. */
  75. public Element first() {
  76. return (state != null) ? state.first() : null;
  77. }
  78. /**
  79. * Return the ContentModel that must be satisfied by
  80. * what comes next in the input stream.
  81. */
  82. public ContentModel contentModel() {
  83. if (state == null) {
  84. return null;
  85. } else {
  86. return state.getModel();
  87. }
  88. }
  89. /**
  90. * Return true if the element that is contained at
  91. * the index specified by the parameter is part of
  92. * the exclusions specified in the DTD for the element
  93. * currently on the TagStack.
  94. */
  95. boolean excluded(int elemIndex) {
  96. return (exclusions != null) && exclusions.get(elem.getIndex());
  97. }
  98. /**
  99. * Update the Vector elemVec with all the elements that
  100. * are part of the inclusions listed in DTD for the element
  101. * currently on the TagStack.
  102. */
  103. boolean included(Vector elemVec, DTD dtd) {
  104. for (int i = 0 ; i < inclusions.size(); i++) {
  105. if (inclusions.get(i)) {
  106. elemVec.addElement(dtd.getElement(i));
  107. System.out.println("Element add thru' inclusions: " + dtd.getElement(i).getName());
  108. }
  109. }
  110. return (!elemVec.isEmpty());
  111. }
  112. /**
  113. * Advance the state by reducing the given element.
  114. * Returns false if the element is not legal and the
  115. * state is not advanced.
  116. */
  117. boolean advance(Element elem) {
  118. if ((exclusions != null) && exclusions.get(elem.getIndex())) {
  119. return false;
  120. }
  121. if (state != null) {
  122. ContentModelState newState = state.advance(elem);
  123. if (newState != null) {
  124. state = newState;
  125. return true;
  126. }
  127. } else if (this.elem.getType() == ANY) {
  128. return true;
  129. }
  130. return (inclusions != null) && inclusions.get(elem.getIndex());
  131. }
  132. /**
  133. * Return true if the current state can be terminated.
  134. */
  135. boolean terminate() {
  136. return (state == null) || state.terminate();
  137. }
  138. /**
  139. * Convert to a string.
  140. */
  141. public String toString() {
  142. return (next == null) ?
  143. "<" + tag.getElement().getName() + ">" :
  144. next + " <" + tag.getElement().getName() + ">";
  145. }
  146. }
  147. class NPrintWriter extends PrintWriter {
  148. private int numLines = 5;
  149. private int numPrinted = 0;
  150. public NPrintWriter (int numberOfLines) {
  151. super(System.out);
  152. numLines = numberOfLines;
  153. }
  154. public void println(char[] array) {
  155. if (numPrinted >= numLines) {
  156. return;
  157. }
  158. char[] partialArray = null;
  159. for (int i = 0; i < array.length; i++) {
  160. if (array[i] == '\n') {
  161. numPrinted++;
  162. }
  163. if (numPrinted == numLines) {
  164. System.arraycopy(array, 0, partialArray, 0, i);
  165. }
  166. }
  167. if (partialArray != null) {
  168. super.print(partialArray);
  169. }
  170. if (numPrinted == numLines) {
  171. return;
  172. }
  173. super.println(array);
  174. numPrinted++;
  175. }
  176. }