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 [EMAIL PROTECTED]
From: "Nicola Ken Barozzi" <[EMAIL PROTECTED]>
> 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 [EMAIL PROTECTED]
- verba volant, scripta manent -
(discussions get forgotten, just code remains)
---------------------------------------------------------------------
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, email: [EMAIL PROTECTED]