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 Nicola Ken Barozzi <ni...@apache.org> on 2002/06/06 19:07:58 UTC
[Morphos] Java data morphing package - second stab
Ok, here is the second stab at it :-)
I'm still crossposting now to other projects that have shown interest.
I have gotten many suggestions privately, so this will contain them +
clarifications, and a concrete example.
This discussion properly resides on the Jakarta Commons mailing list.
To subscribe, send an empty mail to commons-dev-subscribe@jakarta.apache.org
From: "Nicola Ken Barozzi" <ni...@apache.org>
> What is Morphos?
> -----------------------------
> Morphos will be a Java Api and implementation for transforming data, in
any
> form it may be: xml, streams, objects.
>
> It focuses on the API and framework, and demands implementation to other
> projects-modules wherever possible.
>
>
> Why Morphos?
> -----------------------------
> Morphos starts from a need around a community of developers, with an
initial
> charter committed in Jakarta Commons Sandbox.
[...]
> What does it do?
> -----------------------------
> Morphos should simply do:
>
> data --> morphos ---> data
>
> Data can be:
> - stream
> - events
> - objects
>
> I don't see other basic generic "data" types, since files and such can
> become streams and viceversa without any format or form conversion.
> I want a *very* simple api, with no duplicated methods.
> IE having get(Stream) and get(File) is not necessary IMO, since they do
the
> same thing.
> The main API must be very simple. We can always add helper classes.
[...]
Ok, but in Concrete?
------------------------------
>
> Here is the proposed API, all in package org.apache.commons.morphos:
>
> /**
> * The interface that is implemented by classes that morph.
> * It uses two params and not a return value to make it usable with
> * event based Objects (contenthandlers).
> * Parameters are key pairs, used to configure the Morpher.
> * Events in the Morpher are notified by registering a listener.
> */
> public interface Morpher {
>
> void morph(Object input, Object output) throws MorphException.
> IOException;
>
> void addParameter(String paramName, String paramValue);
> String getParameter(String paramName);
> void remove Parameter(String paramName);
> String[] getParameterNames();
> String[] getParameterValues();
>
> void addNotificationListener(NotificationListener nl);
> void removeNotificationListener(NotificationListener nl);
> void clearNotificationListeners();
>
> }
/**
* The interface that is implemented by classes that morph.
* It uses two params and not a return value to make it usable with
* event based Objects (contenthandlers).
* Events in the Morpher are notified by registering a listener.
* [new] parameters are managed with beans get/set methods
* *none* are mandatory
*/
public interface Morpher {
void morph(Object input, Object output) throws MorphException.
IOException;
void addNotificationListener(NotificationListener nl);
void removeNotificationListener(NotificationListener nl);
void clearNotificationListeners();
}
[Clarification]
Why not
Object morph(Object input) throws MorphException, IOException;
?
Because if the output object is a SAX handler, the morphing doesn't take
place, and this is not evident.
Any other pros-cons?
[Clarification 2]
Why use Object as input and output?
Why not use different types?
Genericity.
See the below comments after the Factory/Manager.
> /**
> * A Morpher made out of a sequence of morphers.
> */
>
> public interface MorpherPipeline extends Morpher {
>
> void addStage(Morpher nextMorpher);
>
> }
This remains.
>
> /**
> * The Factory for Morphers.
> * There is a getDefaultFactory method for easy use.
> * Used in frameworks it's better not to use it and rely on
> * services that give the proper MorpherFactory.
> */
> public abstract MorpherFactory {
>
> Morpher getMorpher(DataType inputType, DataType outputType);
> Morpher getMorpher(name);
>
> Morpher getPreparedMorpher(DataType inputType, DataType outputType);
> Morpher getPreparedMorpher(name);
>
> static MorpherFactory getDefaultFactory();
> }
/**
* The Morphers' manager.
* There is a getDefaultFactory method for easy use.
* Used in frameworks it's better not to use it and rely on
* services that give the proper MorpherFactory.
*/
public interface MorpherManager {
Morpher getMorpher(DataType inputType, DataType outputType);
Morpher getMorpher(name);
Morpher getPreparedMorpher(DataType inputType, DataType outputType);
Morpher getPreparedMorpher(name);
}
I've removed the static method, and made it an interface.
It will be the MorpherManager implementation that can use this pattern.
Why not *Factory?
Because it does more than just create them.
[Clarification 2]
Why is a Manager needed?
Because (see clarification 1) any Morpher instance is supposed to be an
implementation that is guaranteed to work with a determined kind of Objects
(a subset); this enforcement is done by the Manager.
> /**
> * Describes what the format of the data is.
> * It consists of a mimetype (format) and a dataForm (representation).
> * For example a gif image file and a jped image file have a different
> mimetype but same dataform (file).
> * An SVG file and an SVG DOM in memory have same mimetype but different
> dataform.
> */
> public interface DataType {
>
> void setMimeType(String mimetype);
> void setDataForm(String format);
>
> String getMimeType();
> String getDataForm();
>
> }
This becomes:
/**
* Describes what the format of the data is.
* It consists of a mimetype (format) and a dataForm (representation).
* For example a gif image file and a jped image file have a different
mimetype but same dataform (file).
* An SVG file and an SVG DOM in memory have same mimetype but different
dataform.
*/
public class DataType {
....
public DataType (String mimetype, String format) {
...
}
public DataType () {
...
}
void setMimeType(String mimetype){...};
void setDataForm(String format){...};
String getMimeType(){...};
String getDataForm(){...};
}
[Example]
/* Create the Manager that gives me the morphers */
MorpherManager mmanager = new SimpleMorpherManager("mmanager-conf.xml");
/* Get a jaxp Morpher by name */
Morpher jaxpmorpher = mmanager.getMorpher("jaxp");
jaxpmorpher.setStylesheet("transform.xml");
/* Get a Morpher that serializes an XML dom to a stream */
Morpher streammorpher =
mmanager.getMorpher(
new DataType("text/xml", "object/dom"),
new DataType("text/xml", "stream/unix")
);
Chain the two:
MorpherPipeline mpipeline = new SimpleMorpherPipeline();
mpipeline.addStage(jaxpmorpher );
mpipeline.addStage(streammorpher );
try{
mpipeline.morph(myDomObject, outputstream);
}
catch(IMorphException ioe){
.....}
catch(IOException ioe){
.....}
--
Nicola Ken Barozzi nicolaken@apache.org
- verba volant, scripta manent -
(discussions get forgotten, just code remains)
---------------------------------------------------------------------
---------------------------------------------------------------------
To unsubscribe, e-mail: fop-dev-unsubscribe@xml.apache.org
For additional commands, email: fop-dev-help@xml.apache.org
Re: [Morphos] Java data morphing package - second stab
Posted by Nicola Ken Barozzi <ni...@apache.org>.
From: "Stephen Colebourne" <sc...@eurobell.co.uk>
> > * It uses two params and not a return value to make it usable with
> > * event based Objects (contenthandlers).
> > * Events in the Morpher are notified by registering a listener.
> > * [new] parameters are managed with beans get/set methods
> > * *none* are mandatory
> > */
> > public interface Morpher {
> > void morph(Object input, Object output) throws MorphException.
> > [Clarification]
> > Why not
> > Object morph(Object input) throws MorphException, IOException;
> > ?
> > Because if the output object is a SAX handler, the morphing doesn't take
> > place, and this is not evident.
> > Any other pros-cons?
>
> The problem with the two object input approach is that it precludes a
simple
> type convertor being written using this architecture. A type convertor
> typically takes in an immutable object and returns an imutable object
> (String/Integer etc.)
Hmmm...
Integer input = new Integer(1);
String output = null;
[...]
mymorpher.morph(input , output);
If the morpher does
output=input.toString();
wouldn't it work?
> Object morph(Object input) does allow a String to Integer convertor, but
> is obviously a second interface, potentially providing confusion.
Yes, we need a single way, I agree.
> Given this, you may want to refine the definition of what can or can't be
> morphed (ie. to exclude immutable outputs).
Thinking of the immutable objects, what is more confusing:
Integer input = new Integer(1);
String output = "immutable string that will be replaced";
[...]
mymorpher.morph(input , output);
or
Contenthandler input = ...
Contenthandler output = ...
output = mymorpher.morph(input);
and still need to trigger the morphing?
IMO you are right, immutable objects make the morph(input, output) method a
bit ridiculous.
I think you've convinced me, what do others think?
--
Nicola Ken Barozzi nicolaken@apache.org
- verba volant, scripta manent -
(discussions get forgotten, just code remains)
---------------------------------------------------------------------
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>
Re: [Morphos] Java data morphing package - second stab
Posted by Stephen Colebourne <sc...@eurobell.co.uk>.
> * It uses two params and not a return value to make it usable with
> * event based Objects (contenthandlers).
> * Events in the Morpher are notified by registering a listener.
> * [new] parameters are managed with beans get/set methods
> * *none* are mandatory
> */
> public interface Morpher {
> void morph(Object input, Object output) throws MorphException.
> [Clarification]
> Why not
> Object morph(Object input) throws MorphException, IOException;
> ?
> Because if the output object is a SAX handler, the morphing doesn't take
> place, and this is not evident.
> Any other pros-cons?
The problem with the two object input approach is that it precludes a simple
type convertor being written using this architecture. A type convertor
typically takes in an immutable object and returns an imutable object
(String/Integer etc.)
Object morph(Object input) does allow a String to Integer convertor, but
is obviously a second interface, potentially providing confusion.
Given this, you may want to refine the definition of what can or can't be
morphed (ie. to exclude immutable outputs).
Stephen
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>