Changeset 2204


Ignore:
Timestamp:
09/11/12 10:06:45 (12 years ago)
Author:
oschonef
Message:
  • add support or extra*Data in SRU responses

HEADS UP: This breaks the existing (just stubbed out API),

because DocumentFragment? had to be used in favor of Document
to hold the XML fragment from the SRU response.

Location:
SRUClient/trunk/src/main/java/eu/clarin/sru/client
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUAbstractResponse.java

    r2203 r2204  
    2020import java.util.List;
    2121
    22 import org.w3c.dom.Document;
     22import org.w3c.dom.DocumentFragment;
    2323
    2424
     
    3434    private final T request;
    3535    private final List<SRUDiagnostic> diagnostics;
    36     private final Document extraResponseData;
     36    private final DocumentFragment extraResponseData;
    3737    private final int totalBytesTransferred;
    3838    private final long timeTotal;
     
    6666     *            processed the response from the endpoint
    6767     */
    68     protected SRUAbstractResponse(T request, List<SRUDiagnostic> diagnostics,
    69             Document extraResponseData, int totalBytesTransferred,
    70             long timeTotal, long timeQueued, long timeNetwork,
     68    protected SRUAbstractResponse(T request,
     69            List<SRUDiagnostic> diagnostics,
     70            DocumentFragment extraResponseData,
     71            int totalBytesTransferred,
     72            long timeTotal,
     73            long timeQueued,
     74            long timeNetwork,
    7175            long timeProcessing) {
    7276        this.request = request;
     
    121125     * Get the extra response data for this result.
    122126     *
    123      * @return a {@link Document} node for the extra response data or
    124      *         <code>null</code> if none
    125      */
    126     public Document getExtraResponseData() {
     127     * @return get an instance of {@link DocumentFragment} containing the XML
     128     *         fragment for the extra response data from the SRU response or
     129     *         <code>null</code> if none are available
     130     */
     131    public DocumentFragment getExtraResponseData() {
    127132        return extraResponseData;
     133    }
     134
     135
     136    /**
     137     * Check, if this response has any extra response data attached to it.
     138     *
     139     * @return <code>true</code> if extra response is attached,
     140     *         <code>false</code> otherwise
     141     */
     142    public boolean hasExtraResponseData() {
     143        return extraResponseData != null;
    128144    }
    129145
  • SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUClient.java

    r2203 r2204  
    1717package eu.clarin.sru.client;
    1818
     19import java.util.ArrayDeque;
    1920import java.util.ArrayList;
     21import java.util.Deque;
    2022import java.util.HashMap;
    2123import java.util.List;
     
    2325import java.util.concurrent.TimeUnit;
    2426
     27import javax.xml.XMLConstants;
     28import javax.xml.parsers.DocumentBuilder;
     29import javax.xml.parsers.DocumentBuilderFactory;
     30import javax.xml.parsers.ParserConfigurationException;
     31import javax.xml.stream.XMLStreamConstants;
    2532import javax.xml.stream.XMLStreamException;
    2633import javax.xml.stream.XMLStreamReader;
    2734
     35import org.w3c.dom.Attr;
     36import org.w3c.dom.DOMException;
    2837import org.w3c.dom.Document;
     38import org.w3c.dom.DocumentFragment;
     39import org.w3c.dom.Element;
     40import org.w3c.dom.Node;
    2941
    3042
     
    4355    /* common */
    4456    private List<SRUDiagnostic> diagnostics;
    45     private Document extraResponseData;
     57    private DocumentFragment extraResponseData;
    4658    /* explain */
    4759    private SRURecord record;
     
    6072    private long timeNetwork;
    6173    private long timeParsing;
     74    /* other fields */
     75    private final DocumentBuilder documentBuilder;
     76    private final Deque<Node> stack = new ArrayDeque<Node>();
     77
    6278
    6379    /**
     
    100116    public SRUClient(SRUVersion defaultVersion, boolean strictMode) {
    101117        this(defaultVersion, strictMode,
    102                 new HashMap<String, SRURecordDataParser>());
     118                new HashMap<String, SRURecordDataParser>(),
     119                DocumentBuilderFactory.newInstance());
    103120    }
    104121
     
    124141     */
    125142    SRUClient(SRUVersion defaultVersion, boolean strictMode,
    126             Map<String, SRURecordDataParser> parsers) {
     143            Map<String, SRURecordDataParser> parsers,
     144            DocumentBuilderFactory documentBuilderFactory) {
    127145        if (defaultVersion == null) {
    128146            throw new NullPointerException("version == null");
     
    133151        this.client = new SRUSimpleClient(defaultVersion, strictMode, parsers);
    134152        this.handler = new Handler();
     153        try {
     154            synchronized (documentBuilderFactory) {
     155                documentBuilderFactory.setNamespaceAware(true);
     156                documentBuilderFactory.setCoalescing(true);
     157                this.documentBuilder =
     158                        documentBuilderFactory.newDocumentBuilder();
     159            } // documentBuilderFactory (documentBuilderFactory)
     160        } catch (ParserConfigurationException e) {
     161            throw new Error("error initialzing document builder factory", e);
     162        }
    135163        reset();
    136164    }
     
    315343        public void onExtraResponseData(XMLStreamReader reader)
    316344                throws XMLStreamException, SRUClientException {
    317             // TODO: parse extraResponseData
     345            final List<SRURecord> records = SRUClient.this.records;
     346            if ((records != null) && !records.isEmpty()) {
     347                final SRURecord record = records.get(records.size() - 1);
     348                record.setExtraRecordData(copyStaxToDocumentFragment(
     349                        documentBuilder, stack, reader));
     350            } else {
     351                /*
     352                 * should never happen ...
     353                 */
     354                throw new SRUClientException(
     355                        "internal error; 'records' are null or empty");
     356            }
    318357        }
    319358
     
    324363                throws SRUClientException {
    325364            SRUClient.this.addTerm(new SRUTerm(value, numberOfRecords,
    326                     displayTerm, whereInList, null));
     365                    displayTerm, whereInList));
    327366        }
    328367
     
    331370        public void onExtraTermData(String value, XMLStreamReader reader)
    332371                throws XMLStreamException, SRUClientException {
    333             // TODO: parse extraTermData
     372            final List<SRUTerm> terms = SRUClient.this.terms;
     373            if ((terms != null) && !terms.isEmpty()) {
     374                SRUTerm term = terms.get(terms.size() - 1);
     375                term.setExtraTermData(copyStaxToDocumentFragment(
     376                        documentBuilder, stack, reader));
     377            } else {
     378                /*
     379                 * should never happen ...
     380                 */
     381                throw new SRUClientException(
     382                        "internal error; 'terms' is null or empty");
     383            }
    334384        }
    335385
     
    353403        public void onRecord(String identifier, int position,
    354404                SRURecordData data) throws SRUClientException {
    355             SRUClient.this.addRecord(new SRURecord(data, identifier,
    356                     position, null));
     405            SRUClient.this.addRecord(
     406                    new SRURecord(data, identifier, position));
    357407        }
    358408
     
    362412                SRUDiagnostic data) throws SRUClientException {
    363413            SRUClient.this.addRecord(new SRURecord(
    364                     new SRUSurrogateRecordData(data), identifier, position,
    365                     null));
     414                    new SRUSurrogateRecordData(data), identifier, position));
    366415        }
    367416
     
    371420                XMLStreamReader reader) throws XMLStreamException,
    372421                SRUClientException {
    373             // TODO: parseExtraRecordData
     422            extraResponseData =
     423                    copyStaxToDocumentFragment(documentBuilder, stack, reader);
    374424        }
    375425
     
    387437            SRUClient.this.timeParsing = millisProcessing;
    388438        }
     439
    389440    } // inner class Handler
    390441
     442
     443    private static DocumentFragment copyStaxToDocumentFragment(
     444            DocumentBuilder builder, Deque<Node> stack, XMLStreamReader reader)
     445            throws XMLStreamException {
     446        try {
     447            final Document doc = builder.newDocument();
     448            stack.push(doc.createDocumentFragment());
     449
     450            while (reader.hasNext()) {
     451                final Node parent = stack.peek();
     452                switch (reader.getEventType()) {
     453                case XMLStreamConstants.START_ELEMENT:
     454                    stack.push(createElementNode(parent, doc, reader));
     455                    break;
     456                case XMLStreamConstants.END_ELEMENT:
     457                    stack.pop();
     458                    break;
     459                case XMLStreamConstants.CHARACTERS:
     460                    parent.appendChild(doc.createTextNode(reader.getText()));
     461                    break;
     462                case XMLStreamConstants.COMMENT:
     463                    parent.appendChild(doc.createComment(reader.getText()));
     464                    break;
     465                case XMLStreamConstants.CDATA:
     466                    parent.appendChild(doc.createCDATASection(reader.getText()));
     467                    break;
     468                default:
     469                    break;
     470                }
     471                reader.next();
     472            } // while
     473            if (stack.size() != 1) {
     474                throw new XMLStreamException(
     475                        "internal error; stack should hold only one element");
     476            }
     477            return (DocumentFragment) stack.pop();
     478        } catch (DOMException e) {
     479            throw new XMLStreamException(
     480                    "error creating document fragment", e);
     481        }
     482    }
     483
     484
     485    private static Element createElementNode(Node parent, Document doc,
     486            XMLStreamReader reader) throws XMLStreamException, DOMException {
     487        Element element = doc.createElementNS(reader.getNamespaceURI(),
     488                reader.getLocalName());
     489
     490        if ((reader.getPrefix() != null) && !reader.getPrefix().isEmpty()) {
     491            element.setPrefix(reader.getPrefix());
     492        }
     493
     494        parent.appendChild(element);
     495
     496        // add namespace declarations
     497        for (int i = 0; i < reader.getNamespaceCount(); i++) {
     498            final String uri    = reader.getNamespaceURI(i);
     499            final String prefix = reader.getNamespacePrefix(i);
     500
     501            if ((prefix != null) && !prefix.isEmpty()) {
     502                element.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI,
     503                        XMLConstants.XMLNS_ATTRIBUTE + ":" + prefix,
     504                        uri);
     505            } else {
     506                if (uri != null) {
     507                    element.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI,
     508                            XMLConstants.XMLNS_ATTRIBUTE,
     509                            uri);
     510                }
     511            }
     512        }
     513
     514        // add other attributes
     515        for (int i = 0; i < reader.getAttributeCount(); i++) {
     516            String name   = reader.getAttributeLocalName(i);
     517            String prefix = reader.getAttributePrefix(i);
     518            if (prefix != null && prefix.length() > 0) {
     519                name = prefix + ":" + name;
     520            }
     521
     522            Attr attr = doc.createAttributeNS(
     523                    reader.getAttributeNamespace(i), name);
     524            attr.setValue(reader.getAttributeValue(i));
     525            element.setAttributeNode(attr);
     526        }
     527        return element;
     528    }
     529
    391530} // class SRUClient
  • SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUExplainResponse.java

    r2203 r2204  
    1919import java.util.List;
    2020
    21 import org.w3c.dom.Document;
     21import org.w3c.dom.DocumentFragment;
    2222
    2323
     
    3232
    3333    SRUExplainResponse(SRUExplainRequest request,
    34             List<SRUDiagnostic> diagnostics, Document extraResponseData,
    35             int totalBytesTransferred, long timeTotal, long timeQueued,
    36             long timeNetwork, long timeProcessing, SRURecord record) {
     34            List<SRUDiagnostic> diagnostics,
     35            DocumentFragment extraResponseData,
     36            int totalBytesTransferred,
     37            long timeTotal,
     38            long timeQueued,
     39            long timeNetwork,
     40            long timeProcessing,
     41            SRURecord record) {
    3742        super(request, diagnostics, extraResponseData, totalBytesTransferred,
    3843                timeTotal, timeQueued, timeNetwork, timeProcessing);
  • SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRURecord.java

    r2168 r2204  
    1717package eu.clarin.sru.client;
    1818
    19 import org.w3c.dom.Document;
     19import org.w3c.dom.DocumentFragment;
    2020
    2121
    2222/**
    2323 * Class for holding a single record from a result set.
    24  * 
     24 *
    2525 * @see SRUSearchRetrieveResponse
    2626 */
     
    2929    private final String recordIdentifier;
    3030    private final int recordPosition;
    31     private final Document extraRecordData;
     31    private DocumentFragment extraRecordData = null;
    3232
    3333
    3434    SRURecord(SRURecordData recordData, String recordIdentifier,
    35             int recordPosition, Document extraRecordData) {
     35            int recordPosition) {
    3636        if (recordData == null) {
    3737            throw new NullPointerException("recordData == null");
     
    4040        this.recordIdentifier = recordIdentifier;
    4141        this.recordPosition = recordPosition;
    42         this.extraRecordData = extraRecordData;
    4342    }
    4443
     
    5655    /**
    5756     * Check if this record is in a certain record schema.
    58      * 
     57     *
    5958     * @param recordSchema
    6059     *            the record schema to test against
     
    7473    /**
    7574     * Get the record.
    76      * 
     75     *
    7776     * @return the record
    7877     */
     
    106105     * Get extra record data attached to this record.
    107106     *
    108      * @return get the extra record data or <code>null</code> if not available
     107     * @return get an instance of {@link DocumentFragment} containing the XML
     108     *         fragment for the extra record data from the SRU response or
     109     *         <code>null</code> if none are available
    109110     */
    110     public Document getExtraRecordData() {
     111    public DocumentFragment getExtraRecordData() {
    111112        return extraRecordData;
    112113    }
    113114
     115
     116    /**
     117     * Check, if this record has extra record data attached to it.
     118     *
     119     * @return <code>true</code> if extra record data is attached,
     120     *         <code>false</code> otherwise
     121     */
     122    public boolean hasExtraRecordData() {
     123        return extraRecordData != null;
     124    }
     125
     126
     127    void setExtraRecordData(DocumentFragment extraRecordData) {
     128        this.extraRecordData = extraRecordData;
     129    }
     130
    114131} // class SRURecord
  • SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUScanResponse.java

    r2203 r2204  
    2020import java.util.List;
    2121
    22 import org.w3c.dom.Document;
     22import org.w3c.dom.DocumentFragment;
    2323
    2424
     
    3131
    3232
    33     SRUScanResponse(SRUScanRequest request, List<SRUDiagnostic> diagnostics,
    34             Document extraResponseData, int totalBytesTransferred,
    35             long timeTotal, long timeQueued, long timeNetwork,
    36             long timeProcessing, List<SRUTerm> terms) {
     33    SRUScanResponse(SRUScanRequest request,
     34            List<SRUDiagnostic> diagnostics,
     35            DocumentFragment extraResponseData,
     36            int totalBytesTransferred,
     37            long timeTotal,
     38            long timeQueued,
     39            long timeNetwork,
     40            long timeProcessing,
     41            List<SRUTerm> terms) {
    3742        super(request, diagnostics, extraResponseData, totalBytesTransferred,
    3843                timeTotal, timeQueued, timeNetwork, timeProcessing);
  • SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUSearchRetrieveResponse.java

    r2203 r2204  
    2020import java.util.List;
    2121
    22 import org.w3c.dom.Document;
     22import org.w3c.dom.DocumentFragment;
    2323
    2424
     
    3737
    3838    SRUSearchRetrieveResponse(SRUSearchRetrieveRequest request,
    39             List<SRUDiagnostic> diagnostics, Document extraResponseData,
    40             int totalBytesTransferred, long timeTotal, long timeQueued,
    41             long timeNetwork, long timeParsing, int numberOfRecords,
    42             String resultSetId, int resultSetIdleTime, List<SRURecord> records,
     39            List<SRUDiagnostic> diagnostics,
     40            DocumentFragment extraResponseData,
     41            int totalBytesTransferred,
     42            long timeTotal,
     43            long timeQueued,
     44            long timeNetwork,
     45            long timeParsing,
     46            int numberOfRecords,
     47            String resultSetId,
     48            int resultSetIdleTime,
     49            List<SRURecord> records,
    4350            int nextRecordPosition) {
    4451        super(request, diagnostics, extraResponseData, totalBytesTransferred,
  • SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUTerm.java

    r2168 r2204  
    1717package eu.clarin.sru.client;
    1818
    19 import org.w3c.dom.Document;
     19import org.w3c.dom.DocumentFragment;
    2020
    2121
     
    3030    private final String displayTerm;
    3131    private final SRUWhereInList whereInList;
    32     private final Document extraTermData;
     32    private DocumentFragment extraTermData = null;
    3333
    3434
     
    4444     * @param whereInList
    4545     *            flag or <code>null</code>
    46      * @param extraTermData
    47      *            extra term data or <code>null</code>
    4846     */
    4947    SRUTerm(String value, int numberOfRecords, String displayTerm,
    50             SRUWhereInList whereInList, Document extraTermData) {
     48            SRUWhereInList whereInList) {
    5149        if (value == null) {
    5250            throw new NullPointerException("value == null");
     
    5654        this.displayTerm = displayTerm;
    5755        this.whereInList = whereInList;
    58         this.extraTermData = extraTermData;
    59 
    6056    }
    6157
     
    10399
    104100    /**
    105      * Get additional information concerning the term.
     101     * Get extra term data for this term.
    106102     *
    107      * @return the extra term data or <code>null</code> if none where supplied
     103     * @return get an instance of {@link DocumentFragment} containing the XML
     104     *         fragment for the extra term data from the SRU response or
     105     *         <code>null</code> if none are available
    108106     */
    109     public Document getExtraTermData() {
     107    public DocumentFragment getExtraTermData() {
    110108        return extraTermData;
    111109    }
    112110
     111
     112    /**
     113     * Check, if this term has extra term data attached to it.
     114     *
     115     * @return <code>true</code> if extra term data is attached,
     116     *         <code>false</code> otherwise
     117     */
     118    public boolean hasExtraTermData() {
     119        return extraTermData != null;
     120    }
     121
     122    void setExtraTermData(DocumentFragment extraTermData) {
     123        this.extraTermData = extraTermData;
     124    }
     125
    113126} // class SRUTerm
  • SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUThreadedClient.java

    r2203 r2204  
    2525import java.util.concurrent.ThreadFactory;
    2626
     27import javax.xml.parsers.DocumentBuilderFactory;
     28
    2729import org.slf4j.Logger;
    2830import org.slf4j.LoggerFactory;
     
    4143    private static final Logger logger =
    4244            LoggerFactory.getLogger(SRUThreadedClient.class);
    43     private ConcurrentMap<String, SRURecordDataParser> parsers =
     45    private final ConcurrentMap<String, SRURecordDataParser> parsers =
    4446            new ConcurrentHashMap<String, SRURecordDataParser>();
     47    private final DocumentBuilderFactory documentBuilderFactory =
     48            DocumentBuilderFactory.newInstance();
    4549    private final ThreadLocal<SRUClient> client;
    4650    private final ExecutorService executor;
     
    9094            protected SRUClient initialValue() {
    9195                logger.debug("instantiated new sru client");
    92                 return new SRUClient(defaultVersion, strictMode, parsers);
     96                return new SRUClient(defaultVersion, strictMode, parsers,
     97                        documentBuilderFactory);
    9398            }
    9499        };
     
    439444                }
    440445            } catch (Throwable t) {
    441                 logger.error("error while performing async callback", t);
     446                callback.onError(request, new SRUClientException(
     447                        "unexpected error while processing the request", t));
    442448            }
    443449        }
Note: See TracChangeset for help on using the changeset viewer.