gnu.xml.pipeline
Class EventFilter
java.lang.Object
|
+--gnu.xml.pipeline.EventFilter
All Implemented Interfaces:
EventConsumer, ContentHandler, DTDHandler, DeclHandler, LexicalHandlerKnown Direct Subclasses:
LinkFilter, NSFilter, ValidationConsumer, WellFormednessFilter, XIncludeFilter, XsltFilter
A customizable event consumer, used to assemble various kinds of filters
using SAX handlers and an optional second consumer. It can be constructed
in two ways:
- To serve as a passthrough, sending all events to a second consumer.
The second consumer may be identified through
getNext.
To serve as a dead end, with all handlers null;
getNext returns null.
Additionally, SAX handlers may be assigned, which completely replace
the "upstream" view (through
EventConsumer) of handlers, initially
null or the "next" consumer provided to the constructor. To make
it easier to build specialized filter classes, this class implements
all the standard SAX consumer handlers, and those implementations
delegate "downstream" to the consumer accessed by
getNext.
The simplest way to create a custom a filter class is to create a
subclass which overrides one or more handler interface methods. The
constructor for that subclass then registers itself as a handler for
those interfaces using a call such as
setContentHandler(this),
so the "upstream" view of event delivery is modified from the state
established in the base class constructor. That way,
the overridden methods intercept those event callbacks
as they go "downstream", and
all other event callbacks will pass events to any next consumer.
Overridden methods may invoke superclass methods (perhaps after modifying
parameters) if they wish to delegate such calls. Such subclasses
should use
getErrorHandler to report errors using the
common error reporting mechanism.
Another important technique is to construct a filter consisting
of only a few specific types of handler. For example, one could easily
prune out lexical events or various declarations by providing handlers
which don't pass those events downstream, or by providing null handlers.
This may be viewed as the consumer oriented analogue of the SAX2
org.xml.sax.helpers.XMLFilterImpl XMLFilterImpl class.
Key differences include:
- This fully separates consumer and producer roles: it
does not implement the producer side XMLReader or
EntityResolver interfaces, so it can only be used
in "push" mode (it has no parse() methods).
- "Extension" handlers are fully supported, enabling a
richer set of application requirements.
And it implements
EventConsumer, which groups related
consumer methods together, rather than leaving them separated.
The chaining which is visible is "downstream" to the next
consumer, not "upstream" to the preceding producer.
It supports "fan-in", where
a consumer can be fed by several producers. (For "fan-out",
see the TeeConsumer class.)
Event chaining is set up differently. It is intended to
work "upstream" from terminus towards producer, during filter
construction, as described above.
This is part of an early binding model:
events don't need to pass through stages which ignore them.
ErrorHandler support is separated, on the grounds that
pipeline stages need to share the same error handling policy.
For the same reason, error handler setup goes "downstream":
when error handlers get set, they are passed to subsequent
consumers.
The chainTo chainTo() convenience routine supports chaining to
an XMLFilterImpl, in its role as a limited functionality event
consumer. Its event producer role (
XMLFilter) is ignored.
The
bind bind() routine may be used associate event pipelines
with any kind of
XMLReader that will produce the events.
Such pipelines don't necessarily need to have any members which are
implemented using this class. That routine has some intelligence
which supports automatic changes to parser feature flags, letting
event piplines become largely independent of the particular feature
sets of parsers.
- David Brownell
void | attributeDecl(java.lang.String eName, java.lang.String aName, java.lang.String type, java.lang.String mode, java.lang.String value) |
static void | bind(XMLReader producer, EventConsumer consumer) |
void | chainTo(XMLFilterImpl next) |
void | characters(char ch[] , int start, int length) |
void | comment(char ch[] , int start, int length) |
void | elementDecl(java.lang.String name, java.lang.String model) |
void | endCDATA() |
void | endDocument() |
void | endDTD() |
void | endElement(java.lang.String uri, java.lang.String localName, java.lang.String qName) |
void | endEntity(java.lang.String name) |
void | endPrefixMapping(java.lang.String prefix) |
void | externalEntityDecl(java.lang.String name, java.lang.String publicId, java.lang.String systemId) |
ContentHandler | getContentHandler() |
Locator | getDocumentLocator() |
DTDHandler | getDTDHandler() |
ErrorHandler | getErrorHandler() |
EventConsumer | getNext() |
java.lang.Object | getProperty(java.lang.String id) |
void | ignorableWhitespace(char ch[] , int start, int length) |
void | internalEntityDecl(java.lang.String name, java.lang.String value) |
void | notationDecl(java.lang.String name, java.lang.String publicId, java.lang.String systemId) |
void | processingInstruction(java.lang.String target, java.lang.String data) |
void | setContentHandler(ContentHandler h) |
void | setDocumentLocator(Locator locator) |
void | setDTDHandler(DTDHandler h) |
void | setErrorHandler(ErrorHandler handler) |
void | setProperty(java.lang.String id, java.lang.Object o) |
void | skippedEntity(java.lang.String name) |
void | startCDATA() |
void | startDocument() |
void | startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId) |
void | startElement(java.lang.String uri, java.lang.String localName, java.lang.String qName, Attributes atts) |
void | startEntity(java.lang.String name) |
void | startPrefixMapping(java.lang.String prefix, java.lang.String uri) |
void | unparsedEntityDecl(java.lang.String name, java.lang.String publicId, java.lang.String systemId, java.lang.String notationName) |
DECL_HANDLER
public static final String DECL_HANDLER
FEATURE_URI
public static final String FEATURE_URI
SAX2 URI prefix for standard feature flags.
LEXICAL_HANDLER
public static final String LEXICAL_HANDLER
PROPERTY_URI
public static final String PROPERTY_URI
SAX2 URI prefix for standard properties (mostly for handlers).
EventFilter
public EventFilter()
Initializes all handlers to null.
EventFilter
public EventFilter(EventConsumer consumer)
Handlers that are not otherwise set will default to those from
the specified consumer, making it easy to pass events through.
If the consumer is null, all handlers are initialzed to null.
- consumer
attributeDecl
public void attributeDecl(java.lang.String eName, java.lang.String aName, java.lang.String type, java.lang.String mode, java.lang.String value)
SAX2: passes this callback to the next consumer, if any
- eName
- aName
- type
- mode
- value
bind
public static void bind(XMLReader producer, EventConsumer consumer)
Binds the standard SAX2 handlers from the specified consumer
pipeline to the specified producer. These handlers include the core
ContentHandler and
DTDHandler, plus the extension
DeclHandler and
LexicalHandler. Any additional
application-specific handlers need to be bound separately.
The
ErrorHandler is handled differently: the producer's
error handler is passed through to the consumer pipeline.
The producer is told to include namespace prefix information if it
can, since many pipeline stages need that Infoset information to
work well.
At the head of the pipeline, certain standard event filters are
recognized and handled specially. This facilitates construction
of processing pipelines that work regardless of the capabilities
of the XMLReader implementation in use; for example, it permits
validating output of a
gnu.xml.util.DomParser.
NSFilter will be removed if the producer can be
told not to discard namespace data, using the "namespace-prefixes"
feature flag.
ValidationConsumer will be removed if the producer
can be told to validate, using the "validation" feature flag.
WellFormednessFilter is always removed, on the
grounds that no XMLReader is permitted to producee malformed
event streams and this would just be processing overhead.
XIncludeFilter stops the special handling, except
that it's told about the "namespace-prefixes" feature of the
event producer so that the event stream is internally consistent.
The first consumer which is not one of those classes stops
such special handling. This means that if you want to force
one of those filters to be used, you could just precede it with
an instance of EventFilter configured as a pass-through.
You might need to do that if you are using an
NSFilter
subclass to fix names found in attributes or character data.
Other than that, this method works with any kind of event consumer,
not just event filters. Note that in all cases, the standard handlers
are assigned; any previous handler assignments for the handler will
be overridden.
- producer - will deliver events to the specified consumer
- consumer - pipeline supplying event handlers to be associated
with the producer (may not be null)
chainTo
public void chainTo(XMLFilterImpl next)
Treats the XMLFilterImpl as a limited functionality event consumer,
by arranging to deliver events to it; this lets such classes be
"wrapped" as pipeline stages.
Upstream Event Setup:
If no handlers have been assigned to this EventFilter, then the
handlers from specified XMLFilterImpl are returned from this
EventConsumer: the XMLFilterImpl is just "wrapped".
Otherwise the specified handlers will be returned.
Downstream Event Setup:
Subclasses may chain event delivery to the specified XMLFilterImpl
by invoking the appropiate superclass methods,
as if their constructor passed a "next" EventConsumer to the
constructor for this class.
If this EventFilter has an ErrorHandler, it is assigned as
the error handler for the XMLFilterImpl, just as would be
done for a next stage implementing
EventConsumer.
- next - the next downstream component of the pipeline.
java.lang.IllegalStateException
- if the "next" consumer has
already been set through the constructor.
characters
public void characters(char ch[] , int start, int length)
SAX2: passes this callback to the next consumer, if any
- start
- length
comment
public void comment(char ch[] , int start, int length)
SAX2: passes this callback to the next consumer, if any
- start
- length
elementDecl
public void elementDecl(java.lang.String name, java.lang.String model)
SAX2: passes this callback to the next consumer, if any
- name
- model
endCDATA
public void endCDATA()
SAX2: passes this callback to the next consumer, if any
endDocument
public void endDocument()
SAX2: passes this callback to the next consumer, if any
endDTD
public void endDTD()
SAX2: passes this callback to the next consumer, if any
endElement
public void endElement(java.lang.String uri, java.lang.String localName, java.lang.String qName)
SAX2: passes this callback to the next consumer, if any
- uri
- localName
- qName
endEntity
public void endEntity(java.lang.String name)
SAX2: passes this callback to the next consumer, if any.
- name
endPrefixMapping
public void endPrefixMapping(java.lang.String prefix)
SAX2: passes this callback to the next consumer, if any
- prefix
externalEntityDecl
public void externalEntityDecl(java.lang.String name, java.lang.String publicId, java.lang.String systemId)
SAX2: passes this callback to the next consumer, if any
- name
- publicId
- systemId
getContentHandler
public final ContentHandler getContentHandler()
Returns the content handler being used.
getDocumentLocator
public Locator getDocumentLocator()
Returns any locator provided to the next consumer, if this class
(or a subclass) is handling
ContentHandler events.
getDTDHandler
public final DTDHandler getDTDHandler()
Returns the dtd handler being used.
getErrorHandler
public final ErrorHandler getErrorHandler()
Returns the error handler assigned this filter stage, or null
if no such assigment has been made.
getNext
public final EventConsumer getNext()
Returns the next event consumer in sequence; or null if there
is no such handler.
getProperty
public final Object getProperty(java.lang.String id)
Retrieves a property of unknown intent (usually a handler)
- id
ignorableWhitespace
public void ignorableWhitespace(char ch[] , int start, int length)
SAX2: passes this callback to the next consumer, if any
- start
- length
internalEntityDecl
public void internalEntityDecl(java.lang.String name, java.lang.String value)
SAX2: passes this callback to the next consumer, if any
- name
- value
notationDecl
public void notationDecl(java.lang.String name, java.lang.String publicId, java.lang.String systemId)
SAX1: passes this callback to the next consumer, if any
- name
- publicId
- systemId
processingInstruction
public void processingInstruction(java.lang.String target, java.lang.String data)
SAX2: passes this callback to the next consumer, if any
- target
- data
setContentHandler
public final void setContentHandler(ContentHandler h)
Assigns the content handler to use; a null handler indicates
that these events will not be forwarded.
This overrides the previous settting for this handler, which was
probably pointed to the next consumer by the base class constructor.
- h
setDocumentLocator
public void setDocumentLocator(Locator locator)
SAX2: passes this callback to the next consumer, if any
- locator
setDTDHandler
public final void setDTDHandler(DTDHandler h)
Assigns the DTD handler to use; a null handler indicates
that these events will not be forwarded.
This overrides the previous settting for this handler, which was
probably pointed to the next consumer by the base class constructor.
- h
setErrorHandler
public final void setErrorHandler(ErrorHandler handler)
Records the error handler that should be used by this stage, and
passes it "downstream" to any subsequent stage.
- handler
setProperty
public final void setProperty(java.lang.String id, java.lang.Object o)
Stores the property, normally a handler; a null handler indicates
that these events will not be forwarded.
This overrides the previous handler settting, which was probably
pointed to the next consumer by the base class constructor.
- id
- o
skippedEntity
public void skippedEntity(java.lang.String name)
SAX2: passes this callback to the next consumer, if any
- name
startCDATA
public void startCDATA()
SAX2: passes this callback to the next consumer, if any
startDocument
public void startDocument()
SAX2: passes this callback to the next consumer, if any
startDTD
public void startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId)
SAX2: passes this callback to the next consumer, if any
- name
- publicId
- systemId
startElement
public void startElement(java.lang.String uri, java.lang.String localName, java.lang.String qName, Attributes atts)
SAX2: passes this callback to the next consumer, if any
- uri
- localName
- qName
- atts
startEntity
public void startEntity(java.lang.String name)
SAX2: passes this callback to the next consumer, if any.
- name
startPrefixMapping
public void startPrefixMapping(java.lang.String prefix, java.lang.String uri)
SAX2: passes this callback to the next consumer, if any
- prefix
- uri
unparsedEntityDecl
public void unparsedEntityDecl(java.lang.String name, java.lang.String publicId, java.lang.String systemId, java.lang.String notationName)
SAX1: passes this callback to the next consumer, if any
- name
- publicId
- systemId
- notationName
- To serve as a passthrough, sending all events to a second consumer.
The second consumer may be identified through
getNext.This may be viewed as the consumer oriented analogue of the SAX2 org.xml.sax.helpers.XMLFilterImpl XMLFilterImpl class. Key differences include:
- This fully separates consumer and producer roles: it
does not implement the producer side XMLReader or
EntityResolver interfaces, so it can only be used
in "push" mode (it has no parse() methods).
- "Extension" handlers are fully supported, enabling a
richer set of application requirements.
And it implements
EventConsumer, which groups related consumer methods together, rather than leaving them separated.The bind bind() routine may be used associate event pipelines with any kind of XMLReader that will produce the events. Such pipelines don't necessarily need to have any members which are implemented using this class. That routine has some intelligence which supports automatic changes to parser feature flags, letting event piplines become largely independent of the particular feature sets of parsers.