1 package eu.fbk.knowledgestore.triplestore;
2
3 import java.io.ObjectStreamException;
4 import java.io.Serializable;
5
6 import javax.annotation.Nullable;
7
8 import com.google.common.base.Objects;
9 import com.google.common.base.Preconditions;
10 import com.google.common.cache.Cache;
11 import com.google.common.cache.CacheBuilder;
12
13 import org.openrdf.model.Value;
14 import org.openrdf.query.BindingSet;
15 import org.openrdf.query.Dataset;
16 import org.openrdf.query.MalformedQueryException;
17 import org.openrdf.query.QueryLanguage;
18 import org.openrdf.query.algebra.TupleExpr;
19 import org.openrdf.query.algebra.Var;
20 import org.openrdf.query.algebra.helpers.QueryModelVisitorBase;
21 import org.openrdf.query.parser.ParsedTupleQuery;
22 import org.openrdf.query.parser.QueryParserUtil;
23
24 import eu.fbk.knowledgestore.data.ParseException;
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 public final class SelectQuery implements Serializable {
55
56
57 private static final long serialVersionUID = -3361485014094610488L;
58
59
60
61
62
63 private static final Cache<String, SelectQuery> CACHE = CacheBuilder.newBuilder().softValues()
64 .build();
65
66
67 private final String string;
68
69
70 private final TupleExpr expression;
71
72
73 @Nullable
74 private final Dataset dataset;
75
76
77
78
79
80
81
82
83
84
85 public static SelectQuery from(final String string) throws ParseException {
86
87 Preconditions.checkNotNull(string);
88
89 SelectQuery query = CACHE.getIfPresent(string);
90 if (query == null) {
91 final ParsedTupleQuery parsedQuery;
92 try {
93 parsedQuery = QueryParserUtil.parseTupleQuery(QueryLanguage.SPARQL, string, null);
94 } catch (final IllegalArgumentException ex) {
95 throw new ParseException(string, "SPARQL query not in SELECT form", ex);
96 } catch (final MalformedQueryException ex) {
97 throw new ParseException(string, "Invalid SPARQL query: " + ex.getMessage(), ex);
98 }
99 query = new SelectQuery(string, parsedQuery.getTupleExpr(), parsedQuery.getDataset());
100 CACHE.put(string, query);
101 }
102 return query;
103 }
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118 public static SelectQuery from(final TupleExpr expression, @Nullable final Dataset dataset)
119 throws ParseException {
120
121 Preconditions.checkNotNull(expression);
122
123 try {
124
125 final String string = new SPARQLRenderer(null, true).render(expression, dataset);
126 SelectQuery query = CACHE.getIfPresent(string);
127 if (query == null) {
128 query = new SelectQuery(string, expression, dataset);
129 CACHE.put(string, query);
130 }
131 return query;
132
133 } catch (final Exception ex) {
134 throw new ParseException(expression.toString(),
135 "The supplied algebraic expression does not denote a valid SPARQL query", ex);
136 }
137 }
138
139
140
141
142
143
144
145
146
147
148
149 private SelectQuery(final String string, final TupleExpr expression,
150 @Nullable final Dataset dataset) {
151 this.string = string;
152 this.expression = expression;
153 this.dataset = dataset;
154 }
155
156
157
158
159
160
161
162 public String getString() {
163 return this.string;
164 }
165
166
167
168
169
170
171
172
173
174 public TupleExpr getExpression() {
175 return this.expression;
176 }
177
178
179
180
181
182
183
184 @Nullable
185 public Dataset getDataset() {
186 return this.dataset;
187 }
188
189
190
191
192
193
194
195
196
197
198
199 public SelectQuery replaceDataset(@Nullable final Dataset dataset) {
200 if (Objects.equal(this.dataset, dataset)) {
201 return this;
202 } else {
203 try {
204 return from(this.expression, dataset);
205 } catch (final ParseException ex) {
206 throw new Error("Unexpected error - replacing dataset made the query invalid (!)",
207 ex);
208 }
209 }
210 }
211
212
213
214
215
216
217
218
219
220
221 public SelectQuery replaceVariables(final BindingSet bindings) {
222
223 if (bindings.size() == 0) {
224 return this;
225 }
226
227
228
229 final TupleExpr newExpression = this.expression.clone();
230 newExpression.visit(new QueryModelVisitorBase<RuntimeException>() {
231
232 @Override
233 public void meet(final Var var) {
234 if (!var.hasValue() && bindings.hasBinding(var.getName())) {
235 final Value value = bindings.getValue(var.getName());
236 var.setValue(value);
237 }
238 }
239
240 });
241
242 try {
243 return from(newExpression, this.dataset);
244 } catch (final ParseException ex) {
245 throw new Error("Unexpected error - replacing variables made the query invalid (!)",
246 ex);
247 }
248 }
249
250
251
252
253 @Override
254 public boolean equals(final Object object) {
255 if (object == this) {
256 return true;
257 }
258 if (!(object instanceof SelectQuery)) {
259 return false;
260 }
261 final SelectQuery other = (SelectQuery) object;
262 return this.string.equals(other.string);
263 }
264
265
266
267
268 @Override
269 public int hashCode() {
270 return this.string.hashCode();
271 }
272
273
274
275
276 @Override
277 public String toString() {
278 return this.string;
279 }
280
281 private Object writeReplace() throws ObjectStreamException {
282 return new SerializedForm(this.string);
283 }
284
285 private static final class SerializedForm {
286
287 private final String string;
288
289 SerializedForm(final String string) {
290 this.string = string;
291 }
292
293 private Object readResolve() throws ObjectStreamException {
294 SelectQuery query = CACHE.getIfPresent(this.string);
295 if (query == null) {
296 try {
297 query = SelectQuery.from(this.string);
298 } catch (final ParseException ex) {
299 throw new Error("Serialized form denotes an invalid SPARQL queries (!)", ex);
300 }
301 }
302 return query;
303 }
304
305 }
306
307 }