Jeremias Maerki wrote: > > The answer to your question probably lies in understanding how and why > > getContentHandler() is used without also using render(). The > FOTreeListener > > is only needed if the input document is parsed, and in fact is > only needed > > if you want to break out of parsing to go do something at a higher level > > before returning (the normal SAX events are not affected at all). So: > > 1) if the process running getContentHandler() doesn't ever parse, don't > > bother registering the FOTreeListener > > Does that ever happen? I would assume that anyone who calls > getContentHandler() will want to send SAX events. I don't think I > understand what you're trying to explain. Sorry.
I don't know whether it happens or not. I can't think of a reason for this to be done. Since I don't understand how this is getting used, I was just trying to cover all possibilities. > > 2) if the process running getContentHandler() doesn't care about being > > notified about the end of a PageSequence (which is the only > FOTreeListener > > event that is *unique*), don't bother registering the FOTreeListener > > Ok, I guess that is something that was introduced by your LayoutStrategy. > Would you explain to me what you mean by "process" in this context? It is only loosely related to LayoutStrategy. It had more to do with trying to separate the parsing and layout (somewhat foundational to LayoutStrategy, but useful even apart from that). fo.FOTreeEvent and fo.FOTreeListener kind of mimic what the SAX events do, but are fired from within FOP as the FOTree is being built. This allows FOTree to do its thing without needing to know how it is being used. By "process" I just mean whatever embedded application is calling getContentHandler(). > > 3) otherwise, have it wrap its parsing code inside of the > following (which > > is what is wrapped around parser.parse in render() now): > > <before> > > if (foInputHandler instanceof FOTreeHandler) { > > FOTreeHandler foTreeHandler = > (FOTreeHandler)foInputHandler; > > foTreeHandler.addFOTreeListener(currentDocument); > > } > > </before> > > > > <after> > > if (foInputHandler instanceof FOTreeHandler) { > > FOTreeHandler foTreeHandler = > (FOTreeHandler)foInputHandler; > > foTreeHandler.removeFOTreeListener(currentDocument); > > } > > </after> > > > > Better yet, refactor both of the above code snippets into > methods that can > > be called more simply, since this code would now be used more than once. > > As methods of Document? Since the code is in Driver now, I was thinking Driver. However, it will work from Document also. You'll just need to use getDriver() to get to the foInputHandler. > > Just looking at what is left in render(), I don't quite follow > why it would > > ever *not* be used if parsing will take place. The only thing > left in there > > is parser.parse(), the above code that it is wrapped in, and the code to > > *not* parse based on the LayoutStrategy's wishes. Since the > parser itself > > can be passed as a parameter, it seems like anybody parsing > could/would use > > it. If you will describe the use case(s) a bit, I'll try to be > of more help. > > Use cases that are not using render? Most prominent use case is Cocoon > which build a SAX pipeline where FOP can be the end of that pipeline. So > Cocoon needs a ContentHandler. Cocoon will not be able to call the > render() method. Personally, I have never used FOP's render() method as > a FOP user. I've always worked with getContentHandler(). I guess the > Cocoon use-case should be enough to convince you that the > getContentHandler() is necessary. The only thing going on in render right now is parser.parse(). Based on your above answer to #1, Cocoon must be doing something like that internally??? And based on your answer immediately above, it absolutely cannot use render() to do that. Although I don't grasp why this should be true, taking it at face value, and assuming that we want FOP to layout this document, here are the options: 1. The equivalent of parser.parse() that exists in the embedded app (Cocoon) will need to be wrapped in the code that activates the FOTreeListener. The code in render() that checks to see whether the LayoutStrategy wants to build an FOTree or not probably needs to be included as well, and again, it should probably be extracted into a method, or included in the <before> method. (This was the code I recently added to accommodate alt-design so that it could create its own data structure instead of using FOTree). 2. The FOTreeListener concept can be abandoned. Simply restore to the original scheme, which had the FOTree start the layout process for the PageSequence as parsing was completed for it. I don't remember exactly where that is, but it is wherever the FOTreeEvent is being fired. Here are the costs that I can think of to this approach: a. Either LayoutStrategy needs to be abandoned, or the LayoutStrategy implementation needs to be made available to the method mentioned above that handles the end of a PageSequence. FONode.getFOTreeControl() can be used for the latter option. (FOTreeControl is the interface from FOTree to Document). b. FOTree independence needs to be abandoned. It was never totally achieved anyway, and AFAICT I am the only one that thought it was very important. Alternatively, an additional FOTree interface could be created to which LayoutStrategy should conform. > > Part of what is making this a bit ugly is that render() really > belongs in > > the Document class, but I don't think that can be done until FOP's API > > issues are resolved. > > Another top-priority todo item on my list that I haven't had time for, > yet. *sigh* Sorry, that was not meant as a dig at you. I have deliberately avoided recommending anything above, as 1) I don't have an interest in the outcome, and 2) I don't want to start any more fights. However, please let me know if I can help resolve this. And I'm sorry to be so dense on Cocoon -- I am familiar with its model at a user level, but must have a false model in my head about how it does its work. Also, if possible, please let me know what you decide. I am evaluating in-progress projects right now to determine which ones I should finish and which ones I should abandon as I exit the project. If LayoutStrategy survives reasonably intact, I am much inclined to try to complete the port of the pioneer LS. If not, then it would be unusable. Victor Mote