Source code: nl/aidministrator/rdf/client/rql/RqlQueryResultParser.java
1 /* Sesame - Storage and Querying architecture for RDF and RDF Schema
2 * Copyright (C) 2002 Aidministrator Nederland b.v.
3 *
4 * Contact:
5 * Aidministrator Nederland b.v.
6 * Julianaplein 14b
7 * 3817 CS Amersfoort
8 * The Netherlands
9 * tel. +31(0)33 4659987
10 * fax. +31(0)33 4659987
11 * sesame@aidministrator.nl
12 *
13 * http://www.aidministrator.nl/
14 *
15 * This library is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU Lesser General Public
17 * License as published by the Free Software Foundation; either
18 * version 2.1 of the License, or (at your option) any later version.
19 *
20 * This library is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * Lesser General Public License for more details.
24 *
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 */
29
30 package nl.aidministrator.rdf.client.rql;
31
32 import nl.aidministrator.rdf.client.model.*;
33
34 import org.xml.sax.*;
35
36 /**
37 * Parser for parsing the query results from RQL queries. This parser
38 * is used by the SesameProxy. This is a SAX-based parser. An RDF triples
39 * based parser would have been nicer but is more difficult to implement
40 * as there are no guarantees for the order in which an RDF parser reports
41 * statements.
42 **/
43 public class RqlQueryResultParser implements ContentHandler {
44
45 /*---------------------------------------+
46 | Variables |
47 +---------------------------------------*/
48
49 /** The object to report the query results to. **/
50 private QueryResultListener _listener;
51
52 /**
53 * Buffer used to store characters reported in consecutive calls
54 * to characters().
55 **/
56 private StringBuffer _chars = new StringBuffer();
57
58 /**
59 * The depth of current XML element in the XML tree.
60 **/
61 private int _xmlTreeDepth = 0;
62
63 /**
64 * Optional value of an "xml:lang" attribute for literal values.
65 **/
66 private String _xmlLang;
67
68 /**
69 * Variable used to build an Intersection result over multiple calls
70 * to startElement().
71 **/
72 private Intersection _intersect;
73
74 /**
75 * Flag indicating whether a value has parsed for the current rdf:li
76 * element. When no value has been parsed yet when the end element for
77 * rdf:li is reported, the value should be an empty string.
78 **/
79 private boolean _tupleValueParsed = false;
80
81 /*---------------------------------------+
82 | Constructors |
83 +---------------------------------------*/
84
85 public RqlQueryResultParser(QueryResultListener list) {
86 _listener = list;
87 }
88
89 /*--------------------------------------------------+
90 | Methods from interface org.xml.sax.ContentHandler |
91 +--------------------------------------------------*/
92
93 public void characters(char ch[], int start, int length) {
94 _chars.append(ch, start, length);
95 }
96
97 public void startElement(String ns, String lName, String qName, Attributes atts) {
98 if (_xmlTreeDepth == 3) { // <rdf:Seq>, start of tuple
99 _listener.startTuple();
100 }
101 else if (_xmlTreeDepth == 4) { // <rdf:li> with possibly a URI
102 String uri = atts.getValue("rdf:resource");
103 if (uri != null) {
104 _listener.tupleValue( new Resource(uri) );
105 _tupleValueParsed = true;
106 }
107 else {
108 // atts might contain xml:lang for literal
109 _xmlLang = atts.getValue("xml:lang");
110 }
111 }
112 else if (_xmlTreeDepth == 5) { // tupleValue is an Intersection
113 _intersect = new Intersection();
114 }
115 else if (_xmlTreeDepth == 6) { // intersection member in <rdf:li>
116 String uri = atts.getValue("rdf:resource");
117 _intersect.add( new Resource(uri) );
118 }
119
120 _xmlTreeDepth++;
121 }
122
123 public void endElement(String ns, String lName, String qName) {
124 _xmlTreeDepth--;
125
126 if (_xmlTreeDepth == 3) { // </rdf:Seq>, end of tuple
127 _listener.endTuple();
128 }
129 else if (_xmlTreeDepth == 4) { // </rdf:li> with possibly a text value
130 if (!_tupleValueParsed) {
131 String value = _chars.toString().trim();
132 _listener.tupleValue( new Literal(value, _xmlLang) );
133 }
134
135 _xmlLang = null;
136 _tupleValueParsed = false;
137 }
138 else if (_xmlTreeDepth == 5) { // end of intersection
139 _listener.tupleValue(_intersect);
140 _intersect = null;
141 _tupleValueParsed = true;
142 }
143
144 _chars.setLength(0);
145 }
146
147 public void ignorableWhitespace(char[] ch, int start, int length) {
148 //ignore
149 }
150
151 public void startDocument() {
152 // ignore
153 }
154
155 public void endDocument() {
156 // ignore
157 }
158
159 public void setDocumentLocator(Locator locator) {
160 //ignore
161 }
162
163 public void startPrefixMapping(String prefix, String uri) {
164 //ignore
165 }
166
167 public void endPrefixMapping(String prefix) {
168 //ignore
169 }
170
171 public void skippedEntity(String name) {
172 //ignore
173 }
174
175 public void processingInstruction(String target, String data) {
176 //ignore
177 }
178 }