package org.mulgara.jena; /* * (c) Copyright 2008 Hewlett-Packard Development Company, LP * All rights reserved. * [See end of file] */ import java.net.URI; import java.net.URISyntaxException; import java.util.HashSet; import java.util.NoSuchElementException; import java.util.Set; import org.jrdf.graph.ObjectNode; import org.jrdf.graph.PredicateNode; import org.jrdf.graph.SubjectNode; import org.mulgara.query.QueryException; import org.mulgara.server.Session; import com.hp.hpl.jena.graph.Capabilities; import com.hp.hpl.jena.graph.Node; import com.hp.hpl.jena.graph.TransactionHandler; import com.hp.hpl.jena.graph.Triple; import com.hp.hpl.jena.graph.TripleMatch; import com.hp.hpl.jena.graph.impl.GraphBase; import com.hp.hpl.jena.graph.query.BindingQueryPlan; import com.hp.hpl.jena.graph.query.Domain; import com.hp.hpl.jena.graph.query.QueryHandler; import com.hp.hpl.jena.shared.JenaException; import com.hp.hpl.jena.util.iterator.ExtendedIterator; import com.hp.hpl.jena.util.iterator.NiceIterator; /** * Represents a Jena graph as instantiated by Mulgara. * * @author Andy Seaborne * @copyright © 2008 Hewlett-Packard Development Company, LP */ public class GraphMulgara extends GraphBase { // TODO Bnodes (bless 'em!) - currently skolemized, change to label skolemization. // TODO Batched updates private Session session; private URI modelURI; private QueryHandler queryHandler; private TransactionMulgara transactionHandler = null; public GraphMulgara(Session session, URI modelURI) { this.session = session; this.modelURI = modelURI; transactionHandler = new TransactionMulgara(this, session); queryHandler = new PatternMulgara(this); } public Session getSession() { return session; } public URI getModelURI() { return modelURI; } @Override public TransactionHandler getTransactionHandler() { return transactionHandler; } @Override public QueryHandler queryHandler() { return queryHandler; } @Override public void performAdd(Triple t) { // if (transactionHandler.inExplicitTransaction()) { } try { Set<org.jrdf.graph.Triple> acc = prepare(t); session.insert(modelURI, acc); } catch (QueryException ex) { throw new JenaException(ex); } } @Override public void performDelete(Triple t) { try { Set<org.jrdf.graph.Triple> acc = prepare(t) ; session.delete(modelURI, acc) ; } catch (QueryException ex) { throw new JenaException(ex) ; } } private final Set<org.jrdf.graph.Triple> prepare(Triple t) { Node s = t.getSubject(); Node p = t.getPredicate(); Node o = t.getObject(); return prepare(s,p,o); } private final Set<org.jrdf.graph.Triple> prepare(Node s, Node p, Node o) { try { // if (s.isBlank() || o.isBlank()) throw new JenaException("GraphMulgara : blank nodes not supported yet") ; SubjectNode sNode = (SubjectNode)Jenara.n2v(s, session); PredicateNode pNode = (PredicateNode)Jenara.n2v(p, session); ObjectNode oNode = (ObjectNode)Jenara.n2v(o, session); org.jrdf.graph.Triple mt = new org.mulgara.query.rdf.TripleImpl(sNode, pNode, oNode); Set<org.jrdf.graph.Triple> acc = new HashSet<org.jrdf.graph.Triple>(); acc.add(mt); return acc; } catch (URISyntaxException ex) { throw new JenaException(ex); } } @Override protected ExtendedIterator graphBaseFind(TripleMatch m) { int length = 0; Node s = m.getMatchSubject(); Node p = m.getMatchPredicate(); Node o = m.getMatchObject(); if (s == null || s.equals(Node.ANY)) { s = Node.createVariable("s"); length++; } if (p == null || p.equals(Node.ANY)) { p = Node.createVariable("p"); length++; } if (o == null || o.equals(Node.ANY)) { o = Node.createVariable("o"); length++; } // Check not already a variable. Node[] variables = new Node[length]; int i = 0; if (s.isVariable()) variables[i++] = s; if (p.isVariable()) variables[i++] = p; if (o.isVariable()) variables[i++] = o; Triple t = new Triple(s,p,o) ; com.hp.hpl.jena.graph.query.Query graphQuery = new com.hp.hpl.jena.graph.query.Query(); graphQuery.addMatch(t); BindingQueryPlan plan = queryHandler().prepareBindings(graphQuery, variables); ExtendedIterator iter = plan.executeBindings(); // Of domains return new AnswerBindingIterator(iter, variables, t); } static class AnswerBindingIterator extends NiceIterator { private ExtendedIterator iter ; private final Triple triple ; private Triple slot ; private boolean finished ; public AnswerBindingIterator(ExtendedIterator iter, Node[] variables, Triple t) { this.iter = iter ; this.triple = t ; finished = false ; } @Override public boolean hasNext() { if (finished) return false; if (slot != null) return true; if (!iter.hasNext()) { NiceIterator.close(iter); finished = true; return false; } Domain d = (Domain)iter.next(); Node s = triple.getSubject(); Node p = triple.getPredicate(); Node o = triple.getObject(); int i = 0; if (s.isVariable()) s = d.getElement(i++); if (p.isVariable()) p = d.getElement(i++); if (o.isVariable()) o = d.getElement(i++); slot = new Triple(s,p,o); return true ; } // This form is common. @Override public Object next() { if (!hasNext()) throw new NoSuchElementException("AnswerIterator.next"); Triple t = slot; slot = null; return t; } @Override public void remove() { throw new UnsupportedOperationException(); } } //private Node bNodeProperty = Node.createURI("http://jena.hpl.hp.com/JenaMulgara#bNodeLabel") ; // Callbacks from the tranaction handler. void transactionStart() {} void transactionCommit() { removeBNodeLabels() ; flushBNodeMapping() ; } void transactionAbort() { // No need - the transaction rollback will do that. //removeBNodeLabels() ; flushBNodeMapping() ; } void flushBNodeMapping() { //nodesToValues.clear(); //valuesToNodes.clear() ; } void removeBNodeLabels() { } @Override public void close() { super.close(); } @Override public Capabilities getCapabilities() { if (capabilities == null) capabilities = new Capabilities() { public boolean sizeAccurate() { return true; } public boolean addAllowed() { return true ; } public boolean addAllowed( boolean every ) { return true; } public boolean deleteAllowed() { return true ; } public boolean deleteAllowed( boolean every ) { return true; } public boolean canBeEmpty() { return true; } public boolean iteratorRemoveAllowed() { return false; } /* ** */ public boolean findContractSafe() { return true; } public boolean handlesLiteralTyping() { return false; } /* ** */ }; return super.getCapabilities() ; } } /* * (c) Copyright 2008 Hewlett-Packard Development Company, LP * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */