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>