Phase 1: Building the FO tree
Creating the FO nodes FOP's first task is building a suitable data structure from the XML input, which is an XML file with formatting objects or a result tree with formatting objects from an XSLT transformation. One could call this FOP's data binding. The data structure is an FO tree, i.e., a tree of FONode objects. The structure of the FO tree exactly parallels the structure of the XML file or the corresponding DOM tree, but instead of XML nodes its nodes are objects of type org.apache.fop.fo.FONode. The FO tree is built on the basis of SAX parser events. The parser is responsible for parsing the XML document; it calls FOP's callbacks when SAX events occur. FOP's callbacks are implemented by the FOTreeBuilder treebuilder object, which is a SAX content handler. It was constructed in the preparation phase, and registered with the parser as the content handler. It has meaningful implementations of the methods startDocument, endDocument, startElement, endElement, and characters. treebuilder delegates its startDocument and endDocument methods to its FOTreeHandler object foInputHandler. FOTreeHandler is a subclas of FOInputHandler. treebuilder.foInputHandler = { runtime: instance of java.lang.Runtime(id=635) pageCount: 0 initialMemory: 0 startTime: 0 foTreeListeners: instance of java.util.HashSet(id=636) org.apache.fop.fo.FOInputHandler.foTreeControl: instance of org.apache.fop.apps.Document(id=634) org.apache.avalon.framework.logger.AbstractLogEnabled.m_logger: instance of org.apache.avalon.framework.logger.ConsoleLogger(id=342) } The first important task of treebuilder is creating a suitable FO node for each element in the XML document. This is done in its startElement method. Its most important tool in this process is its fobjTable object. fobjTable is a map of maps. For each namespace supported by FOP it contains a map of local XML element name to a Node maker object fobjMaker, of type ElementMapping.Maker. In addition to the FO namespace it contains makers for FOP's extensions namespace, the SVG namespace and Batik's extensions namespace. treebuilder.fobjTable = "{ http://www.w3.org/1999/XSL/Format={ static-content=org.apache.fop.fo.FOElementMapping$SC@39e5b5, table=org.apache.fop.fo.FOElementMapping$Ta@117f31e, external-graphic=org.apache.fop.fo.FOElementMapping$EG@15a6029, table-column=org.apache.fop.fo.FOElementMapping$TC@5f6303, table-and-caption=org.apache.fop.fo.FOElementMapping$TAC@5d9084, table-footer=org.apache.fop.fo.FOElementMapping$TB@bad8a8, declarations=org.apache.fop.fo.FOElementMapping$Dec@e61fd1, wrapper=org.apache.fop.fo.FOElementMapping$W@331059, page-sequence=org.apache.fop.fo.FOElementMapping$PS@766a24, single-page-master-reference=org.apache.fop.fo.FOElementMapping$SPMR@32784a, footnote=org.apache.fop.fo.FOElementMapping$Foot@1774b9b, multi-switch=org.apache.fop.fo.FOElementMapping$MS@104c575, bidi-override=org.apache.fop.fo.FOElementMapping$BO@3fa5ac, layout-master-set=org.apache.fop.fo.FOElementMapping$LMS@95cfbe, float=org.apache.fop.fo.FOElementMapping$F@179dce4, list-item=org.apache.fop.fo.FOElementMapping$LI@1950198, basic-link=org.apache.fop.fo.FOElementMapping$BL@19bb25a, multi-property-set=org.apache.fop.fo.FOElementMapping$MPS@da6bf4, table-row=org.apache.fop.fo.FOElementMapping$TR@1e58cb8, region-end=org.apache.fop.fo.FOElementMapping$RE@179935d, block=org.apache.fop.fo.FOElementMapping$B@b9e45a, leader=org.apache.fop.fo.FOElementMapping$L@3ef810, table-header=org.apache.fop.fo.FOElementMapping$TB@100363, list-item-body=org.apache.fop.fo.FOElementMapping$LIB@14e8cee, multi-properties=org.apache.fop.fo.FOElementMapping$MP@67064, region-after=org.apache.fop.fo.FOElementMapping$RA@bcda2d, multi-case=org.apache.fop.fo.FOElementMapping$MC@97d01f, block-container=org.apache.fop.fo.FOElementMapping$BC@e0a386, title=org.apache.fop.fo.FOElementMapping$T@feb48, retrieve-marker=org.apache.fop.fo.FOElementMapping$RM@11ff436, color-profile=org.apache.fop.fo.FOElementMapping$CP@da3a1e, character=org.apache.fop.fo.FOElementMapping$Ch@11dba45, simple-page-master=org.apache.fop.fo.FOElementMapping$SPM@b03be0, page-sequence-master=org.apache.fop.fo.FOElementMapping$PSM@2af081, footnote-body=org.apache.fop.fo.FOElementMapping$FB@113a53d, marker=org.apache.fop.fo.FOElementMapping$M@c5495e, table-body=org.apache.fop.fo.FOElementMapping$TB@53fb57, inline=org.apache.fop.fo.FOElementMapping$In@19a32e0, table-cell=org.apache.fop.fo.FOElementMapping$TCell@8238f4, list-block=org.apache.fop.fo.FOElementMapping$LB@16925b0, region-start=org.apache.fop.fo.FOElementMapping$RS@297ffb, table-caption=org.apache.fop.fo.FOElementMapping$TCaption@914f6a, conditional-page-master-reference=org.apache.fop.fo.FOElementMapping$CPMR@1f4cbee, list-item-label=org.apache.fop.fo.FOElementMapping$LIL@787d6a, multi-toggle=org.apache.fop.fo.FOElementMapping$MT@71dc3d, initial-property-set=org.apache.fop.fo.FOElementMapping$IPS@1326484, repeatable-page-master-alternatives=org.apache.fop.fo.FOElementMapping$RPMA@16546ef, repeatable-page-master-reference=org.apache.fop.fo.FOElementMapping$RPMR@1428ea, flow=org.apache.fop.fo.FOElementMapping$Fl@18a49e0, page-number=org.apache.fop.fo.FOElementMapping$PN@1f82982, instream-foreign-object=org.apache.fop.fo.FOElementMapping$IFO@16d2633, inline-container=org.apache.fop.fo.FOElementMapping$IC@e70e30, root=org.apache.fop.fo.FOElementMapping$R@154864a, region-before=org.apache.fop.fo.FOElementMapping$RBefore@3c9217, region-body=org.apache.fop.fo.FOElementMapping$RB@9b42e6, page-number-citation=org.apache.fop.fo.FOElementMapping$PNC@14520eb }, http://xml.apache.org/fop/extensions={ bookmarks=org.apache.fop.fo.extensions.ExtensionElementMapping$B@1d7fbfb, label=org.apache.fop.fo.extensions.ExtensionElementMapping$L@e020c9, outline=org.apache.fop.fo.extensions.ExtensionElementMapping$O@888e6c }, http://www.w3.org/2000/svg={ <default>=org.apache.fop.fo.extensions.svg.SVGElementMapping$SVGMaker@1742700, svg=org.apache.fop.fo.extensions.svg.SVGElementMapping$SE@acb158 }, http://xml.apache.org/batik/ext={ <default>=org.apache.fop.fo.extensions.svg.BatikExtensionElementMapping$SVGMaker@1af33d6, batik=org.apache.fop.fo.extensions.svg.BatikExtensionElementMapping$SE@17431b9 } }" The values in this map are objects of subclasses of ElementMapping.Maker. ElementMapping.Maker is a static nested class of ElementMapping. It has no members and a single object method FONode make(FONode parent). The subclasses are static nested classes of FOElementMapping. Each subclass has its own implementation of the make method, and returns its own subclass of FONode. For example, FOElementMapping$R returns a org.apache.fop.fo.pagination.Root object. treebuilder delegates its endElement method to the node's end method, which allows FOP to take appropriate action at the end of each FO element. The only node type whose end method takes special action, is org.apache.fop.fo.pagination.PageSequence. It hands control to FOP's next phase, building of the area tree.
Creating the property values Formatting objects have many attributes by which the user may finetune their behaviour. When the FO tree is built, the attributes must be converted to properties. This conversion process must implement XSLT's sometimes complicated rules of default values, inheritance, shorthand notations etc. This is one of the tasks of the property subsystem, which is described in its own chapter.