Jeremias Maerki wrote (Sent: Saturday, November 08, 2003 8:28 AM)

> As you may have seen in the CVS messages I have moved most of the setup
> code that was in the render() method to the getContentHandler() method.
> This is necessary because not everyone uses the render() methods,
> sometimes you simply need to have a ContentHandler to send SAX events to.
> Some of our examples (and some of our basic test cases) use that
> approach.
>
> What is left to do is to enable the FOTreeListener for Document that is
> currently added only if the render() method is called. Providing the
> same functionality with getContentHandler() only means you're not in the
> Driver class anymore when endDocument() is called on the ContentHandler
> which makes it difficult to remove the FOTreeListener on the
> FOTreeHandler when processing is complete.
>
> If noone objects, if noone has a better idea and if noone fixes that
> ahead of me, I'm going to write a ProxyingDefaultHandler as a utility
> class that does nothing other than pass through all method calls to
> another DefaultHandler (in other words: the FOTreeBuilder). I'll then
> add an anonymous inner class derived from that ProxyingDefaultHandler in
> getContentHandler that listens to the endDocument() event and calls
> removeFOTreeListener on FOTreeHandler. Instead of the FOTreeBuilder that
> anonymous inner class will be returned by getContentHandler().

First, my apologies for being so slow to respond. I am trying to clean up
some of this old stuff that I had flagged for followup. I also looked in the
CVS history & source, and it looks like you have not finished this yet.

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
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
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.

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.

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.

Victor Mote

Reply via email to