You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

FOTreeBuilder.java 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. * $Id$
  3. * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
  4. * For details on use and redistribution please refer to the
  5. * LICENSE file included with these sources.
  6. */
  7. package org.apache.fop.fo;
  8. // FOP
  9. import org.apache.fop.apps.FOPException;
  10. import org.apache.fop.apps.StructureHandler;
  11. import org.apache.fop.fo.pagination.Root;
  12. import org.apache.fop.fo.pagination.PageSequence;
  13. import org.apache.fop.extensions.ExtensionObj;
  14. // Avalon
  15. import org.apache.avalon.framework.logger.Logger;
  16. // SAX
  17. import org.xml.sax.helpers.DefaultHandler;
  18. import org.xml.sax.SAXException;
  19. import org.xml.sax.InputSource;
  20. import org.xml.sax.Attributes;
  21. // Java
  22. import java.util.HashMap;
  23. import java.util.ArrayList;
  24. import java.io.IOException;
  25. /**
  26. * SAX Handler that builds the formatting object tree.
  27. *
  28. * Modified by Mark Lillywhite mark-fop@inomial.com. Now uses
  29. * StreamRenderer to automagically render the document as
  30. * soon as it receives a page-sequence end-tag. Also,
  31. * calls methods to set up and shut down the renderer at
  32. * the beginning and end of the FO document. Finally,
  33. * supresses adding the PageSequence object to the Root,
  34. * since it is parsed immediately.
  35. */
  36. public class FOTreeBuilder extends DefaultHandler {
  37. /**
  38. * table mapping element names to the makers of objects
  39. * representing formatting objects
  40. */
  41. protected HashMap fobjTable = new HashMap();
  42. protected ArrayList namespaces = new ArrayList();
  43. /**
  44. * current formatting object being handled
  45. */
  46. protected FONode currentFObj = null;
  47. /**
  48. * the root of the formatting object tree
  49. */
  50. protected FObj rootFObj = null;
  51. /**
  52. * set of names of formatting objects encountered but unknown
  53. */
  54. protected HashMap unknownFOs = new HashMap();
  55. /**
  56. *
  57. * The class that handles formatting and rendering to a stream
  58. * (mark-fop@inomial.com)
  59. */
  60. private StructureHandler structHandler;
  61. private FOUserAgent userAgent;
  62. public FOTreeBuilder() {}
  63. public Logger getLogger() {
  64. return userAgent.getLogger();
  65. }
  66. public void setUserAgent(FOUserAgent ua) {
  67. userAgent = ua;
  68. }
  69. public FOUserAgent getUserAgent() {
  70. return userAgent;
  71. }
  72. public void setStructHandler(StructureHandler sh) {
  73. this.structHandler = sh;
  74. }
  75. /**
  76. * add a mapping from element name to maker.
  77. *
  78. * @param namespaceURI namespace URI of formatting object element
  79. * @param localName local name of formatting object element
  80. * @param maker Maker for class representing formatting object
  81. */
  82. public void addMapping(String namespaceURI, HashMap table) {
  83. this.fobjTable.put(namespaceURI, table);
  84. this.namespaces.add(namespaceURI.intern());
  85. }
  86. /**
  87. * SAX Handler for characters
  88. */
  89. public void characters(char data[], int start, int length) {
  90. if(currentFObj != null) {
  91. currentFObj.addCharacters(data, start, start + length);
  92. }
  93. }
  94. /**
  95. * SAX Handler for the end of an element
  96. */
  97. public void endElement(String uri, String localName, String rawName)
  98. throws SAXException {
  99. currentFObj.end();
  100. currentFObj = currentFObj.getParent();
  101. }
  102. /**
  103. * SAX Handler for the start of the document
  104. */
  105. public void startDocument()
  106. throws SAXException {
  107. rootFObj = null; // allows FOTreeBuilder to be reused
  108. getLogger().info("building formatting object tree");
  109. structHandler.startDocument();
  110. }
  111. public void endDocument()
  112. throws SAXException {
  113. getLogger().info("Parsing of document complete, stopping renderer");
  114. structHandler.endDocument();
  115. }
  116. /**
  117. * SAX Handler for the start of an element
  118. */
  119. public void startElement(String uri, String localName, String rawName,
  120. Attributes attlist) throws SAXException {
  121. /* the formatting object started */
  122. FONode fobj;
  123. /* the maker for the formatting object started */
  124. ElementMapping.Maker fobjMaker = null;
  125. HashMap table = (HashMap)fobjTable.get(uri);
  126. if(table != null) {
  127. fobjMaker = (ElementMapping.Maker)table.get(localName);
  128. // try default
  129. if(fobjMaker == null) {
  130. fobjMaker = (ElementMapping.Maker)table.get(ElementMapping.DEFAULT);
  131. }
  132. }
  133. boolean foreignXML = false;
  134. if (fobjMaker == null) {
  135. String fullName = uri + "^" + localName;
  136. if (!this.unknownFOs.containsKey(fullName)) {
  137. this.unknownFOs.put(fullName, "");
  138. getLogger().warn("Unknown formatting object "
  139. + fullName);
  140. }
  141. if(namespaces.contains(uri.intern())) {
  142. // fall back
  143. fobjMaker = new Unknown.Maker();
  144. } else {
  145. fobjMaker = new UnknownXMLObj.Maker(uri);
  146. foreignXML = true;
  147. }
  148. }
  149. try {
  150. fobj = fobjMaker.make(currentFObj);
  151. fobj.setName(localName);
  152. // set the user agent for resolving user agent values
  153. fobj.setUserAgent(userAgent);
  154. // set the stream renderer so that appropriate
  155. // elements can add pages and handle resolving references
  156. fobj.setStructHandler(structHandler);
  157. fobj.handleAttrs(attlist);
  158. } catch (FOPException e) {
  159. throw new SAXException(e);
  160. }
  161. if (rootFObj == null) {
  162. if (!fobj.getName().equals("fo:root")) {
  163. throw new SAXException(new FOPException("Root element must"
  164. + " be fo:root, not "
  165. + fobj.getName()));
  166. }
  167. rootFObj = (FObj)fobj;
  168. } else {
  169. currentFObj.addChild(fobj);
  170. }
  171. currentFObj = fobj;
  172. }
  173. public void reset() {
  174. currentFObj = null;
  175. rootFObj = null;
  176. structHandler = null;
  177. }
  178. public boolean hasData() {
  179. return (rootFObj != null);
  180. }
  181. }