package client.net.sf.saxon.ce.event; import client.net.sf.saxon.ce.Configuration; import client.net.sf.saxon.ce.om.NamePool; import client.net.sf.saxon.ce.om.Item; import client.net.sf.saxon.ce.om.NamespaceBinding; import client.net.sf.saxon.ce.trans.XPathException; /** * A ProxyReceiver is an Receiver that filters data before passing it to another * underlying Receiver. */ public abstract class ProxyReceiver extends SequenceReceiver { protected Receiver nextReceiver; public void setSystemId(String systemId) { //noinspection StringEquality if (systemId != this.systemId) { // use of == rather than equals() is deliberate, since this is only an optimization this.systemId = systemId; if (nextReceiver != null) { nextReceiver.setSystemId(systemId); } } } /** * Set the underlying receiver. This call is mandatory before using the Receiver. * @param receiver the underlying receiver, the one that is to receive events after processing * by this filter. */ public void setUnderlyingReceiver(Receiver receiver) { if (receiver != nextReceiver) { nextReceiver = receiver; if (pipelineConfiguration != null && receiver != null) { nextReceiver.setPipelineConfiguration(pipelineConfiguration); } } } /** * Get the underlying Receiver (that is, the next one in the pipeline) */ public Receiver getUnderlyingReceiver() { return nextReceiver; } public void setPipelineConfiguration(PipelineConfiguration pipe) { if (pipelineConfiguration != pipe) { pipelineConfiguration = pipe; if (nextReceiver != null) { nextReceiver.setPipelineConfiguration(pipe); } } } public Configuration getConfiguration() { return pipelineConfiguration.getConfiguration(); } /** * Get the namepool for this configuration */ public NamePool getNamePool() { return pipelineConfiguration.getConfiguration().getNamePool(); } /** * Start of event stream */ public void open() throws XPathException { if (nextReceiver == null) { throw new IllegalStateException("ProxyReceiver.open(): no underlying receiver provided"); } nextReceiver.open(); } /** * End of output. Note that closing this receiver also closes the rest of the * pipeline. */ public void close() throws XPathException { // Note: It's wrong to assume that because we've finished writing to this // receiver, then we've also finished writing to other receivers in the pipe. // In the case where the rest of the pipe is to stay open, the caller should // either avoid doing the close(), or should first set the underlying receiver // to null. nextReceiver.close(); } /** * Start of a document node. */ public void startDocument() throws XPathException { nextReceiver.startDocument(); } /** * Notify the end of a document node */ public void endDocument() throws XPathException { nextReceiver.endDocument(); } /** * Notify the start of an element * * @param nameCode integer code identifying the name of the element within the name pool. * @param properties properties of the element node */ public void startElement(int nameCode, int properties) throws XPathException { nextReceiver.startElement(nameCode, properties); } /** * Notify a namespace. Namespaces are notified <b>after</b> the startElement event, and before * any children for the element. The namespaces that are reported are only required * to include those that are different from the parent element; however, duplicates may be reported. * A namespace must not conflict with any namespaces already used for element or attribute names. * * @param nsBinding an integer: the top half is a prefix code, the bottom half a URI code. * These may be translated into an actual prefix and URI using the name pool. A prefix code of * zero represents the empty prefix (that is, the default namespace). A URI code of zero represents * a URI of "", that is, a namespace undeclaration. * @throws IllegalStateException: attempt to output a namespace when there is no open element * start tag */ public void namespace(NamespaceBinding nsBinding, int properties) throws XPathException { nextReceiver.namespace(nsBinding, properties); } /** * Notify an attribute. Attributes are notified after the startElement event, and before any * children. Namespaces and attributes may be intermingled. * * @param nameCode The name of the attribute, as held in the name pool * @throws IllegalStateException: attempt to output an attribute when there is no open element * start tag */ public void attribute(int nameCode, CharSequence value) throws XPathException { nextReceiver.attribute(nameCode, value); } /** * Notify the start of the content, that is, the completion of all attributes and namespaces. * Note that the initial receiver of output from XSLT instructions will not receive this event, * it has to detect it itself. Note that this event is reported for every element even if it has * no attributes, no namespaces, and no content. */ public void startContent() throws XPathException { nextReceiver.startContent(); } /** * End of element */ public void endElement() throws XPathException { nextReceiver.endElement(); } /** * Character data */ public void characters(CharSequence chars) throws XPathException { nextReceiver.characters(chars); } /** * Processing Instruction */ public void processingInstruction(String target, CharSequence data) throws XPathException { nextReceiver.processingInstruction(target, data); } /** * Output a comment */ public void comment(CharSequence chars) throws XPathException { nextReceiver.comment(chars); } /** * Append an arbitrary item (node or atomic value) to the output * * @param item the item to be appended * @param copyNamespaces if the item is an element node, this indicates whether its namespaces * need to be copied. Values are {@link client.net.sf.saxon.ce.om.NodeInfo#ALL_NAMESPACES}, * {@link client.net.sf.saxon.ce.om.NodeInfo#LOCAL_NAMESPACES}, {@link client.net.sf.saxon.ce.om.NodeInfo#NO_NAMESPACES} */ public void append(Item item, int copyNamespaces) throws XPathException { if (nextReceiver instanceof SequenceReceiver) { ((SequenceReceiver)nextReceiver).append(item, copyNamespaces); } else { throw new UnsupportedOperationException("append() method is not supported in this class"); } } } // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. // If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. // This Source Code Form is “Incompatible With Secondary Licenses”, as defined by the Mozilla Public License, v. 2.0.