Xapi-J: an architectural detail (long)
John Tigue
john at datachannel.com
Sun Aug 3 06:21:34 BST 1997
This note explains some of the internal implementation details of Xapi-J
compliant processors. If all you want to do is use an Xapi-J processor,
you do not need to concern yourself with these details. This note is
intended for people who are actually writing Xapi-J processors.
One of the nice features of Java is the clear distinction between
inheritance and interfaces. Xapi-J tries to leverage Java interfaces to
provide
processor users a simple object model and processor implementors wide
latitude
in regards to the processor internals..
Folks don't really have a problem grasping the XML object model:
To get a new XML processor object instance:
xml.XMLProcessor xmler = new xml.XMLProcessor();
To have a processor read a document:
xml.IDocument aDocument = xmler.readXML( someInfoSource );
To get the root of a document:
xml.IElement anElement = aDocument.getRoot();
To get an element's attributes:
java.util.Enumeration someAttributes = anElement.getAttributes();
That's easy to understand. It is a very simple object model
which can be mapped onto many of the current XML processors without
requiring major rewrites.
The greatest confusion centers around the mechanism used to hide the
specifics of the underlying implementation of the XML processor. This is
the only part of Xapi-J which actually involves real classes as opposed
to simply interfaces. Xapi-J does not contain an XML processor, it
simply says what one could look like. It is up to others to actually
supply the working code which is accessed through the Xapi-J interfaces.
One of the goals of Xapi-J is to create an architecture which (although
powerful and flexible) makes simple things simple. Navigating an XML
document object should be simple and as can be seen from the above code
fragments, it is. And getting an XML processor should be simple. That it
is. If a JVM comes with an installed XML processor, in the interests of
making things easy for developers, that processor should be used by
default. So a developer could simple do a "new xml.XMLProcessor();" and
expect that an XMLProcessor will be instantiated and usable. So if, say,
Microsoft wished to package their JVM with an XMLProcessor, they could
tweek the default constructor for xml.XMLProcessor to where it would
instantiate a com.ms.xml.Parser by default.
(I have tested that Xapi-J can be implemented on top of msxml. I have
the code on my hard drive. If anyone is interested drop me an email and
I'll give you the classes. With this interface adaptor, a developer
could write Java applets which save some download time by using the MS
parser which will be on the IE4 client and only downloading the light
weight adaptor. I would not suggest this. As I have mentioned in an
earlier posting I feel that the msxml object model is serious flawed.
Correcting for it required some non-optimal efficiency code.)
A good architecture makes simple things simple but it doesn't limit a
developer. Say a developer wanted to use an XML processor which was
tweeked for parsing MathML documents (call it MathMLProcessor). Perhaps
a MathMLProcessor could only understand that particular XML application
but via this specialization was able to obtain greater performance than
a general purpose XML processor. It would be great if the developer
could specify that when a "new xml.XMLProcessor()" call occurs a
MathMLProcessor should be instantiated. Xapi-J allows for this via the
following method in the xml.XMLProcessor class:
public static synchronized void setIXMLProcessorFactory(
IXMLProcessorFactory factorySettee ) throws XMLException
The method signature is that way because:
public:
accessible from other packages
static:
applies the the class in general not a particular instance
synchronized:
thread-safe access to a static method is usually advisable
void:
standard JavaBean accessor method signature design pattern is:
TypeOfX getX() AND void setX( TypeOfX xToBe )
setIXMLProcessorFactory:
this method sets the class's IXMLProcessorFactory
IXMLProcessorFactory:
an Xapi-J interface for objects which can be asked to create
objects
which implement the interface IXMLProcessor. During "new
xml.XMLProcessor()" the factory will be asked to instantiation an
object which implements IXMLProcessor
factorySettee:
The object which is to be assigned as the factory
throws XMLException:
a general XML exception object; might be thrown if the
factory had already been set (a security concern expressed in the
regular JDK fashion)
So the developer could do the following:
XMLProcessor.setIXMLProcessorFactory( new MathMLProcFactory() );
XMLProcessor xmler = new XMLProcessor();
Here the developer using an Xapi-J compliant processor needs to do just
one special line of code (tell the XMLProcessor class that it should
ask the specified MathMLProcFactory object to create IXMLProcessor's).
After that all the implementation specific details of the
MathMLProcessor are hidden behind the Xapi-J interfaces i.e. just do a
"new XMLProcessor()" and access the document through Xapi-J interfaces.
This is possible because even though the class XMLProcessor is the only
real class in Xapi-J, it is essentially hollow. A XMLProcesssor instance
is not really an XML processor. Xapi-J does not include an XML
processor, just the interface to one. All an XMLProcessor does is
act as a proxy to an object which implements IXMLProcessor. The
IXMLProcessor object is instantiated by the above mentioned factory. So
in the source code for the XMLProcessor class we see something like
the following code fragments:
// Class static factory code:
private static IXMLProcessorFactory processorFactory;
public static synchronized void setIXMLProcessorFactory(
IXMLProcessorFactory factorySettee ) throws XMLException
{
processorFactory = factorySettee;
}
// Instance constructor code:
private IXMLProcessor implementation;
public XMLProcessor ()
{
this.implementation = processorFactory.createIXMLProcessor();
}
// instance action code:
public IDocument readXML( Object xmlSource ) throws XMLException
{
return implementation.readXML( xmlSource );
}
The execution sequence looks like:
1. The factory is set via XMLProcessor.setIXMLProcessorFactory().
2. Later, a "new XMLProcessor()" happens.
3. In the constructor the factory is asked to return an IXMLProcessor.
4. The IXMLProcessor object is assigned to the field "implementation".
5. Later, a "readXML()" call happens.
6. In readXML(), the XMLProcessor object, acting as a proxy, passes
the request onto its IXMLProcessor and then,
7. The XMLProcessor object returns whatever is returned to it from its
IXMLProcessor. I.e. class IXMLProcessor is the real worker.
So the phrase "Xapi-J contains no XML processor" could more precisely be
stated as: Xapi-J does contain a class XMLProcessor but it does not
contain an implementation of the interface IXMLProcessor which is the
real worker/processor in the Xapi-J architecture.
The above is a convoluted dance but to the developer who is simply using
an Xapi-J compliant XML processor it looks really simple on the outside.
(For a very similar "design patter" see java.net.Socket et al.) And only
one
API has to be learned to work with any Xapi-J compliant processor.
--
John Tigue
Sr. Software Architect
DataChannel
http://www.datachannel.com
jtigue at datachannel.com
206-462-1999
-------------- next part --------------
A non-text attachment was scrubbed...
Name: vcard.vcf
Type: text/x-vcard
Size: 263 bytes
Desc: Card for John Tigue
Url : http://mailman.ic.ac.uk/pipermail/xml-dev/attachments/19970803/36d826f5/vcard.vcf
More information about the Xml-dev
mailing list