[
Lists Home |
Date Index |
Thread Index
]
- From: Miles Sabin <msabin@cromwellmedia.co.uk>
- To: 'XML Dev' <xml-dev@ic.ac.uk>
- Date: Tue, 18 May 1999 15:51:15 +0100
David Megginson wrote,
> Miles Sabin writes:
> > It's not diamond inheritance per-se which is the
> > problem, it's (as you point out) the potential for a
> > combinatorial explosion of derived interfaces which is
> > nasty.
>
> Some concrete examples might be helpful -- I know that
> the get/setFeature/Property methods in Parser2 are not a
> silver bullet, but under what circumstances might people
> want to subclass Parser2 further in the future?
Err ... no, that's not what I meant. getProperty() deals
with things quite nicely. It's an example of something
Erich Gamma calls the 'Extension Objects Pattern'. See,
http://www.cs.wustl.edu/~schmidt/PLoP-96/gamma.txt
(only an abstract I'm afraid).
My point was more along the lines of getProperty() etc.
are (or, at least, will be) core Parser functionality,
and that they should, if possible, be defined in the main
Parser interface, rather than relegated to an auxilliary
extension interface. The various discussions on the DOM
IG seem to have come to the conclusion that augmenting
interfaces in this way isn't problematic in Java, and
that it's the cleanest and most comprehensible solution
to the interface evolution problem.
The biggest problem with the Parser2 route is that it
interacts badly with ParserFactory. ParserFactory's
methods return Parsers, so if getProperty() is defined
on Parser2 I have to cast before I can call it, and that's
ugly, particularly since the cast might fail.
ParserFactory can't be modified so that it's methods
return Parser2s without breaking signature compatability
with SAX1, but we can add the new methods directly to
Parser without causing any problems.
Actually, this probably needs a bit of clarification. I
guess a rejoinder might be: doesn't this break
compatibility with parsers which only implement the
current Parser interface? Ie. with a current parser,
wouldn't the effect of,
Parser p = ParserFactory.makeParser();
p.setProperty
("http://xml.org/sax/properties/dtd-handler",
myDTDHandler);
be to throw a NoSuchMethodException?
In fact this doesn't need to happen, because the SAX2
ParserFactory could do something like this,
public static Parser makeParser()
{
Parser p;
// Original stuff elided
try
{
p.getProperty("dummy");
// we get here if we're SAX2 compatible ...
return p;
}
catch(NoSuchMethodException ex)
{
// ... we get here if we're not.
return new SAX1ParserAdapter(p);
}
}
Where SAX1ParserAdapter is defined as follows,
class SAX1ParserAdapter
implements Parser
{
private Parser itsBaseParser;
private DocumentHandler itsDocumentHandler = null;
private DTDHandler itsDTDHandler = null;
private EntityResolver itsEntityResolver = null;
private ErrorHandler itsErrorHandler = null;
private Locale itsLocale = null;
public SAX1ParserAdapter(Parser baseParser)
{
itsBaseParser = baseParser;
}
public void setDocumentHandler
(DocumentHandler handler)
{
// cache locally ...
itsDocumentHandler = handler;
// forward to underlying SAX1 parser ...
itsBaseParser.setDocumentHandler(handler);
}
// etc. for for other Parser methods that can be
// safely forwarded to a SAX1 parser.
public void setFeature
(String featureId, boolean state)
{
// throw relevant exceptions
}
public boolean getFeature(String featureId)
{
// return SAX1 compatible results or throw
// relevant exceptions
}
public void setProperty
(String propertyId, Object value)
{
// call SAX1 Parser.setXXXHandler() methods
// where appropriate (and cache locally), or
// throw relevant exceptions.
}
public Object getProperty(String propertyId)
{
// return locally cached handlers where
// appropriate, or throw relevant exceptions.
}
}
This should work with all possible combinations of
SAX parsers, and SAX client applications.
Case 1: SAX1 parser, SAX1 client
No problem, it's the current situation.
Case 2: SAX1 parser, SAX2 client
No problem, dealt with by adapter as above. SAX2 client
can use SAX2 methods without casting and without having
to worry about NoSuchMethodExceptions.
Case 3: SAX2 parser, SAX1 client
No problem, SAX2 interfaces are backwards compatible.
Case 4: SAX2 parser, SAX2 client.
No problem. As in case 2, the SAX2 client can use SAX2
methods without casting and without having to worry
about NoSuchMethodExceptions.
Note that this assumes that a SAX2 client can only be
built against SAX2 interfaces and classes (which is fine
because that's guaranteed), and that a SAX2 client will
be able to ensure that the SAX2 ParserFactory is on its
classpath at runtime (which shouldn't be a problem).
Cheers,
Miles
--
Miles Sabin Cromwell Media
Internet Systems Architect 5/6 Glenthorne Mews
+44 (0)181 410 2230 London, W6 0LJ
msabin@cromwellmedia.co.uk England
xml-dev: A list for W3C XML Developers. To post, mailto:xml-dev@ic.ac.uk
Archived as: http://www.lists.ic.ac.uk/hypermail/xml-dev/ and on CD-ROM/ISBN 981-02-3594-1
To (un)subscribe, mailto:majordomo@ic.ac.uk the following message;
(un)subscribe xml-dev
To subscribe to the digests, mailto:majordomo@ic.ac.uk the following message;
subscribe xml-dev-digest
List coordinator, Henry Rzepa (mailto:rzepa@ic.ac.uk)
|