package org.exist.util.serializer; import org.exist.storage.DBBroker; import org.exist.storage.serializers.Serializer; import org.exist.util.serializer.json.JSONSerializer; import org.exist.xquery.XPathException; import org.exist.xquery.value.*; import org.xml.sax.SAXException; import org.xml.sax.SAXNotRecognizedException; import org.xml.sax.SAXNotSupportedException; import javax.xml.transform.OutputKeys; import java.io.Writer; import java.util.Properties; /** * Utility class for writing out XQuery results. It is an abstraction around * eXist's internal serializers specialized on writing XQuery sequences. * * @author Wolf */ public class XQuerySerializer { private final Properties outputProperties; private final DBBroker broker; private final Writer writer; public XQuerySerializer(DBBroker broker, Properties outputProperties, Writer writer) { super(); this.broker = broker; this.outputProperties = outputProperties; this.writer = writer; } public void serialize(final Sequence sequence) throws SAXException, XPathException { serialize(sequence, 1, sequence.getItemCount(), false, false, 0, 0); } public void serialize(final Sequence sequence, final int start, final int howmany, final boolean wrap, final boolean typed, final long compilationTime, final long executionTime) throws SAXException, XPathException { if (isJSON()) { serializeJSON(sequence, compilationTime, executionTime); } else { serializeXML(sequence, start, howmany, wrap, typed, compilationTime, executionTime); } } public boolean isJSON() { return "json".equals(outputProperties.getProperty(OutputKeys.METHOD, "xml")); } private void serializeXML(final Sequence sequence, final int start, final int howmany, final boolean wrap, final boolean typed, final long compilationTime, final long executionTime) throws SAXException, XPathException { final Serializer serializer = broker.getSerializer(); serializer.reset(); SAXSerializer sax = null; try { sax = (SAXSerializer) SerializerPool.getInstance().borrowObject( SAXSerializer.class); sax.setOutput(writer, outputProperties); serializer.setProperties(outputProperties); serializer.setSAXHandlers(sax, sax); serializer.toSAX(sequence, start, howmany, wrap, typed, compilationTime, executionTime); } catch (SAXNotSupportedException | SAXNotRecognizedException e) { throw new SAXException(e.getMessage(), e); } finally { if (sax != null) { SerializerPool.getInstance().returnObject(sax); } } } private void serializeJSON(final Sequence sequence, final long compilationTime, final long executionTime) throws SAXException, XPathException { // backwards compatibility: if the sequence contains a single element, we assume // it should be transformed to JSON following the rules of the old JSON writer if (sequence.hasOne() && Type.subTypeOf(sequence.getItemType(), Type.ELEMENT)) { serializeXML(sequence, 1, sequence.getItemCount(), false, false, compilationTime, executionTime); } else { JSONSerializer serializer = new JSONSerializer(broker, outputProperties); serializer.serialize(sequence, writer); } } }