You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-dev@xmlgraphics.apache.org by Victor Mote <vi...@outfitr.com> on 2003/12/20 15:17:52 UTC

RE: Setup code in Driver

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


RE: Setup code in Driver

Posted by Victor Mote <vi...@outfitr.com>.
Peter B. West wrote:

> You have as yet only Glen's opinion about your pioneer LS proposal.  It
> might be worthwhile to wait for others to express theirs.

I don't remember the technical rule for the mathematics of accepting
proposals, but with the size of our group, a -1 from anyone pretty much
kills it IMO. Right now, I see only 4 developers that might express an
opinion: Peter (West), Joerg, Jeremias, and Glen. AFAIR, Joerg has never
officially voted, but expressed only coolness to the LS idea in general, and
even less enthusiasm for the Pioneer LS. I interpreted Glen to vote -1. I do
not expect a +1 from you, because Pioneer LS is predicated on LS, and LS
would have to either be ditched or rendered useless to accommodate the
scheme that you insist upon. So the only unknown is Jeremias -- even if he
voted +1, that wouldn't be enough to carry the issue.

I'm not in love with the Pioneer LS either, but viewed it as a bridge
between the maintenance and trunk lines of development that would allow us
to restore the "release early and release often" principle. Ideally, instead
of splitting the lines of development, we would have factored the layout
logic out in a manner similar to what I have done on the trunk, then started
a new LayoutStrategy while leaving the existing one intact. Changes to
fonts, graphics, config, Avalonization, etc. would then be added in parallel
with changes to the new layout system, still allowing improvements to be
released, tested, fixed, used. The Pioneer LS (RIP) was an attempt to
retrofit us into that state again.

No, I can see that the idea, once coolly tolerated, has now been rejected.

> > It makes me realize again that maybe I was the one pulling
> against the flow.
> ...
>
> Having always pulled against the flow, I feel qualified to comment on
> this.  The Apache projects and subprojects like to describe themselves
> as communities.  I don't see that as meaning a gang, where everyone
> wears the same "colours" and effectively surrenders identity to the
> collective.  At the other end would be a collection of developers
> amongst whom no agreement on direction could be reached, and who each
> pursued a separate line of development.  This would render any
> productive collaboration impossible.  I think Apache communities
> necessarily fall somewhere in between these extremes.
>
> Obviously, I believe there is room for serious individual differences in
> approach within FOP, and by extension, within other Apache communities,
> although this will vary with the maturity of both the codebase and the
> Recommendation(s) of which it is an implementation.  A mature, widely
> used and comprehensive implementation of a stable Recommendation seems
> to offer little room for alternative approaches.
>
> FOP is not a mature, stable and comprehensive implementation of XSL 1.0,
> and XSL 1.1 is out in Working Draft, albeit without radical changes.  I
> don't think it is surprising that there are serious differences of
> approach.  I have explained my own motivations on a number of occasions.
>   The bottom line, though, is that I believe in the approach I am
> taking, and I believe that I, or rather, the design itself, will
> eventually persuade others.

The *technical* issue in play here is whether FOP will be monolithic or
modularized. (There is an even bigger issue about how the Open Source
development model should work, but I have already said 'nuff on that
subject). For the record, I have little doubt that your monolithic approach
can be made to work. The question is, supposing that a modular approach can
be made to work, why not gain the benefits that come with modularization?
And why not, until all are persuaded to the same view, accommodate both?
Your layout scheme can be accommodated within the sphere of LS. However,
AFAICT, no patient LS scheme can be accommodated within your scheme for
layout. So, my objection to your proposal is not that mine is better than
yours, but that you insist that the trial never be had, that we cut off
options for no apparent good reason.

> This last part is easier said than done, for very simple reasons.  I may
> have mentioned before that only I, for most of the time, and Jeremias
> for part of the time, have been able to work full-time on FOP.  Everyone
> else has a job around which he or she has to work.  Given the severe
> time limits, and the difficulty of coming to terms with 1) the
> Recommendation, 2) the maintenance branch, and 3) HEAD, it is not
> surprising that faced with a major change of design direction, most
> people just don't have the time or energy to try to come to terms with it.
>
> That doesn't make alternative approaches worthless.  Alt.design's
> property handling is now bearing some fruit in HEAD, of which I am very
> glad.  That it took so long for this to happen is unfortunate but
> understandable.
>
> The bottom line, it seems to me, is that if you believe in what you are
> doing, go ahead and do it.  The main reason I got to be a committer is
> that Nicola Ken Barozzi asked why my code was being kept on my ISP.  He
> said that anyone had a right to fork the code, or words to that effect,
> IIRC.  It's a lonely path until you do manage to persuade others, but if
> you believe in it, back your judgement.

