Re: structuring pull parsing code and using serializer [Re: [xmlpull-user] Java <-> XML using XMLPull]

Aleksander Slominski <[email protected]> Sat, 01 Mar 2003 13:46:52 -0500
Newsgroups gmane.text.xml.xmlpull.devel
Message-ID <[email protected]>
Naresh Bhatia wrote:

> I have now worked extensively with XMLPull API and your XmlPullWrapper 
> - I love this stuff!

hi Naresh,

i am very happy to hear that :-)

> I have tried several other approaches ranging from SAX all the way to 
> the latest data binding packages, but they all fell short of my 
> expectations. Some could not get the job done (especially when it came 
> to namespaces), others just did not present elegant solutions (I am 
> very picky about my designs and code :->). Anyway I am really 
> impressed by the elegance of the XMLPull API and I have decided to use 
> it for my project.
>  
> In an effort to make the API even more easier to use, I have the 
> following suggestions. They are mainly directed at XmlPullWrapper and 
> your AddressBook example. I have refactored the code a little to 
> demonstrate how this approach could be used on larger projects. My 
> changes are attached along with an Ant build file.
>  
> - I have refactored the AddressBook example into 4 classes. 
> MyAddressBook.java now contains only the main( ) method. The read 
> methods have been refactored into the AddressBookReader class and the 
> write methods have been moved to the AddressBookWriter class. The 
> Person class is now in its own seperate file as this is more realistic 
> on a real project.

that looks reasonable and i would like to make it into a real sample. 
please take a look on this:
http://www.extreme.indiana.edu/~aslom/xml/databinding/jaxme-xmlpull/

>  
> - AddressBookReader inherits from XmlPullWrapper. This gives me access 
> to the parser in all methods - the parser is no longer passed around 
> in method signatures. In addition, I do not have to "create" an 
> XmlPullWrapper object whenever I need to use it - I am the 
> XmlPullWrapper! This also resulted in more frequent use of the 
> XmlPullWrapper methods as they are more accessible!

definitely that is one approach that can be taken and makes code to read 
address book very easy (just pass Reader)/

however i would like to be able to pass parser instance to address book 
reader class as it allows for greater flexibility and makes possible to 
read multiple address books from one  XML input as parser can be opened 
once with XML input and then passed to any part of code that needs it 
(for example when address book XML is embedded in XML document i can 
scan for addreebook tag and then pass parser instance to AddressBookReader)

>  
> - I added a class called XmlSerializerWrapper. The idea is similar to 
> XmlPullWrapper. This class holds convenience methods for 
> XmlSerializer. Currently I have only one method in this class called 
> writeSimpleElement( ), which allows me to write simple elements such 
> as <username>johndoe</username> in one call.

that is very good idea! defintely will add it.

> - Added a method to XmlPullWrapper called getRequiredElementText( ). 
> This method allows you to read simple elements such as 
> <username>johndoe</username> in one call.

OK will add it.

>  
> - Fixed a minor bug in XmlPullWrapper.nextEndTag() - it was going to 
> the next start tag insted of the next end tag - probably a cut&paste 
> error from nextStartTag()  :-)

OK will fix it.

> - I would recommend that XmlPullWrapper and XmlSerializerWrapper be 
> supplied along with the XMLPull API - may be not as part of the API 
> but atleast as a supported utilities. This will encourage people to 
> use "best practices" and the wrappers will be thoroughly tested. In 
> addition, there will be only one standard version of the wrappers 
> instead of Alek's version and Naresh's version :-). Of course, people 
> are free to extend these utilities as they feel fit, but the baseline 
> is always the same.

i agree - we need utilities and it is good idea to keep them together in 
one place. we have now place in XmlPull API CVS repository for such 
additions (that are called addons), see:

http://www.xmlpull.org/v1/doc/addons.html
http://www.xmlpull.org/viewcvs/~checkout~/xmlpull-api-v1/addons/

after consulting with Stefan i was thinking about having XmlPullUtil 
class with only static methods and then have interface that extends 
XmlPullParser interface by adding useful methods (such as nextEndTag) 
and  there is implementation wrapper that uses JDK 1.3 dynamic proxies 
<http://java.sun.com/j2se/1.3/docs/guide/reflection/proxy.html> to 
automatically intercept calls and redirect them to parser impl or 
XMLUtil methods. that would work as follow:

interface XmlPullWrapper extends XmlPullParser {
   void nextEndTag(...)
}


the same for XmlSerializerWrapper, and then to actually create instance 
of wrapper:

XmlPullWrapper pw = XmlPullDynamicProxy.newPullWrapper();   //default to 
wrap parser created using default parser factory

or with more control:

// explicit wrapping that allows to wrap any instance of XmlPullParser
XmlPullParser pp = factory.newPullParser();
//...
XmlPullWrapper pw = XmlPullDynamicProxy.wrapparser);  

then you can use wrapper exactly the same as XmlPullParser (as it 
extends XmlPullParser) *and * use additional methods so this code would 
work:

pw.setInput()
pw.next();
pw.nextEndTag()

this i think makes very nice use of built-in into XmlPull API 
flexibility as it is based on factory and interfaces model so can be 
easily extended and XmlPullDynamicProxy is factory where XmlPullWrapper  
is extensions.

if generalized enough this should allow to compose multiple extensions 
to XmlPullParser dynamically as in this case we have example of 
interceptor based design (some people call it "lightweight" AOP)

one thing to consider  is performance hit of using dynamic proxy and i 
plan to measure it comparing using dynamic proxy and 
XmlPullutil/XmlPullParser directly.

anyway those are my currentideas and i look forward to hear your comments.

> Here's the new main( ) function in MyAddressBook.java after the 
> refinements mentioned above. It is much more concise.
>  
>     public static void main (String args[])
>     throws XmlPullParserException, IOException {
>        
>         System.out.println("reading address book from XML");
>         AddressBookReader addressBookReader =
>             new AddressBookReader(new StringReader(SAMPLE_XML));

>
>         Vector addressBook = addressBookReader.readAddressBook();
>  
>         //add new entry to address book
>         addressBook.add(new Person("Foo Bar", "Silicon Street"));
>  
>         System.out.println("serializing address book to XML");
>         StringWriter sw = new StringWriter();
>         AddressBookWriter addressBookWriter = new AddressBookWriter(sw);
>         addressBookWriter.writeAddressBook(addressBook);

i would keep AddressBookReader/Writer stateless so they can be reused so 
it should allow setting input not only when it is created with constructor

>         System.out.println("Addressbook as XML:\n"+ sw);
>     }
> I would love to get your feedback on this stuff!

i plan to drop Util and Wrapper classes into addons soon and will add 
your modifications.

thanks,

alek

-- 
"Mr. Pauli, we in the audience are all agreed that your theory is crazy. 
What divides us is whether it is crazy enough to be true." Niels H. D. Bohr



------------------------ Yahoo! Groups Sponsor ---------------------~-->
Get 128 Bit SSL Encryption!
http://us.click.yahoo.com/LIgTpC/vN2EAA/xGHJAA/2U_rlB/TM
---------------------------------------------------------------------~->

To unsubscribe from this group, send an email to:
[email protected]

 

Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/