Project

Profile

Help

Support #3237 » ContentHandlerForwarder.java

Aniruddha Joag, 2017-06-29 11:35

 
package test.saxon.streaming.transformerhandler;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;

import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.SAXSource;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

public class ContentHandlerForwarder implements ContentHandler
{
private final List<ContentHandler> listForkedContentHandlers = new ArrayList<>();
private final Consumer<ContentHandler> forkedContentHandlerConsumer = new Consumer<ContentHandler>()
{
@Override
public void accept(ContentHandler contentHandler)
{
listForkedContentHandlers.add(contentHandler);
}
};


private ContentHandlerForwarder(Transformer mainTransformer, Source mainSource, Transformation... forkingTransformations) throws TransformerException
{
if(forkingTransformations == null || forkingTransformations.length == 0)
return;

Transformation mainTransformation = new Transformation(mainTransformer, mainSource, new SAXResult(this));
TransformationSequencingXMLReader transformationSequencingXMLReader = new TransformationSequencingXMLReader(mainTransformation, forkedContentHandlerConsumer);
Transformation forkTransformation = null;
for(int i = 0; i < forkingTransformations.length; i++)
{
forkTransformation = forkingTransformations[i];
forkTransformation.setSource(new SAXSource(transformationSequencingXMLReader, null));
transformationSequencingXMLReader = new TransformationSequencingXMLReader(forkTransformation, forkedContentHandlerConsumer);
}
//forkTransformation now is the last of the forking transformer
//calling execute on it will
// 1. call the transform on the transformer object, which will first set a receiving content handler on the source for this transform
//which is a transformationChainingXMLReader. The setContentHandler of TransformationChainingXMLReader will pass on that content handler to the consumer
//which will add it to listForkedContentHandlers
// 2. call the parse method on transformationChainingXMLReader, which in turn will now call transform on the previous forked transform
//Thus the transform will be chained across each forked transform, while in each case collecting and storing the receiving content handler of that forked transform
//in listForkedContentHandlers
// 3. finally the first forked transform is called and the source assigned to it is the main source and the transformer is the main transformer
// The result for this main transform is an instance of ContentHandlerForwarder, which will forward the sax events received to every instance in listForkedContentHandlers
forkTransformation.execute();
}

public static void forkResult(Transformer mainTransformer, Source mainSource, Transformation... forkingTransformations) throws TransformerException
{
new ContentHandlerForwarder(mainTransformer, mainSource, forkingTransformations);
}

@Override
public void setDocumentLocator(Locator locator)
{
for(ContentHandler forkedContentHandler : listForkedContentHandlers)
forkedContentHandler.setDocumentLocator(locator);
}

@Override
public void endDocument() throws SAXException
{
for(ContentHandler forkedContentHandler : listForkedContentHandlers)
forkedContentHandler.endDocument();
}

@Override
public void startDocument() throws SAXException
{
for(ContentHandler forkedContentHandler : listForkedContentHandlers)
forkedContentHandler.startDocument();
}

@Override
public void startPrefixMapping(String prefix, String uri) throws SAXException
{
for(ContentHandler forkedContentHandler : listForkedContentHandlers)
forkedContentHandler.startPrefixMapping(prefix, uri);
}

@Override
public void endPrefixMapping(String prefix) throws SAXException
{
for(ContentHandler forkedContentHandler : listForkedContentHandlers)
forkedContentHandler.endPrefixMapping(prefix);
}

@Override
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException
{
for(ContentHandler forkedContentHandler : listForkedContentHandlers)
forkedContentHandler.startElement(uri, localName, qName, atts);
}

@Override
public void endElement(String uri, String localName, String qName) throws SAXException
{
for(ContentHandler forkedContentHandler : listForkedContentHandlers)
forkedContentHandler.endElement(uri, localName, qName);
}

@Override
public void characters(char[] ch, int start, int length) throws SAXException
{
for(ContentHandler forkedContentHandler : listForkedContentHandlers)
forkedContentHandler.characters(ch, start, length);
}

@Override
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException
{
for(ContentHandler forkedContentHandler : listForkedContentHandlers)
forkedContentHandler.ignorableWhitespace(ch, start, length);
}

@Override
public void processingInstruction(String target, String data) throws SAXException
{
for(ContentHandler forkedContentHandler : listForkedContentHandlers)
forkedContentHandler.processingInstruction(target, data);
}

@Override
public void skippedEntity(String name) throws SAXException
{
for(ContentHandler forkedContentHandler : listForkedContentHandlers)
forkedContentHandler.skippedEntity(name);
}
}
(12-12/15)