View Javadoc

1   /*
2    * Copyright (c) 2007, James Leigh All rights reserved.
3    * 
4    * Redistribution and use in source and binary forms, with or without
5    * modification, are permitted provided that the following conditions are met:
6    * 
7    * - Redistributions of source code must retain the above copyright notice, this
8    *   list of conditions and the following disclaimer.
9    * - Redistributions in binary form must reproduce the above copyright notice,
10   *   this list of conditions and the following disclaimer in the documentation
11   *   and/or other materials provided with the distribution. 
12   * - Neither the name of the openrdf.org nor the names of its contributors may
13   *   be used to endorse or promote products derived from this software without
14   *   specific prior written permission.
15   * 
16   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26   * POSSIBILITY OF SUCH DAMAGE.
27   * 
28   */
29  package org.openrdf.repository.contextaware;
30  
31  import org.openrdf.model.Resource;
32  import org.openrdf.query.MalformedQueryException;
33  import org.openrdf.query.QueryLanguage;
34  import org.openrdf.query.UnsupportedQueryLanguageException;
35  import org.openrdf.query.algebra.Filter;
36  import org.openrdf.query.algebra.Or;
37  import org.openrdf.query.algebra.QueryModelNode;
38  import org.openrdf.query.algebra.SameTerm;
39  import org.openrdf.query.algebra.StatementPattern;
40  import org.openrdf.query.algebra.TupleExpr;
41  import org.openrdf.query.algebra.ValueConstant;
42  import org.openrdf.query.algebra.ValueExpr;
43  import org.openrdf.query.algebra.Var;
44  import org.openrdf.query.algebra.StatementPattern.Scope;
45  import org.openrdf.query.algebra.helpers.QueryModelNodeReplacer;
46  import org.openrdf.query.algebra.helpers.QueryModelVisitorBase;
47  import org.openrdf.query.parser.ParsedQuery;
48  import org.openrdf.query.parser.QueryParserUtil;
49  import org.openrdf.query.parser.serqo.SeRQOFormatter;
50  
51  /**
52   * Rewrites the query it the query laungage SERQO replacing all statement
53   * patterns with no context to use the assign context.
54   * 
55   * @author James Leigh
56   * 
57   */
58  public class ContextQueryRewriter extends
59  		QueryModelVisitorBase<RuntimeException> {
60  	private static final QueryLanguage _ql = QueryLanguage.SERQO;
61  
62  	private SeRQOFormatter _formatter = new SeRQOFormatter();
63  
64  	private Resource[] _contexts;
65  
66  	public Resource[] getContexts() {
67  		return _contexts;
68  	}
69  
70  	public void setContexts(Resource[] readContexts) {
71  		this._contexts = readContexts;
72  	}
73  
74  	public QueryLanguage getQueryLanguage() {
75  		return _ql;
76  	}
77  
78  	public String rewriteQuery(QueryLanguage ql, String query, String baseURI)
79  			throws MalformedQueryException, UnsupportedQueryLanguageException {
80  		ParsedQuery parsedQuery = QueryParserUtil
81  				.parseQuery(ql, query, baseURI);
82  		TupleExpr tupleExpr = parsedQuery.getTupleExpr();
83  		tupleExpr.visit(this);
84  		return _formatter.formatQuery(parsedQuery);
85  	}
86  
87  	@Override
88  	public void meet(StatementPattern node) throws RuntimeException {
89  		if (_contexts.length > 1) {
90  			ValueExpr condition = null;
91  			node.setScope(Scope.NAMED_CONTEXTS);
92  			Var var = node.getContextVar();
93  			if (var == null || var.isAnonymous()) {
94  				int id = System.identityHashCode(node);
95  				String hex = Integer.toHexString(id);
96  				var = new Var("_ctx" + hex);
97  			}
98  			var.setValue(null);
99  			node.setContextVar(var);
100 			for (Resource ctx : _contexts) {
101 				ValueConstant val = new ValueConstant(ctx);
102 				SameTerm eq = new SameTerm(var, val);
103 				if (condition == null) {
104 					condition = eq;
105 				} else {
106 					condition = new Or(condition, eq);
107 				}
108 			}
109 			QueryModelNode parentNode = node.getParentNode();
110 			Filter filter = new Filter(node, condition);
111 			QueryModelNodeReplacer replacer = new QueryModelNodeReplacer();
112 			replacer.replaceChildNode(parentNode, node, filter);
113 		} else if (_contexts.length == 1) {
114 			node.setScope(Scope.NAMED_CONTEXTS);
115 			Var var = node.getContextVar();
116 			if (var == null) {
117 				var = new Var("_");
118 				var.setAnonymous(true);
119 			}
120 			var.setValue(_contexts[0]);
121 			node.setContextVar(var);
122 		} else {
123 			node.setScope(Scope.DEFAULT_CONTEXTS);
124 			Var var = node.getContextVar();
125 			if (var != null)
126 				var.setValue(null);
127 			node.setContextVar(var);
128 		}
129 	}
130 }