Re: PROPOSAL (round 2): Extensions to MDR XMI API

Martin Matula <[email protected]>
Newsgroups gmane.comp.java.netbeans.modules.mdr.devel
Message-ID <[email protected]>
Hi Holger,

Holger Krug wrote:
> Why then is their a method XMIReader.read(InputSource) ?

It is there for convenience. For the same reason I put 
write(OutputTarget) into the XMIWriter interface so that user of XMI 
interfaces will not need to know about SAX classes when working with it. 
Otherwise the user will not be able to use the XMI API without 
hardcoding use of a specific implementation of ContentHandler into their 
application. To be able to do that, users will either need to include 
the implementation of the ContentHandler in their module (this would 
result in having many copies of the same implementation accross 
different modules) or I can include the default implementation in MDR 
module - this would cause that it would be no longer enough for modules 
to depend only on mdrapi, they would also need to depend on the mdr 
module itself. Another possibility is to create a separate module 
containing just the implementation of ContentHandler, which is also not 
so cool.

> As I understand the usual design of XML interfaces it should be done
> this way:
> 
> /**
>  *  Instances of classes implementing this interfaces are supposed
>  *  to be used in the following way:
>  *  <pre>
>  *   XMLReader.parser = XMLReaderFactory.createXMLReader();
>  *   parser.setContentHandler(xmiReader);
>  *   parser.parse(inputSource); 
>  *
>  */
> public interface XMIReader extends ContentHandler, Cloneable {
>   ... additional interface methods but no read method ...
> }
> 
> Having the read(..) method in the interface gives a misleading hint to
> implementors that they are free to implement read(..) as they
> like. But if this would be the case a user would be forced to choose:
> Shall I use the instance of XMIReader I have at hand as ContentHandler
> (see the javadoc above) or directly via read(..). This is ugly, because
> the user has no clue what the difference is.  Hence I would recommend
> either to remove read (the preferred solution), or at least to
> document that read(..) is simply a convenience for the user and *must*
> be implemented in a way semantically equivalent to the code given in
> the Javadoc above.

I admit this is a problem. One solution could be to move the read method 
into XMIReaderFactory (read(InputSource, XMIReader)) and implement it 
there (because XMIReaderFactory is a class). I can even make it final 
there although I don't see a reason.
Although this would make the interfaces asymetric with XMIWriterFactory 
and XMIWriter.

> Why do you allow to define a collection of extents whereto to write ?
> Do you suppose that a XMIReader should write simultaneously to all
> those extents ? I yes, I think that should be documented in the interface.

I will change XMIReader to take only one extent. See below.


> Here I similarily do not understand why a ContentHandler is one of the
> parameters no the only one:
> 
> public interface XMIWriter {
>   .. additional parameters but no further write method ..
>   
>   /**
>    * To write to a stream or other kind of output target user
>    * can use code like:
>    *
>    * <pre>
>    * Writer writer = ... ;
>    * ContentHandler handler = new com.megginson.sax.XMLWriter(writer);
>    * xmiWriter.write(handler);
>    * </pre>
>    *
>    * <code>XMLWriter</code> is in the public domain and can be downloaded
>    * from <a href="http://www.megginson.com/Software/">here</a>.
>    */
>   public void write(ContentHandler handler);
> 
> }
> 
> Having written this I now understand that you need the document URI to
> be able to support the XMIReferenceProvider. OK, so why not simply
> allow the document URI as optional second parameter of write.(..).

OK. But as I said earlier, I would also like to have method that does 
not take ContentHandler, or have getDefaultContentHandler method somewhere.

>>- XMIHRefResolver.resolve now receives also a pointer to XMIReader. This 
>>is to make it possible for the resolver to clone the instance of 
>>XMIReader (this will make a new copy with preserved properties and 
>>extents) and read a new XMI file if necessary.
> 
> 
> Read the new XMI file into which extent(s) ?

Extents can be distinguished by their types, but it is true that now 
that we have XMIHRefResolver, it is enough to support only one extent 
for each XMIReader and XMIHRefResolver will control which extent goes 
where. This will also solve the problem when there are links between 
extents of the same type.
So I will change getExtents() method to setExtent(RefPackage).

> 
> Do circular references between XMI files pose problems ?
> 

Currently yes. We are working on a solution.

> If the XMIHRefResolver shall be able to open a new XMI file and if the
> URI of the new XMI file is given relatively to the original one, it
> must know the URI of the original XMI file. 

Yes, it gets it in systemId parameter.

> But the XMIReader may be
> used as ContentHandler and, as such, it does not in every case know
> about the URI, because XML parsers are not forced to call
> ContentHandler.setDocumentLocator(Locator). A solution would be to
> document, that references given by relative URI's may be resolved only
> if ContentHandler.setDocumentLocator(Locator) is called.

Yes, we will document it.

Martin
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.