com.crabshue.commons.xproc.XprocRunner Maven / Gradle / Ivy
package com.crabshue.commons.xproc;
import java.io.File;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import javax.xml.transform.URIResolver;
import javax.xml.transform.sax.SAXSource;
import com.crabshue.commons.xproc.datastore.FileDataStore;
import net.sf.saxon.lib.ExtensionFunctionDefinition;
import org.xml.sax.InputSource;
import com.crabshue.commons.exceptions.ApplicationException;
import com.crabshue.commons.xproc.exceptions.XProcErrorType;
import com.crabshue.commons.xproc.helper.ErrorTranslator;
import com.xmlcalabash.core.XProcConfiguration;
import com.xmlcalabash.core.XProcException;
import com.xmlcalabash.core.XProcMessageListener;
import com.xmlcalabash.core.XProcRuntime;
import com.xmlcalabash.io.ReadablePipe;
import com.xmlcalabash.runtime.XOutput;
import com.xmlcalabash.runtime.XPipeline;
import net.sf.saxon.s9api.DocumentBuilder;
import net.sf.saxon.s9api.ExtensionFunction;
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.XdmNode;
public class XprocRunner {
private final Processor saxon;
private InputStream xproc;
private Map inputs;
private URIResolver resolver;
private FileDataStore dataStore;
private Class extends XProcMessageListener> listener;
private XprocRunner(boolean licensed) {
saxon = new Processor(false);
inputs = new HashMap<>();
}
private XprocRunner() {
this(false);
}
public static XprocRunner of(InputStream xproc) {
XprocRunner ret = new XprocRunner();
if (xproc == null) {
throw new ApplicationException(XProcErrorType.CANNOT_PARSE_INPUT,
"Pipeline could not be parsed, null object provided");
}
ret.xproc = xproc;
return ret;
}
public XprocRunner withLocalStore(File base){
this.dataStore = new FileDataStore(base);
return this;
}
public XprocRunner withExtensionFunction(ExtensionFunction function) {
saxon.registerExtensionFunction(function);
return this;
}
public XprocRunner withExtensionFunction(ExtensionFunctionDefinition extensionFunction) {
saxon.registerExtensionFunction(extensionFunction);
return this;
}
public XprocRunner withSource(InputStream xml) {
return this.withInputPort("source", xml);
}
public XprocRunner withInputPort(String portName, InputStream xml) {
this.inputs.put(portName, xml);
return this;
}
public XprocRunner withErrorListener(Class extends XProcMessageListener> listener) {
this.listener = listener;
return this;
}
public XprocRunner withUriResolver(URIResolver resolver) {
this.resolver = resolver;
return this;
}
public XprocResult run(OutputPortHandler handler) {
final XProcConfiguration config = new XProcConfiguration(saxon);
if (listener != null)
config.errorListener = listener.getName();
final DocumentBuilder builder = saxon.newDocumentBuilder();
final XProcRuntime runtime = new XProcRuntime(config);
if (resolver != null)
runtime.setURIResolver(resolver);
if(dataStore!=null){
dataStore.setOriginalStore(runtime.getDataStore());
runtime.setDataStore(dataStore);
}
try {
XdmNode pipeline = getNode(builder, xproc);
final XPipeline xpipeline = runtime.use(pipeline);
inputs.forEach((port, inputStream) -> {
xpipeline.writeTo(port, getNode(builder, inputStream));
});
xpipeline.run();
XprocResult ret = new XprocResult<>();
xpipeline.getOutputs().forEach(port -> {
final XOutput out = xpipeline.getOutput(port);
final ReadablePipe outPipe = out.getReader();
outPipe.canReadSequence(true);
while (outPipe.moreDocuments()) {
try {
ret.add(port, handler.handle(saxon, port, outPipe.read()));
} catch (SaxonApiException e) {
throw new ApplicationException(XProcErrorType.XPROC_CANNOT_RETRIEVE_OUTPUT,
"cannot retrieve the output port", e).addContextValue("port.name", port);
}
}
});
xpipeline.reset();
return ret;
} catch (SaxonApiException e) {
throw new ApplicationException(XProcErrorType.ERROR_IN_PIPELINE, "cannot process the pipeline", e);
} catch (XProcException e) {
throw new ApplicationException(XProcErrorType.XPROC_ERROR, "cannot process the pipeline", e)
.addContextValue("code", e.getErrorCode())
.addContextValue("explanation", ErrorTranslator.translate(e.getErrorCode()));
} finally {
// FIXME: need to figure out...
// function.reset();
runtime.close();
}
}
/**
* Transform inputStream into xPipeline compatible node.
*
* @param builder
* @param inputStream
* @return
*/
private XdmNode getNode(DocumentBuilder builder, InputStream inputStream) {
if (inputStream == null) {
throw new ApplicationException(XProcErrorType.CANNOT_PARSE_INPUT,
"Input could not be parsed, null object provided");
}
try {
return builder.build(new SAXSource(new InputSource(inputStream)));
} catch (SaxonApiException e) {
throw new ApplicationException(XProcErrorType.CANNOT_PARSE_INPUT, "Input could not be parsed", e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy