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]