Well, I don't mean to give the impression that I don't believe in what I am
doing, but merely that I have been unsuccessful in my efforts to persuade
others. There is a PhD on fop-user who has more than once suggested that FOP
needs to be rewritten in Ada. Maybe he is right, but I don't think anyone
seriously thinks that we should make him a committer so that he can start
into that project, either on the trunk or a branch. The Java language, at
least for now, is a settled issue. The issue of monolithic vs. modularized,
while orthogonal to the language issue, is of no less magnitude. I thought
that the idea of accommodating patient processing through modularization was
a settled issue as well. I see now that it ain't and probably never will be.

So, I believe in what I am doing, but don't see a cost-effective way, and
probably no way at all, to get it done within the FOP project. I don't see
any need to drag those along who don't want to come. As I said in a previous
posting, if we're going to go in different directions, the "next best thing"
is to part in peace and work separately instead of against each other.
Whether that means forking the code, starting from scratch, throwing in with
some other project, etc. I don't know. That decision is immaterial to you.
But since you seemed to issue a challenge on the matter, I wanted you to
know that I do indeed believe in what I am doing.

Victor Mote


Re: Setup code in Driver

Posted by "Peter B. West" <pb...@powerup.com.au>.
Victor Mote wrote:
> Glen Mazza wrote:
> 
> 
>>--- Victor Mote <vi...@outfitr.com> wrote:

...
>>
>>
>>You've mentioned before, I believe, there was some
>>things you wished to do to improve the fonts.  That
>>may be good--because most of us have not researched
>>them.
> 
> 
> The font work has to get thrown away. It is useless without configuration,
> and there is no way I'm going to try to figure out what the team wants on
> that issue. And actually it is pretty useless without a working layout
> system. Jeremias knows at least as much about fonts as I do, and can
> probably make faster progress with me inactive.
> 
> 
>>>If LayoutStrategy
>>>survives reasonably intact, I am much inclined to
>>>try to complete the port
>>>of the pioneer LS.
>>
>>I'd rather you not.  I don't want to have to maintain
>>the 0.20.x layout strategy in addition to the 1.0
>>strategy in 1.0.  The committers and contributors
>>(Simon and Chris, in particular) are happy working on
>>the improving 1.0 layout and wish to remain with it.
>>
>>Recent patches (hyphenation, borders) to 1.0 LS have
>>made 0.20.x even more behind.  Also, the 1.0 Area Tree
>>and Renderers are incompatible with 0.20.x LS, I don't
>>want their architectures changed in order to
>>accomodate it.
>>
>>Those who wish to use the 0.20.x layout strategy can
>>continue to run 0.20.x.
>>
>>Let the decision to bring in that LS be with the ones
>>who will have to maintain it.  As for me, getting one
>>LS right is more than enough work.
> 
> 
> For the sake of brevity and peace, I will ignore the factual and analytical
> errors here, and simply say "Thanks! That certainly makes my life easier."

You have as yet only Glen's opinion about your pioneer LS proposal.  It 
might be worthwhile to wait for others to express theirs.

> It makes me realize again that maybe I was the one pulling against the flow.
...

Having always pulled against the flow, I feel qualified to comment on 
this.  The Apache projects and subprojects like to describe themselves 
as communities.  I don't see that as meaning a gang, where everyone 
wears the same "colours" and effectively surrenders identity to the 
collective.  At the other end would be a collection of developers 
amongst whom no agreement on direction could be reached, and who each 
pursued a separate line of development.  This would render any 
productive collaboration impossible.  I think Apache communities 
necessarily fall somewhere in between these extremes.

Obviously, I believe there is room for serious individual differences in 
approach within FOP, and by extension, within other Apache communities, 
although this will vary with the maturity of both the codebase and the 
Recommendation(s) of which it is an implementation.  A mature, widely 
used and comprehensive implementation of a stable Recommendation seems 
to offer little room for alternative approaches.

FOP is not a mature, stable and comprehensive implementation of XSL 1.0, 
and XSL 1.1 is out in Working Draft, albeit without radical changes.  I 
don't think it is surprising that there are serious differences of 
approach.  I have explained my own motivations on a number of occasions. 
  The bottom line, though, is that I believe in the approach I am 
taking, and I believe that I, or rather, the design itself, will 
eventually persuade others.

This last part is easier said than done, for very simple reasons.  I may 
have mentioned before that only I, for most of the time, and Jeremias 
for part of the time, have been able to work full-time on FOP.  Everyone 
else has a job around which he or she has to work.  Given the severe 
time limits, and the difficulty of coming to terms with 1) the 
Recommendation, 2) the maintenance branch, and 3) HEAD, it is not 
surprising that faced with a major change of design direction, most 
people just don't have the time or energy to try to come to terms with it.

That doesn't make alternative approaches worthless.  Alt.design's 
property handling is now bearing some fruit in HEAD, of which I am very 
glad.  That it took so long for this to happen is unfortunate but 
understandable.

The bottom line, it seems to me, is that if you believe in what you are 
doing, go ahead and do it.  The main reason I got to be a committer is 
that Nicola Ken Barozzi asked why my code was being kept on my ISP.  He 
said that anyone had a right to fork the code, or words to that effect, 
IIRC.  It's a lonely path until you do manage to persuade others, but if 
you believe in it, back your judgement.

> 
> Perhaps, in light of this, it may be worthwhile to abandon LayoutStrategy
> entirely. That would solve Jeremias's problem that started this thread.
...

Peter
-- 
Peter B. West <http://www.powerup.com.au/~pbwest/resume.html>


RE: Setup code in Driver

Posted by Victor Mote <vi...@outfitr.com>.
Glen Mazza wrote:

> --- Victor Mote <vi...@outfitr.com> wrote:
> > 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.
>
> You've mentioned before, I believe, there was some
> things you wished to do to improve the fonts.  That
> may be good--because most of us have not researched
> them.

The font work has to get thrown away. It is useless without configuration,
and there is no way I'm going to try to figure out what the team wants on
that issue. And actually it is pretty useless without a working layout
system. Jeremias knows at least as much about fonts as I do, and can
probably make faster progress with me inactive.

> > If LayoutStrategy
> > survives reasonably intact, I am much inclined to
> > try to complete the port
> > of the pioneer LS.
>
> I'd rather you not.  I don't want to have to maintain
> the 0.20.x layout strategy in addition to the 1.0
> strategy in 1.0.  The committers and contributors
> (Simon and Chris, in particular) are happy working on
> the improving 1.0 layout and wish to remain with it.
>
> Recent patches (hyphenation, borders) to 1.0 LS have
> made 0.20.x even more behind.  Also, the 1.0 Area Tree
> and Renderers are incompatible with 0.20.x LS, I don't
> want their architectures changed in order to
> accomodate it.
>
> Those who wish to use the 0.20.x layout strategy can
> continue to run 0.20.x.
>
> Let the decision to bring in that LS be with the ones
> who will have to maintain it.  As for me, getting one
> LS right is more than enough work.

For the sake of brevity and peace, I will ignore the factual and analytical
errors here, and simply say "Thanks! That certainly makes my life easier."
It makes me realize again that maybe I was the one pulling against the flow.
My apologies to all, especially Peter.

Perhaps, in light of this, it may be worthwhile to abandon LayoutStrategy
entirely. That would solve Jeremias's problem that started this thread.

That actually leaves only one piece of unfinished business on my part -- the
static field lastFOTextProcessed in fo.FOText. This is used for
text-transform. It has been my intention to make that an instance variable
in PageSequence. However, there are some design-related issues that need to
be resolved before that should be done, and I intend to stay out of that. So
I mention it only to make sure that you know that I know that it shouldn't
be as it is, but that I don't see a ready solution. If multi-threading is
more important than text-transform, and you can't get the field converted to
an instance variable, just comment out the text-transform code.

Best wishes to all.

Victor Mote


RE: Setup code in Driver

Posted by Glen Mazza <gr...@yahoo.com>.
--- Victor Mote <vi...@outfitr.com> wrote:
> 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.

You've mentioned before, I believe, there was some
things you wished to do to improve the fonts.  That
may be good--because most of us have not researched
them.

> If LayoutStrategy
> survives reasonably intact, I am much inclined to
> try to complete the port
> of the pioneer LS. 

I'd rather you not.  I don't want to have to maintain
the 0.20.x layout strategy in addition to the 1.0
strategy in 1.0.  The committers and contributors
(Simon and Chris, in particular) are happy working on
the improving 1.0 layout and wish to remain with it.

Recent patches (hyphenation, borders) to 1.0 LS have
made 0.20.x even more behind.  Also, the 1.0 Area Tree
and Renderers are incompatible with 0.20.x LS, I don't
want their architectures changed in order to
accomodate it.

Those who wish to use the 0.20.x layout strategy can
continue to run 0.20.x.

Let the decision to bring in that LS be with the ones
who will have to maintain it.  As for me, getting one
LS right is more than enough work.

Glen


__________________________________
Do you Yahoo!?
New Yahoo! Photos - easier uploading and sharing.
http://photos.yahoo.com/

RE: Setup code in Driver

Posted by Victor Mote <vi...@outfitr.com>.
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


Re: Setup code in Driver

Posted by Jeremias Maerki <de...@greenmail.ch>.
On 20.12.2003 15:17:52 Victor Mote wrote:
> 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.

Right. I still got 622 unread mails in my fop-dev folder. :-) So I guess
I simply forgot. Available time also influenced this.

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

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

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

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

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

Jeremias Maerki