From: "Joerg Pietschmann" <[EMAIL PROTECTED]>
> Jeremias Maerki <[EMAIL PROTECTED]> wrote:
> > By the way: What's the current agreement whether to use Avalon or not? I
> > mean, we're already using LogKit (which is cool).
>
> No, it's not cool unless done properly. I don't think users
> who want only pure FO processing should be forced to use
> another heavyweigth framework and logkit.
I've used Avalon framework in many projects, and IMHO it's not heavyweight.
Logkit is *very* light and fast, and I would humbly suggest to take a look
at the framework/logging classes that shields logging from implementation.
In this way any logger can be plugged in without changing code.
> I rather imagine something like the following layered
> architecture:
>
> 1. FOP core. Processes XML, either as SAX event stream by
> supplying a content handler or by utilising the interface
> javax.xml.transform.Source, into a renderer specific result
> (probably a java.io.OutputStream, could even apply to a voice
> renderer :-)
> Do not rely on any hardcoded external files. Get configuration
> via a java.util.Properties object or other explicit methods.
In my experience, using the avalon framework Configuration adds a *lot* of
flexibility and is very easy to use. Now it also has writing capability.
Using XML, it has a hierarchy.
> Use a FOP owned interface like javax.transform.ErrorListener for
> reporting errors and such, or perhaps even reuse ErrorListener
> (somewhat odd, though).
In error reporting there are wo levels: user and developer.
The user gets notified by ErrorListener, the developer by logging. The user
could also want to put a logger as errorListener. Anyway avalon frameworl
logging shields from the logging implementation.
> Use a javax.transform.URIResolver or a similar FOP owned
> interface for resolving URIs (external graphics source, user
> font file...).
There is already a tried and tested Avalon Component for this.
> 2. Intermediate layer with a class combining a transformer and
> a FO processor instance (optional)
> 3. Class for embedding into the framework. Provides implementations
> for the URIResolver and the ErrorListener, the latter redirecting
> to the logging toolkit. May read external, user writable configuration
> files. Uses framework for passing options and other parametrisations
> from the outside (command line, servlet request, applet parameter...)
There is already a CLI util class in Avalon.
> It may be an idea to use the factory pattern like javax.transform:
>
> abstract classe FOProcessorFactory {
> // get a new factory. factory may cache default properties for
> // processors, fonts,...
> static FOProcessorFactory newInstance();
> // create a new processor. a FOProcessor instance is only good
> // for one run, like a Transformer
> abstract FOProcessor newFOProcessor();
> abstract FOProcessor newFOProcessor();
There are ComponentManagers in Avalon, that handle lifecycle automatically.
> // inherited to generated processors
> abstract void setErrorListener(ErrorListener);
> // inherited to generated processors. use also for example for
> // loading default fonts while creating a new processor instance
> abstract void setURIResolver(URIResolver);
> // set attributes, like font file URIs or even compiled font
> // classes
> abstract void setAttribute(String name, Object value)
> // perhaps a few shortcuts for transformations
> abstract void setTransformation(Source xsl);
> abstract void setTransformation(Templates);
> // various get methods omitted :-)
> }
>
> abstract class FOProcessor {
> abstract void setRenderer();
> abstract void render(Source,OutputStream);
>
> abstract void setErrorListener(ErrorListener);
> abstract void setURIResolver(URIResolver);
> abstract void setAttribute(String name, Object value)
> // shortcuts
> abstract void setTransformation(Source xsl);
> abstract void setTransformation(Templates);
> // extra shortcut (makes no sense for the factory)
> abstract void setTransformation(Transformer);
> }
This is basically a definition of an interface of a FOProcessor, the main
avalon-style Component for FOP.
Using Excalibur ComponentManager, you just need to add a reference in the
xml configuration and it gets automatically setup, configured, and managed.
> If a transformation is set, the Source in render() is the original
> XML piped through the transformation. I'm not sure whether get/set/
> clearParameter for the transformation should be added to FOProcessor,
> fortunately, no output properties are necessary.
If it implements the Parametrizable interface of Avalon, the Parameters get
set automatically by Excalibur.
Same with Configurable.
IMHO, Avalon *really* helps in making a clean class structure and
Componentization.
I am finding it a bit difficult in getting the grasp of FOP specific stuff,
but understand something of Avalon, so I'm very willing to help in this
regard.
Cheers!
Ken
-