/* * Copyright (c) 2009 Mysema Ltd. * All rights reserved. * */ package com.mysema.rdfbean.sesame; import java.util.Collection; import javax.annotation.Nullable; import org.openrdf.model.BNode; import org.openrdf.model.Literal; import org.openrdf.model.Resource; import org.openrdf.model.Statement; import org.openrdf.model.URI; import org.openrdf.model.Value; import org.openrdf.model.ValueFactory; import org.openrdf.query.BooleanQuery; import org.openrdf.query.GraphQuery; import org.openrdf.query.MalformedQueryException; import org.openrdf.query.Query; import org.openrdf.query.TupleQuery; import org.openrdf.query.algebra.ProjectionElem; import org.openrdf.query.algebra.ProjectionElemList; import org.openrdf.query.algebra.TupleExpr; import org.openrdf.query.algebra.Var; import org.openrdf.query.parser.ParsedBooleanQuery; import org.openrdf.query.parser.ParsedGraphQuery; import org.openrdf.query.parser.ParsedTupleQuery; import org.openrdf.repository.RepositoryConnection; import org.openrdf.repository.RepositoryResult; import com.google.common.base.Function; import com.google.common.collect.Iterables; import com.mysema.commons.lang.Assert; import com.mysema.commons.lang.CloseableIterator; import com.mysema.query.QueryException; import com.mysema.query.QueryMetadata; import com.mysema.rdfbean.model.BID; import com.mysema.rdfbean.model.Dialect; import com.mysema.rdfbean.model.ID; import com.mysema.rdfbean.model.InferenceOptions; import com.mysema.rdfbean.model.NODE; import com.mysema.rdfbean.model.QueryLanguage; import com.mysema.rdfbean.model.QueryOptions; import com.mysema.rdfbean.model.RDFBeanTransaction; import com.mysema.rdfbean.model.RDFConnection; import com.mysema.rdfbean.model.RepositoryException; import com.mysema.rdfbean.model.SPARQLQuery; import com.mysema.rdfbean.model.SPARQLUpdateClause; import com.mysema.rdfbean.model.SPARQLVisitor; import com.mysema.rdfbean.model.STMT; import com.mysema.rdfbean.model.UID; import com.mysema.rdfbean.model.UnsupportedQueryLanguageException; import com.mysema.rdfbean.model.UpdateLanguage; /** * SaesameConnection is the RDFConnection implementation for * RepositoryConnection usage * * @author sasa * */ public class SesameConnection implements RDFConnection { private static final URI RDF_TYPE = org.openrdf.model.vocabulary.RDF.TYPE; private static final Var RDF_TYPE_VAR = new Var("rdf_type", RDF_TYPE);; private static final ProjectionElemList projections = new ProjectionElemList(); static { RDF_TYPE_VAR.setAnonymous(true); projections.addElements(new ProjectionElem("subject")); projections.addElements(new ProjectionElem("_rdf_type", "predicate")); projections.addElements(new ProjectionElem("object")); } private final RepositoryConnection connection; private final SesameDialect dialect; @Nullable private SesameTransaction localTxn = null; private boolean readonlyTnx = false; private final Function<STMT, Statement> stmtTransformer = new Function<STMT, Statement>() { @Override public Statement apply(STMT stmt) { return convert(stmt); } }; private final ValueFactory vf; private final SesameRepository repository; private final InferenceOptions inference; private final boolean serializeQueries; public SesameConnection(SesameRepository repository, RepositoryConnection connection, InferenceOptions inference, boolean serializeQueries) { this.repository = Assert.notNull(repository, "repository"); this.connection = Assert.notNull(connection, "connection"); this.vf = connection.getValueFactory(); this.dialect = new SesameDialect(vf); this.inference = inference; this.serializeQueries = serializeQueries; } @Override public RDFBeanTransaction beginTransaction(boolean readOnly, int txTimeout, int isolationLevel) { localTxn = new SesameTransaction(this, isolationLevel); readonlyTnx = readOnly; localTxn.begin(); return localTxn; } public void cleanUpAfterCommit() { localTxn = null; readonlyTnx = false; } public void cleanUpAfterRollback() { localTxn = null; readonlyTnx = false; close(); } @Override public void clear() { dialect.clear(); } @Override public void close() { try { if (localTxn != null) { localTxn.rollback(); } connection.close(); } catch (Exception e) { throw new RepositoryException(e); } } private Iterable<Statement> convert(final Collection<STMT> stmts) { return Iterables.transform(stmts, stmtTransformer); } @Nullable private Resource convert(@Nullable ID id) { return id != null ? dialect.getResource(id) : null; } @Nullable private Value convert(@Nullable NODE node) { return node != null ? dialect.getNode(node) : null; } private Statement convert(STMT stmt) { Resource subject = dialect.getResource(stmt.getSubject()); URI predicate = dialect.getURI(stmt.getPredicate()); Value object = dialect.getNode(stmt.getObject()); URI context = stmt.getContext() != null ? dialect.getURI(stmt.getContext()) : null; return dialect.createStatement(subject, predicate, object, context); } @Nullable private URI convert(@Nullable UID uid) { return uid != null ? dialect.getURI(uid) : null; } @Override public BID createBNode() { return dialect.getBID(dialect.createBNode()); } @SuppressWarnings("unchecked") @Override public <D, Q> Q createUpdate(UpdateLanguage<D, Q> updateLanguage, D definition) { if (updateLanguage == UpdateLanguage.SPARQL_UPDATE) { return (Q) new SPARQLUpdateClause(this, definition.toString()); } else { throw new UnsupportedOperationException(updateLanguage.toString()); } } @SuppressWarnings("unchecked") @Override public <D, Q> Q createQuery(QueryLanguage<D, Q> queryLanguage, D definition) { boolean queryInference = !inference.subClassOf(); if (queryLanguage.equals(QueryLanguage.SPARQL)) { return (Q) createSPARQLQuery((String) definition); } else if (serializeQueries) { SPARQLVisitor visitor = new SPARQLVisitor(); QueryMetadata md = (QueryMetadata) definition; visitor.setInToOr(true); visitor.visit(md, queryLanguage); SPARQLQuery query = createSPARQLQuery(visitor.toString()); visitor.addBindings(query, md); System.err.println(visitor.toString()); return (Q) query; } else if (queryLanguage.equals(QueryLanguage.TUPLE)) { SesameRDFVisitor visitor = new SesameRDFVisitor(dialect); TupleExpr tuple = visitor.visit((QueryMetadata) definition, queryLanguage); ParsedTupleQuery queryModel = new ParsedTupleQuery(tuple); TupleQuery query = DirectQuery.getQuery(connection, queryModel, queryInference); return (Q) new TupleQueryImpl(query, dialect); } else if (queryLanguage.equals(QueryLanguage.GRAPH)) { SesameRDFVisitor visitor = new SesameRDFVisitor(dialect); TupleExpr tuple = visitor.visit((QueryMetadata) definition, queryLanguage); ParsedGraphQuery queryModel = new ParsedGraphQuery(tuple); GraphQuery query = DirectQuery.getQuery(connection, queryModel, queryInference); return (Q) new GraphQueryImpl(query, dialect); } else if (queryLanguage.equals(QueryLanguage.BOOLEAN)) { SesameRDFVisitor visitor = new SesameRDFVisitor(dialect); TupleExpr tuple = visitor.visit((QueryMetadata) definition, queryLanguage); ParsedBooleanQuery queryModel = new ParsedBooleanQuery(tuple); BooleanQuery query = DirectQuery.getQuery(connection, queryModel, queryInference); return (Q) new BooleanQueryImpl(query, dialect); } else { throw new UnsupportedQueryLanguageException(queryLanguage); } } private SPARQLQuery createSPARQLQuery(String queryString) { try { Query query = connection.prepareQuery(org.openrdf.query.QueryLanguage.SPARQL, queryString); if (query instanceof BooleanQuery) { return new BooleanQueryImpl((BooleanQuery) query, dialect); } else if (query instanceof GraphQuery) { return new GraphQueryImpl((GraphQuery) query, dialect); } else if (query instanceof TupleQuery) { return new TupleQueryImpl((TupleQuery) query, dialect); } else { throw new RepositoryException("Unsupported query type " + query.getClass().getName()); } } catch (MalformedQueryException e) { throw new QueryException(e); } catch (org.openrdf.repository.RepositoryException e) { throw new QueryException(e); } } @Override public CloseableIterator<STMT> findStatements(ID sub, UID pre, NODE obj, UID con, boolean includeInferred) { Resource subject = convert(sub); URI predicate = convert(pre); Value object = convert(obj); URI context = convert(con); // default results return new RepositoryResultIterator(dialect, findStatements(subject, predicate, object, includeInferred, context), includeInferred); } @Override public boolean exists(@Nullable ID sub, @Nullable UID pre, @Nullable NODE obj, @Nullable UID con, boolean includeInferred) { Resource subject = convert(sub); URI predicate = convert(pre); Value object = convert(obj); URI context = convert(con); try { if (context == null) { return connection.hasStatement(subject, predicate, object, includeInferred); } else { return connection .hasStatement(subject, predicate, object, includeInferred, context); } } catch (org.openrdf.repository.RepositoryException e) { throw new RepositoryException(e); } } private RepositoryResult<Statement> findStatements(@Nullable Resource subject, @Nullable URI predicate, @Nullable Value object, boolean includeInferred, @Nullable URI context) { try { if (context == null) { return connection.getStatements(subject, predicate, object, includeInferred); } else if (includeInferred) { return connection.getStatements(subject, predicate, object, includeInferred, context, null); } else { return connection.getStatements(subject, predicate, object, includeInferred, context); } } catch (org.openrdf.repository.RepositoryException e) { throw new RepositoryException(e); } } public RepositoryConnection getConnection() { return connection; } public Dialect<Value, Resource, BNode, URI, Literal, Statement> getDialect() { return dialect; } @Override public long getNextLocalId() { return repository.getNextLocalId(); } public RDFBeanTransaction getTransaction() { return localTxn; } @Override public void remove(ID subject, UID predicate, NODE object, UID context) { Resource subj = subject != null ? dialect.getResource(subject) : null; URI pred = predicate != null ? dialect.getURI(predicate) : null; Value obj = object != null ? dialect.getNode(object) : null; URI cont = context != null ? dialect.getURI(context) : null; try { connection.remove(subj, pred, obj, cont); } catch (org.openrdf.repository.RepositoryException e) { try { connection.rollback(); } catch (org.openrdf.repository.RepositoryException e1) { throw new RepositoryException(e); } throw new RepositoryException(e); } } @Override public void update(Collection<STMT> removedStatements, Collection<STMT> addedStatements) { if (!readonlyTnx) { try { if (localTxn == null) { connection.begin(); } if (removedStatements != null && !removedStatements.isEmpty()) { connection.remove(convert(removedStatements)); } if (addedStatements != null && !addedStatements.isEmpty()) { connection.add(convert(addedStatements)); } if (localTxn == null) { connection.commit(); } } catch (org.openrdf.repository.RepositoryException e) { try { connection.rollback(); } catch (org.openrdf.repository.RepositoryException e1) { throw new RepositoryException(e); } throw new RepositoryException(e); } } } @Override public QueryOptions getQueryOptions() { return QueryOptions.DEFAULT; } @Override public InferenceOptions getInferenceOptions() { return inference; } }