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]

Reply via email to