package org.xbib.elasticsearch.plugin.rest.oai; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.common.io.stream.BytesStreamOutput; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.rest.BytesRestResponse; import org.elasticsearch.rest.RestChannel; import org.elasticsearch.rest.RestResponse; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.rest.action.support.RestResponseListener; import org.elasticsearch.search.SearchHit; import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.ISODateTimeFormat; import org.xbib.oai.OAIConstants; import org.xbib.oai.server.ServerOAIRequest; import org.xbib.xml.XSI; import javax.xml.namespace.QName; import javax.xml.stream.XMLEventFactory; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.util.XMLEventConsumer; import java.io.IOException; import java.io.OutputStream; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Map; public class OAIResponseBuilder extends RestResponseListener<SearchResponse> implements OAIConstants { private final static XMLEventFactory eventFactory = XMLEventFactory.newInstance(); private final static XMLOutputFactory outputfactory = XMLOutputFactory.newInstance(); private final static DateTimeFormatter formatter = ISODateTimeFormat.dateTimeNoMillis(); private final Settings settings; private XMLEventConsumer consumer; public OAIResponseBuilder(Settings settings, RestChannel channel) { super(channel); this.settings = settings; } protected Settings settings() { return settings; } @Override public RestResponse buildResponse(SearchResponse response) throws Exception { return buildResponse(response, channel.bytesOutput()); } protected RestResponse buildResponse(SearchResponse response, BytesStreamOutput out) throws Exception { if (response.getHits().getHits().length > 0) { for (SearchHit hits : response.getHits()) { // TODO } } return new BytesRestResponse(RestStatus.OK, "text/xml; charset=UTF-8", out.bytes()); } protected OAIResponseBuilder setOutputStream(OutputStream out) throws XMLStreamException { this.consumer = outputfactory.createXMLEventWriter(out); return this; } protected OAIResponseBuilder beginDocument() throws XMLStreamException { consumer.add(eventFactory.createStartDocument()); return this; } protected OAIResponseBuilder endDocument() throws XMLStreamException, IOException { consumer.add(eventFactory.createEndDocument()); return this; } protected OAIResponseBuilder beginElement(String name) throws XMLStreamException { consumer.add(eventFactory.createStartElement(toQName(NS_URI, name), null, null)); return this; } protected OAIResponseBuilder endElement(String name) throws XMLStreamException { consumer.add(eventFactory.createEndElement(toQName(NS_URI, name), null)); return this; } protected OAIResponseBuilder element(String name) throws XMLStreamException { consumer.add(eventFactory.createStartElement(toQName(NS_URI, name), null, null)); consumer.add(eventFactory.createEndElement(toQName(NS_URI, name), null)); return this; } protected OAIResponseBuilder element(String name, String value) throws XMLStreamException { consumer.add(eventFactory.createStartElement(toQName(NS_URI, name), null, null)); consumer.add(eventFactory.createCharacters(value)); consumer.add(eventFactory.createEndElement(toQName(NS_URI, name), null)); return this; } protected OAIResponseBuilder element(String name, Date value) throws XMLStreamException { consumer.add(eventFactory.createStartElement(toQName(NS_URI, name), null, null)); consumer.add(eventFactory.createCharacters(formatter.print(value.getTime()))); consumer.add(eventFactory.createEndElement(toQName(NS_URI, name), null)); return this; } protected OAIResponseBuilder beginResponse(String baseURL, ServerOAIRequest serverOAIRequest) throws XMLStreamException { consumer.add(eventFactory.createStartElement(toQName(NS_URI, "OAI-PMH"), null, null)); consumer.add(eventFactory.createNamespace(NS_URI)); consumer.add(eventFactory.createNamespace(XSI.NS_PREFIX, XSI.NS_URI)); consumer.add(eventFactory.createAttribute(XSI.NS_PREFIX, XSI.NS_URI, "schemaLocation", "http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd")); element("responseDate", new Date()); request(serverOAIRequest.getParameterMap(), baseURL); return this; } protected OAIResponseBuilder endResponse() throws XMLStreamException { consumer.add(eventFactory.createEndElement(toQName(NS_URI, "OAI-PMH"), null)); return this; } protected OAIResponseBuilder request(Map<String,Object> attrs, String baseURL) throws XMLStreamException { consumer.add(eventFactory.createStartElement(toQName(NS_URI, REQUEST), null, null)); for (Map.Entry<String,Object> me : attrs.entrySet()) { Object o = me.getValue(); if (!(o instanceof List)) { o = Arrays.asList(o); } for (Object value : (List)o) { consumer.add(eventFactory.createAttribute(me.getKey(),value.toString())); } } consumer.add(eventFactory.createCharacters(baseURL)); consumer.add(eventFactory.createEndElement(toQName(NS_URI, REQUEST), null)); return this; } protected QName toQName(String namespaceUri, String qname) { int i = qname.indexOf(':'); if (i == -1) { return new QName(namespaceUri, qname); } else { String prefix = qname.substring(0, i); String localPart = qname.substring(i + 1); return new QName(namespaceUri, localPart, prefix); } } }