View Javadoc

1   /*
2    * Copyright James Leigh (c) 2007.
3    *
4    * Licensed under the Aduna BSD-style license.
5    */
6   package org.openrdf.repository.augur;
7   
8   import info.aduna.iteration.CloseableIteration;
9   import info.aduna.iteration.Iteration;
10  
11  import java.util.Set;
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.query.GraphQuery;
18  import org.openrdf.query.GraphQueryResult;
19  import org.openrdf.query.MalformedQueryException;
20  import org.openrdf.query.Query;
21  import org.openrdf.query.QueryEvaluationException;
22  import org.openrdf.query.QueryLanguage;
23  import org.openrdf.query.TupleQuery;
24  import org.openrdf.query.algebra.Projection;
25  import org.openrdf.query.algebra.ProjectionElem;
26  import org.openrdf.query.algebra.ProjectionElemList;
27  import org.openrdf.query.algebra.TupleExpr;
28  import org.openrdf.query.parser.ParsedGraphQuery;
29  import org.openrdf.query.parser.ParsedQuery;
30  import org.openrdf.query.parser.ParsedTupleQuery;
31  import org.openrdf.query.parser.QueryParserUtil;
32  import org.openrdf.query.parser.serqo.SeRQOFormatter;
33  import org.openrdf.repository.Repository;
34  import org.openrdf.repository.RepositoryConnection;
35  import org.openrdf.repository.RepositoryException;
36  import org.openrdf.repository.RepositoryResult;
37  import org.openrdf.repository.augur.helpers.AStatementIterator;
38  import org.openrdf.repository.augur.helpers.AugurNodeFactory;
39  import org.openrdf.repository.augur.helpers.ConsumeStatementIterator;
40  import org.openrdf.repository.augur.helpers.RepositoryCloseableIteration;
41  import org.openrdf.repository.augur.model.AResource;
42  import org.openrdf.repository.augur.model.AugurNode;
43  import org.openrdf.repository.augur.model.AugurStatementNode;
44  import org.openrdf.repository.augur.model.CachableAugurNode;
45  import org.openrdf.repository.delegate.VersioningConnection;
46  
47  /**
48   * Wraps resulting Resource with an AugurNode. When Resources are passed back to
49   * the connection, it uses query expansion to pro-actively retrieves results for
50   * other Resources from the previous request. The results can only be
51   * operationed on from a single thread.
52   * 
53   * @author James Leigh
54   */
55  class AugurConnection extends VersioningConnection {
56  
57  	private AugurNodeFactory _factory;
58  
59  	private SeRQOFormatter formatter = new SeRQOFormatter();
60  
61  	public AugurConnection(Repository repository, RepositoryConnection con) {
62  		super(repository, con, 0);
63  		_factory = new AugurNodeFactory(this);
64  	}
65  
66  	@Override
67  	public RepositoryResult<Statement> getStatements(Resource subj, URI pred,
68  			Value obj, boolean includeInferred, Resource... contexts)
69  		throws RepositoryException
70  	{
71  		AugurStatementNode node;
72  		node = _factory.createAugurStatementNode(subj, pred, obj, includeInferred, contexts);
73  		if (isCacheEnabled(node)) {
74  			CachableAugurNode node2 = (CachableAugurNode)node;
75  			return getCachableStatements(node2, subj, obj, includeInferred);
76  		}
77  		CloseableIteration<? extends Statement, RepositoryException> stmts;
78  		stmts = super.getStatements(subj, pred, obj, includeInferred, contexts);
79  		return new RepositoryResult<Statement>(new AStatementIterator<RepositoryException>(stmts, node));
80  	}
81  
82  	@Override
83  	public GraphQuery prepareGraphQuery(QueryLanguage ql, String queryString, String baseURI)
84  		throws MalformedQueryException, RepositoryException
85  	{
86  		return (GraphQuery)prepareQuery(ql, queryString, baseURI);
87  	}
88  
89  	@Override
90  	public Query prepareQuery(QueryLanguage ql, String queryString, String baseURI)
91  		throws MalformedQueryException, RepositoryException
92  	{
93  		ParsedQuery parsedQuery = QueryParserUtil.parseQuery(ql, queryString, baseURI);
94  		if (parsedQuery instanceof ParsedGraphQuery) {
95  			GraphQuery query = super.prepareGraphQuery(ql, queryString, baseURI);
96  			boolean include = query.getIncludeInferred();
97  			AugurNode node = _factory.createAugurNode(parsedQuery, include);
98  			return new AugurGraphQuery(node, query);
99  		}
100 		else if (parsedQuery instanceof ParsedTupleQuery) {
101 			TupleQuery query = super.prepareTupleQuery(ql, queryString, baseURI);
102 			boolean include = query.getIncludeInferred();
103 			AugurNode node = _factory.createAugurNode(parsedQuery, include);
104 			Set<String> names = parsedQuery.getTupleExpr().getBindingNames();
105 			return new AugurTupleQuery(node, query, names);
106 		}
107 		return super.prepareQuery(ql, queryString, baseURI);
108 	}
109 
110 	@Override
111 	public TupleQuery prepareTupleQuery(QueryLanguage ql, String queryString, String baseURI)
112 		throws MalformedQueryException, RepositoryException
113 	{
114 		return (TupleQuery)prepareQuery(ql, queryString, baseURI);
115 	}
116 
117 	private RepositoryResult<Statement> getCachableStatements(
118 			CachableAugurNode node, Resource subj, Value obj, boolean includeInferred)
119 		throws RepositoryException
120 	{
121 		CloseableIteration<? extends Statement, QueryEvaluationException> stmts;
122 		stmts = node.getStatements(subj, obj);
123 		if (stmts == null) {
124 			try {
125 				ParsedGraphQuery parsedQuery = createGraphQuery(node);
126 				String queryString = formatter.formatGraphQuery(parsedQuery);
127 				GraphQuery graphQuery = super.prepareGraphQuery(QueryLanguage.SERQO, queryString, null);
128 				graphQuery.setIncludeInferred(node.isIncludeInferred());
129 				GraphQueryResult results = graphQuery.evaluate();
130 				Iteration<Statement, QueryEvaluationException> iter = results;
131 				AResource carried = (AResource)node.getCarriedOverResource(subj, obj);
132 				iter = new ConsumeStatementIterator<QueryEvaluationException>(iter, carried, node, getVersion());
133 				return new RepositoryResult<Statement>(new RepositoryCloseableIteration<Statement>(
134 						new AStatementIterator<QueryEvaluationException>(iter, node)));
135 			}
136 			catch (MalformedQueryException e) {
137 				throw new RepositoryException(e);
138 			}
139 			catch (QueryEvaluationException e) {
140 				throw new RepositoryException(e);
141 			}
142 		}
143 		return new RepositoryResult<Statement>(new RepositoryCloseableIteration<Statement>(new AStatementIterator<QueryEvaluationException>(
144 				stmts, node)));
145 	}
146 
147 	private ParsedGraphQuery createGraphQuery(AugurStatementNode node) {
148 		TupleExpr tupleExpr = node.getTupleExpr();
149 		String subjName = node.getSubjectName();
150 		String predName = node.getPredicateName();
151 		String objName = node.getObjectName();
152 		String ctxName = node.getContextName();
153 		ProjectionElem projSubj = new ProjectionElem(subjName, "subject");
154 		ProjectionElem projPred = new ProjectionElem(predName, "predicate");
155 		ProjectionElem projObj = new ProjectionElem(objName, "object");
156 		ProjectionElem projCtx = new ProjectionElem(ctxName, "context");
157 		ProjectionElemList projElemList = new ProjectionElemList(projSubj, projPred, projObj, projCtx);
158 		Projection proj = new Projection(tupleExpr, projElemList);
159 		ParsedGraphQuery query = new ParsedGraphQuery(proj);
160 		if (logger.isDebugEnabled()) {
161 			logger.debug(proj.toString());
162 		}
163 		return query;
164 	}
165 
166 	private boolean isCacheEnabled(AugurStatementNode node) {
167 		return node instanceof CachableAugurNode && ((CachableAugurNode)node).isCacheEnabled(getVersion());
168 	}
169 }