View Javadoc

1   /*
2    * Copyright James Leigh (c) 2007.
3    *
4    * Licensed under the Aduna BSD-style license.
5    */
6   package org.openrdf.query.parser.serqo;
7   
8   import java.lang.reflect.UndeclaredThrowableException;
9   import java.util.Iterator;
10  import java.util.List;
11  import java.util.Map;
12  
13  import org.openrdf.model.Resource;
14  import org.openrdf.model.Statement;
15  import org.openrdf.model.URI;
16  import org.openrdf.model.Value;
17  import org.openrdf.model.ValueFactory;
18  import org.openrdf.model.impl.ValueFactoryImpl;
19  import org.openrdf.model.vocabulary.RDF;
20  import org.openrdf.query.algebra.And;
21  import org.openrdf.query.algebra.BNodeGenerator;
22  import org.openrdf.query.algebra.BinaryTupleOperator;
23  import org.openrdf.query.algebra.BinaryValueOperator;
24  import org.openrdf.query.algebra.Compare;
25  import org.openrdf.query.algebra.CompareAll;
26  import org.openrdf.query.algebra.CompareAny;
27  import org.openrdf.query.algebra.CompareSubQueryValueOperator;
28  import org.openrdf.query.algebra.Count;
29  import org.openrdf.query.algebra.Datatype;
30  import org.openrdf.query.algebra.Difference;
31  import org.openrdf.query.algebra.Distinct;
32  import org.openrdf.query.algebra.EmptySet;
33  import org.openrdf.query.algebra.Exists;
34  import org.openrdf.query.algebra.Extension;
35  import org.openrdf.query.algebra.ExtensionElem;
36  import org.openrdf.query.algebra.Filter;
37  import org.openrdf.query.algebra.FunctionCall;
38  import org.openrdf.query.algebra.Group;
39  import org.openrdf.query.algebra.GroupElem;
40  import org.openrdf.query.algebra.In;
41  import org.openrdf.query.algebra.Intersection;
42  import org.openrdf.query.algebra.IsBNode;
43  import org.openrdf.query.algebra.IsLiteral;
44  import org.openrdf.query.algebra.IsResource;
45  import org.openrdf.query.algebra.IsURI;
46  import org.openrdf.query.algebra.Join;
47  import org.openrdf.query.algebra.Label;
48  import org.openrdf.query.algebra.Lang;
49  import org.openrdf.query.algebra.LangMatches;
50  import org.openrdf.query.algebra.LeftJoin;
51  import org.openrdf.query.algebra.Like;
52  import org.openrdf.query.algebra.LocalName;
53  import org.openrdf.query.algebra.MathExpr;
54  import org.openrdf.query.algebra.Max;
55  import org.openrdf.query.algebra.Min;
56  import org.openrdf.query.algebra.MultiProjection;
57  import org.openrdf.query.algebra.Namespace;
58  import org.openrdf.query.algebra.Not;
59  import org.openrdf.query.algebra.Or;
60  import org.openrdf.query.algebra.Order;
61  import org.openrdf.query.algebra.OrderElem;
62  import org.openrdf.query.algebra.Projection;
63  import org.openrdf.query.algebra.ProjectionElem;
64  import org.openrdf.query.algebra.ProjectionElemList;
65  import org.openrdf.query.algebra.QueryModelNode;
66  import org.openrdf.query.algebra.QueryRoot;
67  import org.openrdf.query.algebra.Regex;
68  import org.openrdf.query.algebra.SameTerm;
69  import org.openrdf.query.algebra.SingletonSet;
70  import org.openrdf.query.algebra.Slice;
71  import org.openrdf.query.algebra.StatementPattern;
72  import org.openrdf.query.algebra.Str;
73  import org.openrdf.query.algebra.SubQueryValueOperator;
74  import org.openrdf.query.algebra.UnaryTupleOperator;
75  import org.openrdf.query.algebra.UnaryValueOperator;
76  import org.openrdf.query.algebra.Union;
77  import org.openrdf.query.algebra.ValueConstant;
78  import org.openrdf.query.algebra.Var;
79  import org.openrdf.query.algebra.helpers.QueryModelVisitorBase;
80  import org.openrdf.query.parser.ParsedGraphQuery;
81  import org.openrdf.query.parser.ParsedTupleQuery;
82  import org.openrdf.rio.RDFHandler;
83  import org.openrdf.rio.RDFHandlerException;
84  
85  /**
86   * Converts Query Object into RDF Statements.
87   * 
88   * @author James Leigh
89   */
90  public class SeRQOBuilder extends QueryModelVisitorBase<RuntimeException> {
91  
92  	private static final URI[] members = new URI[256];
93  	static {
94  		ValueFactory vf = ValueFactoryImpl.getInstance();
95  		for (int i = 0; i < members.length; i++) {
96  			members[i] = vf.createURI(RDF.NAMESPACE + "_" + (i + 1));
97  		}
98  	}
99  
100 	private RDFHandler rdf;
101 
102 	private Resource subject;
103 
104 	private ValueFactory vf;
105 
106 	public RDFHandler getRDFHandler() {
107 		return rdf;
108 	}
109 
110 	public void setRDFHandler(RDFHandler rdfHandler) {
111 		this.rdf = rdfHandler;
112 	}
113 
114 	public ValueFactory getValueFactory() {
115 		return vf;
116 	}
117 
118 	public void setValueFactory(ValueFactory valueFactory) {
119 		this.vf = valueFactory;
120 	}
121 
122 	public void handleGraphQuery(ParsedGraphQuery query) {
123 		try {
124 			init();
125 			Map<String, String> ns = query.getQueryNamespaces();
126 			for (Map.Entry<String, String> e : ns.entrySet()) {
127 				rdf.handleNamespace(e.getKey(), e.getValue());
128 			}
129 			subject = vf.createBNode();
130 			handleType(SeRQO.GRAPHQUERY);
131 			handleChild(SeRQO.TUPLEEXPR, query.getTupleExpr());
132 			rdf.endRDF();
133 		} catch (RDFHandlerException e) {
134 			throw new UndeclaredThrowableException(e);
135 		}
136 	}
137 
138 	public void handleTupleQuery(ParsedTupleQuery query) {
139 		try {
140 			init();
141 			subject = vf.createBNode();
142 			handleType(SeRQO.TUPLEQUERY);
143 			handleChild(SeRQO.TUPLEEXPR, query.getTupleExpr());
144 			rdf.endRDF();
145 		} catch (RDFHandlerException e) {
146 			throw new UndeclaredThrowableException(e);
147 		}
148 	}
149 
150 	@Override
151 	public void meet(QueryRoot node) {
152 		handleType(SeRQO.QUERYROOT);
153 		super.meet(node);
154 	}
155 
156 	@Override
157 	public void meet(And node) {
158 		handleType(SeRQO.AND);
159 		super.meet(node);
160 	}
161 
162 	@Override
163 	public void meet(BNodeGenerator node) {
164 		handleType(SeRQO.BNODEGENERATOR);
165 		super.meet(node);
166 	}
167 
168 	@Override
169 	public void meet(Compare node) {
170 		handleType(SeRQO.COMPARE);
171 		handleLiteral(SeRQO.OPERATOR, node.getOperator().name());
172 		super.meet(node);
173 	}
174 
175 	@Override
176 	public void meet(CompareAll node) {
177 		handleType(SeRQO.COMPAREALL);
178 		handleLiteral(SeRQO.OPERATOR, node.getOperator().name());
179 		super.meet(node);
180 	}
181 
182 	@Override
183 	public void meet(CompareAny node) {
184 		handleType(SeRQO.COMPAREANY);
185 		handleLiteral(SeRQO.OPERATOR, node.getOperator().name());
186 		super.meet(node);
187 	}
188 
189 	@Override
190 	public void meet(Count node) {
191 		handleType(SeRQO.COUNT);
192 		super.meet(node);
193 	}
194 
195 	@Override
196 	public void meet(Datatype node) {
197 		handleType(SeRQO.DATATYPE);
198 		super.meet(node);
199 	}
200 
201 	@Override
202 	public void meet(Difference node) {
203 		handleType(SeRQO.DIFFERENCE);
204 		super.meet(node);
205 	}
206 
207 	@Override
208 	public void meet(Distinct node) {
209 		handleType(SeRQO.DISTINCT);
210 		super.meet(node);
211 	}
212 
213 	@Override
214 	public void meet(EmptySet node) {
215 		handleType(SeRQO.EMPTYSET);
216 		super.meet(node);
217 	}
218 
219 	@Override
220 	public void meet(Exists node) {
221 		handleType(SeRQO.EXISTS);
222 		super.meet(node);
223 	}
224 
225 	@Override
226 	public void meet(Extension node) {
227 		handleType(SeRQO.EXTENSION);
228 		handleChildList(SeRQO.ELEMENTS, node.getElements());
229 		super.meet(node);
230 	}
231 
232 	@Override
233 	public void meet(ExtensionElem node) {
234 		handleType(SeRQO.EXTENSIONELEM);
235 		handleLiteral(SeRQO.NAME, node.getName());
236 		handleChild(SeRQO.ARG, node.getExpr());
237 		super.meet(node);
238 	}
239 
240 	@Override
241 	public void meet(FunctionCall node) {
242 		handleType(SeRQO.FUNCTIONCALL);
243 		handleLiteral(SeRQO.URI, node.getURI());
244 		handleChildList(SeRQO.ARGS, node.getArgs());
245 		super.meet(node);
246 	}
247 
248 	@Override
249 	public void meet(Group node) {
250 		handleType(SeRQO.GROUP);
251 		handleLiteralList(SeRQO.GROUPNAMES, node.getGroupBindingNames());
252 		handleChildList(SeRQO.ELEMENTS, node.getGroupElements());
253 		super.meet(node);
254 	}
255 
256 	@Override
257 	public void meet(GroupElem node) {
258 		handleType(SeRQO.GROUPELEM);
259 		handleLiteral(SeRQO.NAME, node.getName());
260 		handleChild(SeRQO.OPERATOR, node.getOperator());
261 		super.meet(node);
262 	}
263 
264 	@Override
265 	public void meet(In node) {
266 		handleType(SeRQO.IN);
267 		super.meet(node);
268 	}
269 
270 	@Override
271 	public void meet(Intersection node) {
272 		handleType(SeRQO.INTERSECTION);
273 		super.meet(node);
274 	}
275 
276 	@Override
277 	public void meet(IsBNode node) {
278 		handleType(SeRQO.ISBNODE);
279 		super.meet(node);
280 	}
281 
282 	@Override
283 	public void meet(IsLiteral node) {
284 		handleType(SeRQO.ISLITERAL);
285 		super.meet(node);
286 	}
287 
288 	@Override
289 	public void meet(IsResource node) {
290 		handleType(SeRQO.ISRESOURCE);
291 		super.meet(node);
292 	}
293 
294 	@Override
295 	public void meet(IsURI node) {
296 		handleType(SeRQO.ISURI);
297 		super.meet(node);
298 	}
299 
300 	@Override
301 	public void meet(Join node) {
302 		handleType(SeRQO.JOIN);
303 		super.meet(node);
304 	}
305 
306 	@Override
307 	public void meet(Label node) {
308 		handleType(SeRQO.LABEL);
309 		super.meet(node);
310 	}
311 
312 	@Override
313 	public void meet(Lang node) {
314 		handleType(SeRQO.LANG);
315 		super.meet(node);
316 	}
317 
318 	@Override
319 	public void meet(LangMatches node) {
320 		handleType(SeRQO.LANGMATCHES);
321 		super.meet(node);
322 	}
323 
324 	@Override
325 	public void meet(Like node) {
326 		handleType(SeRQO.LIKE);
327 		handleLiteral(SeRQO.PATTERN, node.getPattern());
328 		handleLiteral(SeRQO.CASESENSITIVE, node.isCaseSensitive());
329 		super.meet(node);
330 	}
331 
332 	@Override
333 	public void meet(LocalName node) {
334 		handleType(SeRQO.LOCALNAME);
335 		super.meet(node);
336 	}
337 
338 	@Override
339 	public void meet(MathExpr node) {
340 		handleType(SeRQO.MATHEXPR);
341 		handleLiteral(SeRQO.OPERATOR, node.getOperator().name());
342 		super.meet(node);
343 	}
344 
345 	@Override
346 	public void meet(Max node) {
347 		handleType(SeRQO.MAX);
348 		super.meet(node);
349 	}
350 
351 	@Override
352 	public void meet(Min node) {
353 		handleType(SeRQO.MIN);
354 		super.meet(node);
355 	}
356 
357 	@Override
358 	public void meet(Namespace node) {
359 		handleType(SeRQO.NAMESPACE);
360 		super.meet(node);
361 	}
362 
363 	@Override
364 	public void meet(Not node) {
365 		handleType(SeRQO.NOT);
366 		super.meet(node);
367 	}
368 
369 	@Override
370 	public void meet(LeftJoin node) {
371 		handleType(SeRQO.LEFTJOIN);
372 		handleChild(SeRQO.CONDITION, node.getCondition());
373 		super.meet(node);
374 	}
375 
376 	@Override
377 	public void meet(Or node) {
378 		handleType(SeRQO.OR);
379 		super.meet(node);
380 	}
381 
382 	@Override
383 	public void meet(Order node) {
384 		handleType(SeRQO.ORDER);
385 		handleChildList(SeRQO.ELEMENTS, node.getElements());
386 		super.meet(node);
387 	}
388 
389 	@Override
390 	public void meet(OrderElem node) {
391 		handleType(SeRQO.ORDERELEM);
392 		handleLiteral(SeRQO.ASC, node.isAscending());
393 		handleChild(SeRQO.ARG, node.getExpr());
394 		super.meet(node);
395 	}
396 
397 	@Override
398 	public void meet(MultiProjection node) {
399 		handleType(SeRQO.MULTIPROJECTION);
400 		handleChildList(SeRQO.ELEMENTS, node.getProjections());
401 		super.meet(node);
402 	}
403 
404 	@Override
405 	public void meet(Projection node) {
406 		handleType(SeRQO.PROJECTION);
407 		handleChild(SeRQO.ELEMENT, node.getProjectionElemList());
408 		super.meet(node);
409 	}
410 
411 	@Override
412 	public void meet(ProjectionElemList node) {
413 		handleType(SeRQO.PROJECTIONELEMLIST);
414 		handleChildList(SeRQO.ELEMENTS, node.getElements());
415 		super.meet(node);
416 	}
417 
418 	@Override
419 	public void meet(ProjectionElem node) {
420 		handleType(SeRQO.PROJECTIONELEM);
421 		handleLiteral(SeRQO.SOURCENAME, node.getSourceName());
422 		handleLiteral(SeRQO.TARGETNAME, node.getTargetName());
423 		super.meet(node);
424 	}
425 
426 	@Override
427 	public void meet(Regex node) {
428 		handleType(SeRQO.REGEX);
429 		handleChild(SeRQO.FLAGS, node.getFlagsArg());
430 		super.meet(node);
431 	}
432 
433 	@Override
434 	public void meet(Slice node) {
435 		handleType(SeRQO.SLICE);
436 		handleLiteral(SeRQO.LIMIT, node.getLimit());
437 		handleLiteral(SeRQO.OFFSET, node.getOffset());
438 		super.meet(node);
439 	}
440 
441 	@Override
442 	public void meet(SameTerm node) {
443 		handleType(SeRQO.SAMETERM);
444 		super.meet(node);
445 	}
446 
447 	@Override
448 	public void meet(Filter node) {
449 		handleType(SeRQO.FILTER);
450 		handleChild(SeRQO.CONDITION, node.getCondition());
451 		super.meet(node);
452 	}
453 
454 	@Override
455 	public void meet(SingletonSet node) {
456 		handleType(SeRQO.SINGLETONSET);
457 		super.meet(node);
458 	}
459 
460 	@Override
461 	public void meet(StatementPattern node) {
462 		handleType(SeRQO.STATEMENTPATTERN);
463 		handleLiteral(SeRQO.SCOPE, node.getScope().name());
464 		handleChild(SeRQO.SUBJECTVAR, node.getSubjectVar());
465 		handleChild(SeRQO.PREDICATEVAR, node.getPredicateVar());
466 		handleChild(SeRQO.OBJECTVAR, node.getObjectVar());
467 		handleChild(SeRQO.CONTEXTVAR, node.getContextVar());
468 		super.meet(node);
469 	}
470 
471 	@Override
472 	public void meet(Str node) {
473 		handleType(SeRQO.STR);
474 		super.meet(node);
475 	}
476 
477 	@Override
478 	public void meet(Union node) {
479 		handleType(SeRQO.UNION);
480 		super.meet(node);
481 	}
482 
483 	@Override
484 	public void meet(ValueConstant node) {
485 		handleType(SeRQO.VALUECONSTANT);
486 		handleValue(SeRQO.VALUE, node.getValue());
487 		super.meet(node);
488 	}
489 
490 	@Override
491 	public void meet(Var node) {
492 		handleType(SeRQO.VAR);
493 		handleLiteral(SeRQO.NAME, node.getName());
494 		handleValue(SeRQO.VALUE, node.getValue());
495 		super.meet(node);
496 	}
497 
498 	@Override
499 	protected void meetBinaryTupleOperator(BinaryTupleOperator node) {
500 		handleChild(SeRQO.LEFTARG, node.getLeftArg());
501 		handleChild(SeRQO.RIGHTARG, node.getRightArg());
502 		super.meetBinaryTupleOperator(node);
503 	}
504 
505 	@Override
506 	protected void meetBinaryValueOperator(BinaryValueOperator node) {
507 		handleChild(SeRQO.LEFTARG, node.getLeftArg());
508 		handleChild(SeRQO.RIGHTARG, node.getRightArg());
509 		super.meetBinaryValueOperator(node);
510 	}
511 
512 	@Override
513 	protected void meetCompareSubQueryValueOperator(
514 			CompareSubQueryValueOperator node) {
515 		handleChild(SeRQO.ARG, node.getArg());
516 		super.meetCompareSubQueryValueOperator(node);
517 	}
518 
519 	@Override
520 	protected void meetNode(QueryModelNode node) {
521 		// don't meet children
522 	}
523 
524 	@Override
525 	protected void meetSubQueryValueOperator(SubQueryValueOperator node) {
526 		handleChild(SeRQO.SUBQUERY, node.getSubQuery());
527 		super.meetSubQueryValueOperator(node);
528 	}
529 
530 	@Override
531 	protected void meetUnaryTupleOperator(UnaryTupleOperator node) {
532 		handleChild(SeRQO.ARG, node.getArg());
533 		super.meetUnaryTupleOperator(node);
534 	}
535 
536 	@Override
537 	protected void meetUnaryValueOperator(UnaryValueOperator node) {
538 		handleChild(SeRQO.ARG, node.getArg());
539 		super.meetUnaryValueOperator(node);
540 	}
541 
542 	private void handleChildList(URI predicate,
543 			List<? extends QueryModelNode> list) {
544 		if (list == null)
545 			return;
546 		Resource parentResource = subject;
547 		Resource childResource = vf.createBNode();
548 		handleValue(predicate, childResource);
549 		subject = childResource;
550 		meetNodeList(list);
551 		subject = parentResource;
552 	}
553 
554 	private void handleChild(URI predicate, QueryModelNode child) {
555 		if (child == null)
556 			return;
557 		Resource parentResource = subject;
558 		Resource childResource = vf.createBNode();
559 		handleValue(predicate, childResource);
560 		subject = childResource;
561 		child.visit(this);
562 		subject = parentResource;
563 	}
564 
565 	private void handleLiteralList(URI predicate, Iterable<String> list) {
566 		if (list == null)
567 			return;
568 		Resource parentResource = subject;
569 		Resource childResource = vf.createBNode();
570 		handleValue(predicate, childResource);
571 		subject = childResource;
572 		meetLiteralList(list);
573 		subject = parentResource;
574 	}
575 
576 	private void handleLiteral(URI predicate, boolean value) {
577 		handleValue(predicate, vf.createLiteral(value));
578 	}
579 
580 	private void handleLiteral(URI predicate, int value) {
581 		handleValue(predicate, vf.createLiteral(value));
582 	}
583 
584 	private void handleLiteral(URI predicate, String value) {
585 		if (value == null)
586 			return;
587 		handleValue(predicate, vf.createLiteral(value));
588 	}
589 
590 	private void handleType(URI rdfType) {
591 		try {
592 			rdf.handleStatement(vf.createStatement(subject, RDF.TYPE, rdfType));
593 		} catch (RDFHandlerException e) {
594 			throw new UndeclaredThrowableException(e);
595 		}
596 	}
597 
598 	private void handleValue(URI predicate, Value object) {
599 		if (object == null)
600 			return;
601 		try {
602 			Statement st;
603 			st = vf.createStatement(subject, predicate, object);
604 			rdf.handleStatement(st);
605 		} catch (RDFHandlerException e) {
606 			throw new UndeclaredThrowableException(e);
607 		}
608 	}
609 
610 	private void init() throws RDFHandlerException {
611 		if (vf == null)
612 			vf = new ValueFactoryImpl();
613 		rdf.startRDF();
614 		rdf.handleNamespace("rdf", RDF.NAMESPACE);
615 		rdf.handleNamespace("serqo", SeRQO.NAMESPACE_URL);
616 	}
617 
618 	private void meetNodeList(List<? extends QueryModelNode> list) {
619 		handleType(RDF.SEQ);
620 		for (int i = 0, n = list.size(); i < n; i++) {
621 			URI pred;
622 			if (i < members.length) {
623 				pred = members[i];
624 			} else {
625 				pred = vf.createURI(RDF.NAMESPACE + "_" + (i + 1));
626 			}
627 			handleChild(pred, list.get(i));
628 		}
629 	}
630 
631 	private void meetLiteralList(Iterable<String> literals) {
632 		handleType(RDF.SEQ);
633 
634 		int i = 0;
635 		Iterator<String> iter = literals.iterator();
636 		while (iter.hasNext()) {
637 			String literal = iter.next();
638 
639 			URI pred;
640 			if (i < members.length) {
641 				pred = members[i];
642 			} else {
643 				pred = vf.createURI(RDF.NAMESPACE + "_" + (i + 1));
644 			}
645 
646 			handleLiteral(pred, literal);
647 
648 			i++;
649 		}
650 	}
651 }