Finn Bock wrote:

> At the moment I can't find a way to either get hold of the assigned
> LayoutManagerLS instance or to set a new LayoutManagerLS. I assume that
> it is just a temporary issue as long as
> - the Document creation is hardwired in Driver
> - no accessor exists for currentDocument and
> - the LayoutManagerLS creation is also hardwired in Driver.

The LayoutManagerLS object is instantiated at line 584 of apps.Driver. I
guess I don't know enough about your workflow to give you a good answer
here. I thought from a previous post that you were modifying apps.Driver. If
so, then simply instantiate your subclass of AddLMVisitor right after that,
and use the accessor to set the value:

584a586,589
>             if (currentDocument.getLayoutStrategy() instanceof
LayoutManagerLS) {
>                 LayoutManagerLS lmls =
(LayoutManagerLS)currentDocument.getLayoutStrategy();
>                 lmls.setAddLMVisitor(new MyAddLMVisitor());
>             }

Until we get our API issues straightened out, you will probably need to
modify or subclass Driver to handle something like the above. In the
standard code, I could create an empty method at the location noted above,
and you could override that in your subclass. Would that help any? If not,
please provide more details about how you are instantiating FOP, and we'll
try to accommodate it.

> Or perhaps I have just overlooked the right spot to access
> setAddLMVisitor.
>
>  > Also I added
> > some accessor methods in AddLMVisitor that will give your
> subclass access to
> > the list objects that are there, as you will probably need them.
>
> Yes, I need some way to add the LM's, and the accessor is fine.

I also just made the instance variables protected instead of private, which
I should have done in the first place.

> > I tested it on my side by commenting out the method for "Block" in
> > AddLMVisitor, and creating a subclass that had only "Block" in
> it. I watched
> > it go through the debugger as expected & the output seemed
> fine. (That was
> > without any casting -- unless I am missing something, you
> should be able to
> > eliminate the cast in your code as well,
>
> I could be wrong, but I dont't think I can get by without the cast.
> Without a cast the invocation in my acceptVisitor is compiled to java
> byte code:
>
> invokevirtual <Method void serveVisitor(org.apache.fop.fo.FObjMixed)>
>
> and with a cast it turns into:
>
> invokevirtual <Method void serveVisitor(dk.innovasion.fop.TextField)>
>
> The difference is that the FOTreeVisitor interface does not know
> anything about my FObjMixed subclass called dk.innovasion.fop.TextField.
> This is compiled with jdk1.4, but I think all java compilers must behave
> like this.
> If you want to test this yourself, you should perhaps remove the
> serveVisitor(Block) method from both AddLMVisitor and from FOTreeVisitor.

You're right that my test was inadequate & that the cast is necessary. I
just committed a change to mitigate this:
1. converts FOTreeVisitor to an interface, which will allow you to extend
the interface & implement the extended interface in your extension of
AddLMVisitor. This way you can cast the visitor as an FOTreeVisitorExtension
instead of an AddLMVisitorExtension, which (to my mind anyway) keeps the
layout stuff out of the FO Tree logic. So conceptually, you are doing two
things: a) adding a new element into the FO Tree (extending the
FOTreeVisitor), b) doing something with that new element in layout
(extending AddLMVisitor).
2. converts the methods to unique names instead of overloading one method
name. I don't think this directly affects the issue at hand, other than
perhaps making the method selection a bit less obtuse.

> [finn]
>
>  > I'm not sure how a AddLMVisitor subclass would work if two different
>  > extensions are used in the same document, but that is not an issue in
>  > my use.
>
> [Victor]
>
>  > AFAIK, it should just be a matter of setting up a method in the
>  > subclass for each of the extensions. But maybe I am misunderstanding
>  > your question.
>
> I was think of the situation where two independently developed
> extensions both need to add their own serveXXX methods to the
> AddLMVisitor instance. Since there is only one AddMVisitor instance, my
> extension will exclude the use of all other 3rd party extensions. But
> this is not yet an actual issue for me.

OK, I see your point. Some possible workarounds:
1. Have one extension extend the AddLMVisitor extension of the other.
2. LMIter could be modified with some "instanceof" logic to handle one
extension or the other. Of course, then you have to be able to get a
modified version of LMIter.
3. I thought about adding a hook into the FO Tree build process that would
execute a method in some external class that conformed to an FO Tree
interface. This would allow "something" to be done outside of the FO Tree
build, but concurrently with the build itself. So, for this to work, the
logic (adding layout managers) would have to be doable as the node is being
added to the FO Tree, instead of as a separate step after the FO Tree is
built. Of course, this can actually be done now also (without any hook), but
not without getting layout code into the FO Tree.

This kind of opens the question of how much FOP's design should be
influenced by such issues, and I don't have a good answer. Since it is open
source, the possibility exists of getting the extension built into the
standard code. If it is proprietary code (and therefore can't be
contributed), then I have to question how badly we should contort FOP to
make it easy to do that. There certainly seems to be a finite limit to how
much can be done at a practical level.

Victor Mote

Reply via email to