All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ontoware.rdf2go.impl.jena.ModelSetImplJena Maven / Gradle / Ivy

package org.ontoware.rdf2go.impl.jena;

import static org.ontoware.rdf2go.impl.jena.ModelImplJena.getJenaLang;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.io.input.ReaderInputStream;
import org.apache.commons.io.output.WriterOutputStream;
import org.apache.jena.riot.Lang;
import org.apache.jena.riot.RDFDataMgr;
import org.apache.jena.riot.RiotException;
import org.apache.jena.riot.RiotWriter;
import org.ontoware.aifbcommons.collection.ClosableIterable;
import org.ontoware.aifbcommons.collection.ClosableIterator;
import org.ontoware.rdf2go.Reasoning;
import org.ontoware.rdf2go.exception.LockException;
import org.ontoware.rdf2go.exception.MalformedQueryException;
import org.ontoware.rdf2go.exception.ModelRuntimeException;
import org.ontoware.rdf2go.exception.QueryLanguageNotSupportedException;
import org.ontoware.rdf2go.exception.SyntaxNotSupportedException;
import org.ontoware.rdf2go.model.Model;
import org.ontoware.rdf2go.model.ModelSet;
import org.ontoware.rdf2go.model.QuadPattern;
import org.ontoware.rdf2go.model.QueryResultTable;
import org.ontoware.rdf2go.model.Statement;
import org.ontoware.rdf2go.model.Syntax;
import org.ontoware.rdf2go.model.impl.AbstractModelSetImpl;
import org.ontoware.rdf2go.model.node.Node;
import org.ontoware.rdf2go.model.node.NodeOrVariable;
import org.ontoware.rdf2go.model.node.Resource;
import org.ontoware.rdf2go.model.node.ResourceOrVariable;
import org.ontoware.rdf2go.model.node.URI;
import org.ontoware.rdf2go.model.node.UriOrVariable;
import org.ontoware.rdf2go.model.node.Variable;
import org.ontoware.rdf2go.model.node.impl.URIImpl;

import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;


/**
 * A ModelSet implementation for Jena. It relies on the Jena
 * {@linkplain com.hp.hpl.jena.query.Dataset}.
 * 
 * @since 4.8.1
 * 
 * @author Roland Stühmer
 * 
 * @version $Revision: 1950 $
 * 
 */
public class ModelSetImplJena extends AbstractModelSetImpl {

	private static final long serialVersionUID = 9211877052180956697L;
	
	private final com.hp.hpl.jena.query.Dataset dataset;
	private final com.hp.hpl.jena.shared.Lock lock;
	private Query countStatementsQuery;
	private boolean open = true;
	
	private static class ContextIterator implements ClosableIterator {

		private final Iterator underlying;

		public ContextIterator(Iterator idIterator) {
			this.underlying = idIterator;
		}

		@Override
		public void close() {
		}

		@Override
		public boolean hasNext() {
			return this.underlying.hasNext();
		}

		@Override
		public URI next() {
			return new URIImpl(this.underlying.next());
		}

		@Override
		public void remove() {
			throw new UnsupportedOperationException();
		}
	}

	private class ModelIterator implements ClosableIterator {

		private final ClosableIterator underlying;

		private URI lastURI;

		public ModelIterator(ClosableIterator contextIterator) {
			this.underlying = contextIterator;
		}

		@Override
		public void close() {
			this.underlying.close();
		}

		@Override
		public boolean hasNext() {
			return this.underlying.hasNext();
		}

		@Override
		public Model next() {
			URI uri = this.underlying.next();

			Model model = getModel(uri);

			this.lastURI = uri;
			return model;
		}

		@Override
		public void remove() {
			// only possible when next() has been invoked at least once
			if (this.lastURI == null) {
				throw new IllegalStateException();
			}

			removeModel(lastURI);

			this.lastURI = null;
		}

	}

	private class JenaQuadPattern implements QuadPattern {

		private static final long serialVersionUID = -2397218722246644188L;

		private final UriOrVariable context;

		private final NodeOrVariable object;

		private final UriOrVariable predicate;

		private final ResourceOrVariable subject;

		public JenaQuadPattern(UriOrVariable context,
				ResourceOrVariable subject, UriOrVariable predicate,
				NodeOrVariable object) {
			this.checkNonNull(context);
			this.checkNonNull(subject);
			this.checkNonNull(predicate);
			this.checkNonNull(object);

			this.context = context;
			this.subject = subject;
			this.predicate = predicate;
			this.object = object;
		}

		@Override
		public UriOrVariable getContext() {
			return this.context;
		}

		@Override
		public NodeOrVariable getObject() {
			return this.object;
		}

		@Override
		public UriOrVariable getPredicate() {
			return this.predicate;
		}

		@Override
		public ResourceOrVariable getSubject() {
			return this.subject;
		}

		@Override
		public boolean matches(Statement statement) {
			return this.matches(statement.getContext(), this.context)
					&& this.matches(statement.getSubject(), this.subject)
					&& this.matches(statement.getPredicate(), this.predicate)
					&& this.matches(statement.getObject(), this.object);
		}

		private void checkNonNull(NodeOrVariable value) {
			if (value == null) {
				throw new NullPointerException();
			}
		}

		private boolean matches(Node node, NodeOrVariable variable) {
			return variable.equals(Variable.ANY) || variable.equals(node);
		}
	}

	private static class StatementIterator implements ClosableIterator {
		
		private final Iterator underlying;
		
		public StatementIterator(
				Iterator jenaQuadIterator) {
			this.underlying = jenaQuadIterator;
		}

		@Override
		public void close() {
		}

		@Override
		public boolean hasNext() {
			return this.underlying.hasNext();
		}

		@Override
		public Statement next() {
			com.hp.hpl.jena.sparql.core.Quad quad = this.underlying
					.next();
			return new StatementJena29Impl(quad.getGraph(), quad.getSubject(),
					quad.getPredicate(), quad.getObject());
		}

		@Override
		public void remove() {
			this.underlying.remove();
		}
	}

	public ModelSetImplJena(com.hp.hpl.jena.query.Dataset dataset) {
		this.dataset = dataset;
		this.lock = this.dataset.getLock();
		org.apache.jena.riot.RIOT.init(); //wires RIOT readers/writers into Jena
	}

	@Override
	public ModelSet open() {
		return this;
	}

	@Override
	public boolean isOpen() {
		return this.open;
	}

	@Override
	public void close() {
		this.open = false;
	}

	@Override
	public long size() throws ModelRuntimeException {

		// Start with the size of the default graph
		long size = this.dataset.getDefaultModel().size();

		// Loop and add the sizes of all contained graphs
		Iterator it = this.dataset.listNames();
		while (it.hasNext()) {
			size += this.dataset.getNamedModel(it.next()).size();
		}

		return size;
	}

	@Override
	public Model getModel(URI contextURI) {
		com.hp.hpl.jena.rdf.model.Model jenaModel = dataset
				.getNamedModel(contextURI.toString());

		if (jenaModel == null) {
			jenaModel = com.hp.hpl.jena.rdf.model.ModelFactory
					.createDefaultModel();
		}
		
		// return opened model
		return new ModelImplJena(contextURI, jenaModel).open();
	}

	@Override
	public boolean removeModel(URI contextURI) {
		this.dataset.removeNamedModel(contextURI.toString());
		return true;
	}

	@Override
	public boolean containsModel(URI contextURI) {
		return this.dataset.containsNamedModel(contextURI.toString());
	}

	@Override
	public Model getDefaultModel() {
		com.hp.hpl.jena.rdf.model.Model jenaModel = this.dataset
				.getDefaultModel();
		// return opened model
		return new ModelImplJena(jenaModel).open();
	}

	/**
	 * Return all named models. This does not currently return the
	 * default model because there is no usable iterator in Jena for this. Also
	 * the default Model in Jena has no usable context URI which causes problems
	 * later when iterating over the models e.g., using
	 * {@linkplain ClosableIterator#remove()}
	 */
	@Override
	public ClosableIterator getModels() {
		return new ModelIterator(this.getModelURIs());
	}

	@Override
	public ClosableIterator getModelURIs() {
		return new ContextIterator(this.dataset.listNames());
	}

	@Override
	public Object getUnderlyingModelSetImplementation() {
		return this.dataset;
	}

	@Override
	public ClosableIterable queryConstruct(String query,
			String querylanguage) throws QueryLanguageNotSupportedException,
			MalformedQueryException, ModelRuntimeException {

		Query jenaQuery = QueryFactory.create(query);
		QueryExecution qexec = QueryExecutionFactory.create(jenaQuery,
				this.dataset);

		if (jenaQuery.isConstructType()) {
			com.hp.hpl.jena.rdf.model.Model m = qexec.execConstruct();
			Model resultModel = new ModelImplJena(null, m, Reasoning.none);
			resultModel.open();
			return resultModel;
		} else {
			throw new RuntimeException(
					"Cannot handle this type of query! Please use CONSTRUCT.");
		}
	}

	@Override
	public QueryResultTable querySelect(String query, String querylanguage)
			throws QueryLanguageNotSupportedException, MalformedQueryException,
			ModelRuntimeException {
		com.hp.hpl.jena.query.Syntax syntax = com.hp.hpl.jena.query.Syntax
				.lookup(querylanguage);
		if (syntax == null) {
			// delegate to super
			throw new QueryLanguageNotSupportedException(
					"Unsupported query language: " + querylanguage);
		}
		Query jenaQuery = QueryFactory.create(query, syntax);
		return new QueryResultTableImpl(jenaQuery,
				this.dataset);
	}

	@Override
	public ClosableIterable sparqlConstruct(String query)
			throws ModelRuntimeException, MalformedQueryException {
		Query jenaQuery = QueryFactory.create(query);
		QueryExecution qexec = QueryExecutionFactory.create(jenaQuery,
				this.dataset);

		if (jenaQuery.isConstructType()) {
			com.hp.hpl.jena.rdf.model.Model m = qexec.execConstruct();
			Model resultModel = new ModelImplJena(null, m, Reasoning.none);
			resultModel.open();
			return resultModel;
		} else {
			throw new RuntimeException(
					"Cannot handle this type of query! Please use CONSTRUCT.");
		}

	}

	@Override
	public ClosableIterable sparqlDescribe(String query)
			throws ModelRuntimeException {
		Query jenaQuery = QueryFactory.create(query);
		QueryExecution qexec = QueryExecutionFactory.create(jenaQuery,
				this.dataset);

		if (jenaQuery.isDescribeType()) {
			com.hp.hpl.jena.rdf.model.Model m = qexec.execDescribe();
			Model resultModel = new ModelImplJena(null, m, Reasoning.none);
			resultModel.open();
			return resultModel;
		} else {
			throw new RuntimeException(
					"Cannot handle this type of query! Please use DESCRIBE.");
		}
	}

	@Override
	public QueryResultTable sparqlSelect(String queryString)
			throws MalformedQueryException, ModelRuntimeException {
		Query jenaQuery = QueryFactory.create(queryString);
		return new QueryResultTableImpl(jenaQuery,
				this.dataset);
	}

	@Override
	public boolean sparqlAsk(String query) throws ModelRuntimeException,
			MalformedQueryException {
		Query jenaQuery = QueryFactory.create(query);
		QueryExecution qexec = QueryExecutionFactory.create(jenaQuery,
				this.dataset);

		if (jenaQuery.isAskType()) {
			return qexec.execAsk();
		} else {
			throw new RuntimeException(
					"Cannot handle this type of query! Please use ASK.");
		}
	}

	/**
	 * Read data from an {@linkplain Reader} with RDF syntax {@link Syntax#Trix}.
	 */
	@Override
	public void readFrom(Reader in) throws IOException, ModelRuntimeException {
		readFrom(in, Syntax.Trix, null);
	}

	@Override
	public void readFrom(Reader in, Syntax syntax) throws IOException,
			ModelRuntimeException, SyntaxNotSupportedException {
		readFrom(in, syntax, null);
	}

	@Override
	public void readFrom(Reader in, Syntax syntax, String baseURI)
			throws IOException, ModelRuntimeException,
			SyntaxNotSupportedException {
		ReaderInputStream is = new ReaderInputStream(in, StandardCharsets.UTF_8);
		readFrom(is, syntax, baseURI);
	}

	/**
	 * Read data from an {@linkplain InputStream} with RDF syntax
	 * {@link Syntax#Trix}.
	 * 
	 * 
* Please note:
* In this Jena implementation this will fail until a matching * {@linkplain RiotReader} is available. Please use * {@linkplain ModelSetImplJena#readFrom(Reader, Syntax)} with an available * syntax such as {@link Syntax#Nquads} or {@link Syntax#Trig}. */ @Override public void readFrom(InputStream in) throws IOException, ModelRuntimeException { readFrom(in, Syntax.Trix, null); } @Override public void readFrom(InputStream in, Syntax syntax) throws IOException, ModelRuntimeException, SyntaxNotSupportedException { readFrom(in, syntax, null); } @Override public void readFrom(InputStream in, Syntax syntax, String baseURI) throws IOException, ModelRuntimeException, SyntaxNotSupportedException { RDFDataMgr.read(this.dataset.asDatasetGraph(), in, baseURI, getJenaLang(syntax)); } /** * Write data to a {@linkplain Writer} with RDF syntax * {@link Syntax#Trix}. * *
* Please note:
* In this Jena implementation this will fail until a matching * {@linkplain RiotWriter} is available. Please use * {@linkplain ModelSetImplJena#writeTo(Writer, Syntax)} with an available * syntax such as {@link Syntax#Nquads}. */ @Override public void writeTo(Writer out) throws IOException, ModelRuntimeException { writeTo(out, Syntax.Trix); } /** * Write data to an {@linkplain OutputStream} with RDF syntax * {@link Syntax#Trix}. * *
* Please note:
* In this Jena implementation this will fail until a matching * {@linkplain RiotWriter} is available. Please use * {@linkplain ModelSetImplJena#writeTo(OutputStream, Syntax)} with an available * syntax such as {@link Syntax#Nquads}. */ @Override public void writeTo(OutputStream out) throws IOException, ModelRuntimeException { writeTo(out, Syntax.Trix); } @Override public void writeTo(Writer writer, Syntax syntax) throws IOException, ModelRuntimeException, SyntaxNotSupportedException { WriterOutputStream stream = new WriterOutputStream(writer, StandardCharsets.UTF_8); writeTo(stream, syntax); } @Override public void writeTo(OutputStream out, Syntax syntax) throws IOException, ModelRuntimeException, SyntaxNotSupportedException { if (syntax == null) { throw new NullPointerException("syntax may not be null"); } Lang jenaLang = getJenaLang(syntax); // if (RDFLanguages.isTriples(jenaLang)) { // /* // * NB: Writing a ModelSet to a triple serialization loses the // * context of any quads if present. // */ // Iterator it = this.getModels(); // while (it.hasNext()) { // Model model = it.next(); // model.writeTo(out, syntax); // } // this.getDefaultModel().writeTo(out, syntax); // } // FIXME stuehmer: write unit test to see if this can be removed // else { try { RDFDataMgr.write(out, this.dataset, jenaLang); } catch (RiotException e) { throw new SyntaxNotSupportedException( "error writing syntax " + syntax + ": " + e.getMessage()); } } @Override public QuadPattern createQuadPattern(UriOrVariable context, ResourceOrVariable subject, UriOrVariable predicate, NodeOrVariable object) { return new JenaQuadPattern(context, subject, predicate, object); } @Override public void addStatement(Statement statement) throws ModelRuntimeException { addStatement(statement.getContext(), statement.getSubject(), statement.getPredicate(), statement.getObject()); } @Override public void addStatement(URI context, Resource subject, URI predicate, Node object) throws ModelRuntimeException { com.hp.hpl.jena.rdf.model.Model jenaModel; if (context != null) { jenaModel = this.dataset.getNamedModel(context.toString()); } else { jenaModel = this.dataset.getDefaultModel(); } jenaModel.getGraph().add( new com.hp.hpl.jena.graph.Triple(TypeConversion.toJenaNode( subject, jenaModel), TypeConversion.toJenaNode( predicate, jenaModel), TypeConversion.toJenaNode( object, jenaModel))); } @Override public void removeAll() throws ModelRuntimeException { // Empty the default graph this.dataset.getDefaultModel().removeAll(); // Remove all named graphs Iterator it = this.dataset.listNames(); while (it.hasNext()) { it.next(); it.remove(); } } @Override public void removeStatements(QuadPattern quadPattern) throws ModelRuntimeException { removeStatements(quadPattern.getContext(), quadPattern.getSubject(), quadPattern.getPredicate(), quadPattern.getObject()); } @Override public void removeStatements(UriOrVariable context, ResourceOrVariable subject, UriOrVariable predicate, NodeOrVariable object) throws ModelRuntimeException { this.dataset.asDatasetGraph().deleteAny( (context != null) ? TypeConversion.toJenaNode(context) : com.hp.hpl.jena.graph.Node.ANY, TypeConversion.toJenaNode(subject), TypeConversion.toJenaNode(predicate), TypeConversion.toJenaNode(object)); } @Override public void removeStatement(Statement statement) throws ModelRuntimeException { removeStatement(statement.getContext(), statement.getSubject(), statement.getPredicate(), statement.getObject()); } @Override public void removeStatement(URI context, Resource subject, URI predicate, Node object) throws ModelRuntimeException { if (context == null) { this.dataset .getDefaultModel() .getGraph() .delete(new com.hp.hpl.jena.graph.Triple(TypeConversion .toJenaNode(subject), TypeConversion .toJenaNode(predicate), TypeConversion .toJenaNode(object))); } else { this.dataset.asDatasetGraph().delete( TypeConversion.toJenaNode(context), TypeConversion.toJenaNode(subject), TypeConversion.toJenaNode(predicate), TypeConversion.toJenaNode(object)); } } @Override public long countStatements(QuadPattern pattern) { String context = (pattern.getContext() != null) ? pattern.getContext() .toString() : com.hp.hpl.jena.graph.Node.ANY.getName(); String subject = pattern.getSubject().toString(); String predicate = pattern.getPredicate().toString(); String object = pattern.getObject().toString(); com.hp.hpl.jena.query.QuerySolutionMap initialBindings = new com.hp.hpl.jena.query.QuerySolutionMap(); if (pattern.getContext() != null) { initialBindings.add("c", this.dataset.getDefaultModel() .createResource(context)); } initialBindings.add("s", this.dataset.getDefaultModel().createResource(subject)); initialBindings.add("p", this.dataset.getDefaultModel().createResource(predicate)); initialBindings.add("o", this.dataset.getDefaultModel().createResource(object)); String query = "SELECT (count(*) AS ?count) WHERE { GRAPH ?c { ?s ?p ?o } }"; // Initialize the reusable query if (this.countStatementsQuery == null) { this.countStatementsQuery = QueryFactory.create(query, com.hp.hpl.jena.query.Syntax.syntaxARQ); } QueryExecution exec = QueryExecutionFactory.create( this.countStatementsQuery, this.dataset, initialBindings); QueryResultTable result = new QueryResultTableImpl(exec); return Long .parseLong(result.iterator().next().getLiteralValue("count")); } @Override public ClosableIterator findStatements(QuadPattern pattern) throws ModelRuntimeException { return this.findStatements(pattern.getContext(), pattern.getSubject(), pattern.getPredicate(), pattern.getObject()); } @Override public ClosableIterator findStatements(UriOrVariable contextURI, ResourceOrVariable subject, UriOrVariable predicate, NodeOrVariable object) throws ModelRuntimeException { return new StatementIterator(this.dataset.asDatasetGraph().find( (contextURI != null) ? TypeConversion.toJenaNode(contextURI) : com.hp.hpl.jena.graph.Node.ANY, TypeConversion.toJenaNode(subject), TypeConversion.toJenaNode(predicate), TypeConversion.toJenaNode(object))); } @Override public ClosableIterator iterator() { return new StatementIterator(this.dataset.asDatasetGraph().find()); } @Override public void commit() throws ModelRuntimeException { } @Override public void setAutocommit(boolean autocommit) { } @Override public String getNamespace(String prefix) { // We use the default model because there is no prefix mapping on // Dataset itself: return this.dataset.getDefaultModel().getNsPrefixURI(prefix); } @Override public Map getNamespaces() { // We use the default model because there is no prefix mapping on // Dataset itself: return this.dataset.getDefaultModel().getNsPrefixMap(); } /** * Remove the specified namespace from all {@linkplain Model}s * in this {@linkplain ModelSet} including the default graph. */ @Override public void removeNamespace(String prefix) { this.dataset.getDefaultModel().removeNsPrefix(prefix); Iterator it = this.getModels(); while (it.hasNext()) { it.next().removeNamespace(prefix); } } /** * Set the specified namespace for all {@linkplain Model}s * in this {@linkplain ModelSet} including the default graph. */ @Override public void setNamespace(String prefix, String namespaceURI) throws IllegalArgumentException { this.dataset.getDefaultModel().setNsPrefix(prefix, namespaceURI); Iterator it = this.getModels(); while (it.hasNext()) { it.next().setNamespace(prefix, namespaceURI); } } @Override public boolean isLocked() { return super.isLocked(); } @Override public void lock() throws LockException { if (isLocked()) { throw new LockException("Already locked"); } else { super.lock(); this.lock.enterCriticalSection(com.hp.hpl.jena.shared.Lock.WRITE); } } @Override public void unlock() { if (isLocked()) { this.lock.leaveCriticalSection(); super.unlock(); } } @Override public boolean isEmpty() { return this.dataset.asDatasetGraph().isEmpty(); } @Override public String toString() { return this.dataset.asDatasetGraph().toString(); } @Override public boolean addModel(Model model) { for (String prefix : model.getNamespaces().keySet()) { this.dataset.getDefaultModel().setNsPrefix(prefix, model.getNamespace(prefix)); } if (model instanceof ModelImplJena) { this.dataset.getNamedModel(model.getContextURI().toString()).add( ((com.hp.hpl.jena.rdf.model.Model) model .getUnderlyingModelImplementation())); return true; } else { return super.addModel(model); } } @Override public void addModel(Model model, URI contextURI) { for (String prefix : model.getNamespaces().keySet()) { this.dataset.getDefaultModel().setNsPrefix(prefix, model.getNamespace(prefix)); } if (model instanceof ModelImplJena) { this.dataset.getNamedModel(contextURI.toString()).add( ((com.hp.hpl.jena.rdf.model.Model) model .getUnderlyingModelImplementation())); } else { super.addModel(model, contextURI); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy