001: /*
002: * Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2007.
003: *
004: * Licensed under the Aduna BSD-style license.
005: */
006: package org.openrdf.query.resultio.sparqlxml;
007:
008: import static org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLConstants.BINDING_NAME_ATT;
009: import static org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLConstants.BINDING_TAG;
010: import static org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLConstants.BNODE_TAG;
011: import static org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLConstants.LITERAL_DATATYPE_ATT;
012: import static org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLConstants.LITERAL_LANG_ATT;
013: import static org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLConstants.LITERAL_TAG;
014: import static org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLConstants.RESULT_SET_TAG;
015: import static org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLConstants.RESULT_TAG;
016: import static org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLConstants.URI_TAG;
017: import static org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLConstants.VAR_NAME_ATT;
018: import static org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLConstants.VAR_TAG;
019:
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.util.ArrayList;
023: import java.util.List;
024: import java.util.Map;
025:
026: import org.xml.sax.SAXException;
027:
028: import info.aduna.xml.SimpleSAXAdapter;
029: import info.aduna.xml.SimpleSAXParser;
030: import info.aduna.xml.XMLReaderFactory;
031:
032: import org.openrdf.model.Value;
033: import org.openrdf.model.ValueFactory;
034: import org.openrdf.model.impl.ValueFactoryImpl;
035: import org.openrdf.query.TupleQueryResultHandlerException;
036: import org.openrdf.query.impl.MapBindingSet;
037: import org.openrdf.query.resultio.QueryResultParseException;
038: import org.openrdf.query.resultio.TupleQueryResultFormat;
039: import org.openrdf.query.resultio.TupleQueryResultParserBase;
040:
041: /**
042: * Parser for reading tuple query results formatted as SPARQL Results Documents.
043: * See <a href="http://www.w3.org/TR/rdf-sparql-XMLres/">SPARQL Query Results
044: * XML Format</a> for the definition of this format. The parser assumes that
045: * the XML is wellformed.
046: */
047: public class SPARQLResultsXMLParser extends TupleQueryResultParserBase {
048:
049: /*-------------*
050: * Construtors *
051: *-------------*/
052:
053: /**
054: * Creates a new parser for the SPARQL Query Results XML Format that will use
055: * an instance of {@link ValueFactoryImpl} to create Value objects.
056: */
057: public SPARQLResultsXMLParser() {
058: super ();
059: }
060:
061: /**
062: * Creates a new parser for the SPARQL Query Results XML Format that will use
063: * the supplied ValueFactory to create Value objects.
064: */
065: public SPARQLResultsXMLParser(ValueFactory valueFactory) {
066: super (valueFactory);
067: }
068:
069: /*---------*
070: * Methods *
071: *---------*/
072:
073: public TupleQueryResultFormat getTupleQueryResultFormat() {
074: return TupleQueryResultFormat.SPARQL;
075: }
076:
077: public void parse(InputStream in) throws IOException,
078: QueryResultParseException, TupleQueryResultHandlerException {
079: try {
080: SimpleSAXParser simpleSAXParser = new SimpleSAXParser(
081: XMLReaderFactory.createXMLReader());
082:
083: simpleSAXParser.setListener(new SPARQLResultsParser());
084:
085: simpleSAXParser.parse(in);
086: } catch (SAXException e) {
087: Exception wrappedExc = e.getException();
088:
089: if (wrappedExc instanceof QueryResultParseException) {
090: throw (QueryResultParseException) wrappedExc;
091: } else if (wrappedExc instanceof TupleQueryResultHandlerException) {
092: throw (TupleQueryResultHandlerException) wrappedExc;
093: } else {
094: throw new QueryResultParseException(wrappedExc);
095: }
096: }
097: }
098:
099: /*---------------------------------*
100: * Inner class SPARQLResultsParser *
101: *---------------------------------*/
102:
103: private class SPARQLResultsParser extends SimpleSAXAdapter {
104:
105: /*-----------*
106: * Variables *
107: *-----------*/
108:
109: /**
110: * The variable names that are specified in the header.
111: */
112: private List<String> bindingNames;
113:
114: /**
115: * The most recently parsed binding name.
116: */
117: private String currentBindingName;
118:
119: /**
120: * The most recently parsed value.
121: */
122: private Value currentValue;
123:
124: /**
125: * The bound variables for the current result.
126: */
127: private MapBindingSet currentSolution;
128:
129: /*---------*
130: * Methods *
131: *---------*/
132:
133: @Override
134: public void startDocument() throws SAXException {
135: bindingNames = new ArrayList<String>();
136: currentValue = null;
137: }
138:
139: @Override
140: public void endDocument() throws SAXException {
141: try {
142: handler.endQueryResult();
143: } catch (TupleQueryResultHandlerException e) {
144: throw new SAXException(e);
145: }
146: }
147:
148: @Override
149: public void startTag(String tagName, Map<String, String> atts,
150: String text) throws SAXException {
151: if (BINDING_TAG.equals(tagName)) {
152: currentBindingName = atts.get(BINDING_NAME_ATT);
153:
154: if (currentBindingName == null) {
155: throw new SAXException(BINDING_NAME_ATT
156: + " attribute missing for " + BINDING_TAG
157: + " element");
158: }
159: } else if (URI_TAG.equals(tagName)) {
160: try {
161: currentValue = valueFactory.createURI(text);
162: } catch (IllegalArgumentException e) {
163: // Malformed URI
164: throw new SAXException(e.getMessage());
165: }
166: } else if (BNODE_TAG.equals(tagName)) {
167: currentValue = valueFactory.createBNode(text);
168: } else if (LITERAL_TAG.equals(tagName)) {
169: String xmlLang = atts.get(LITERAL_LANG_ATT);
170: String datatype = atts.get(LITERAL_DATATYPE_ATT);
171:
172: if (datatype != null) {
173: try {
174: currentValue = valueFactory.createLiteral(text,
175: valueFactory.createURI(datatype));
176: } catch (IllegalArgumentException e) {
177: // Illegal datatype URI
178: throw new SAXException(e.getMessage());
179: }
180: } else if (xmlLang != null) {
181: currentValue = valueFactory.createLiteral(text,
182: xmlLang);
183: } else {
184: currentValue = valueFactory.createLiteral(text);
185: }
186: } else if (RESULT_TAG.equals(tagName)) {
187: currentSolution = new MapBindingSet(bindingNames.size());
188: } else if (VAR_TAG.equals(tagName)) {
189: String varName = atts.get(VAR_NAME_ATT);
190:
191: if (varName == null) {
192: throw new SAXException(VAR_NAME_ATT
193: + " missing for " + VAR_TAG + " element");
194: }
195:
196: bindingNames.add(varName);
197: } else if (RESULT_SET_TAG.equals(tagName)) {
198: try {
199: handler.startQueryResult(bindingNames);
200: } catch (TupleQueryResultHandlerException e) {
201: throw new SAXException(e);
202: }
203: }
204: }
205:
206: @Override
207: public void endTag(String tagName) throws SAXException {
208: if (BINDING_TAG.equals(tagName)) {
209: if (currentValue == null) {
210: throw new SAXException("Value missing for "
211: + BINDING_TAG + " element");
212: }
213:
214: currentSolution.addBinding(currentBindingName,
215: currentValue);
216:
217: currentBindingName = null;
218: currentValue = null;
219: } else if (RESULT_TAG.equals(tagName)) {
220: try {
221: handler.handleSolution(currentSolution);
222: currentSolution = null;
223: } catch (TupleQueryResultHandlerException e) {
224: throw new SAXException(e);
225: }
226: }
227: }
228: }
229: }
|