--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.db.common.utils;\r
+\r
+import java.util.Collection;\r
+import java.util.Set;\r
+import java.util.concurrent.Semaphore;\r
+\r
+import org.simantics.databoard.accessor.Accessor;\r
+import org.simantics.databoard.binding.Binding;\r
+import org.simantics.databoard.type.Datatype;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.RequestProcessor;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Statement;\r
+import org.simantics.db.VirtualGraph;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.WriteOnlyGraph;\r
+import org.simantics.db.common.request.DelayedWriteRequest;\r
+import org.simantics.db.exception.AdaptionException;\r
+import org.simantics.db.exception.BindingException;\r
+import org.simantics.db.exception.CancelTransactionException;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.exception.DoesNotContainValueException;\r
+import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;\r
+import org.simantics.db.exception.NoInverseException;\r
+import org.simantics.db.exception.NoSingleResultException;\r
+import org.simantics.db.exception.ResourceNotFoundException;\r
+import org.simantics.db.exception.RuntimeDatabaseException;\r
+import org.simantics.db.exception.ServiceException;\r
+import org.simantics.db.exception.ValidationException;\r
+import org.simantics.db.procedure.Procedure;\r
+import org.simantics.db.request.DelayedWrite;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.db.request.UndoTraits;\r
+import org.simantics.db.request.Write;\r
+import org.simantics.utils.datastructures.Callback;\r
+\r
+/**\r
+ * Synchronous Transaction. <p>\r
+ * \r
+ * Hint: Import all methods as static.\r
+ * import static org.simantics.db.Transaction.*; \r
+ * \r
+ * Remember also to change Eclipse Preferences:\r
+ * Organize Imports: number of static imports needed for .* on vakiona 99, siihen vaikka 3\r
+ *\r
+ * \r
+ * Usage A:\r
+ * \r
+ * startTransaction(session, true);\r
+ * try {\r
+ * ...\r
+ * commit();\r
+ * } finally {\r
+ * endTransaction();\r
+ * }\r
+ * \r
+ * Usage B:\r
+ * setGraph(g);\r
+ * ...\r
+ * setGraph(null);\r
+ *\r
+ * @author Toni Kalajainen <toni.kalajainen@vtt.fi>\r
+ */\r
+public class Transaction {\r
+\r
+ public static enum Type {\r
+ READ,\r
+ WRITE,\r
+ DELAYED_WRITE\r
+ }\r
+ \r
+ /** Thread local transactions */\r
+ private static ThreadLocal<TransactionInfo> transactions = new ThreadLocal<TransactionInfo>();\r
+ \r
+ static private class TransactionInfo {\r
+ WriteGraph wg;\r
+ ReadGraph rg;\r
+ \r
+ /** Semaphore that is released when the transaction is complete */\r
+ Semaphore ts;\r
+ \r
+ /** Semaphore that is release after transaction ended */\r
+ Semaphore es;\r
+ \r
+ /** Error */\r
+ DatabaseException error;\r
+ \r
+ /** */\r
+ boolean commit = false;\r
+ \r
+ TransactionInfo() {\r
+ }\r
+ \r
+ TransactionInfo(Object graph) {\r
+ if (graph instanceof WriteGraph) {\r
+ wg = (WriteGraph) graph;\r
+ rg = (ReadGraph) graph;\r
+ } else if (graph instanceof ReadGraph) {\r
+ wg = null;\r
+ rg = (ReadGraph) graph;\r
+ } else {\r
+ throw new RuntimeDatabaseException("Not a sync graph");\r
+ } \r
+ }\r
+ }\r
+ \r
+ public static ReadGraph readGraph() {\r
+ TransactionInfo t = transactions.get();\r
+ return t == null ? null : t.rg;\r
+ }\r
+ \r
+ public static WriteGraph writeGraph() {\r
+ TransactionInfo t = transactions.get();\r
+ return t == null ? null : t.wg;\r
+ }\r
+ \r
+ public static Object setGraph(Object graph) {\r
+ if (graph==null) {\r
+ transactions.set(null);\r
+ return null;\r
+ }\r
+ \r
+ {\r
+ Object oldGraph = null;\r
+ TransactionInfo t = transactions.get();\r
+ if (t!=null) { \r
+ oldGraph = t.rg;\r
+ if (graph instanceof WriteGraph) {\r
+ t.wg = (WriteGraph) graph;\r
+ t.rg = (ReadGraph) graph;\r
+ } else if (graph instanceof ReadGraph) {\r
+ t.wg = null;\r
+ t.rg = (ReadGraph) graph;\r
+ } else {\r
+ throw new RuntimeDatabaseException("Not a sync graph");\r
+ } \r
+ } else {\r
+ t = new TransactionInfo(graph);\r
+ }\r
+ transactions.set(t);\r
+ return oldGraph;\r
+ }\r
+ }\r
+ \r
+ public static void startTransaction(RequestProcessor processor, boolean write) throws DatabaseException {\r
+ startTransaction(processor, write ? Type.WRITE : Type.READ);\r
+ }\r
+ \r
+ public static void startTransaction(RequestProcessor processor, Type type) throws DatabaseException {\r
+ switch (type) {\r
+ case READ:\r
+ {\r
+ if (transactions.get()!=null) throw new RuntimeDatabaseException("There is already a transaction.");\r
+ final Semaphore started = new Semaphore(0);\r
+ final TransactionInfo t = new TransactionInfo();\r
+ t.es = new Semaphore(0);\r
+ t.ts = new Semaphore(0);\r
+ transactions.set(t);\r
+\r
+ Read<Object> request = new Read<Object>() {\r
+ @Override\r
+ public Object perform(ReadGraph g) throws DatabaseException {\r
+ t.wg = null;\r
+ t.rg = g;\r
+ started.release();\r
+ try {\r
+ t.ts.acquire();\r
+ } catch (InterruptedException e) {\r
+ }\r
+ return null;\r
+ }\r
+ };\r
+ Procedure<Object> procedure = new Procedure<Object>() {\r
+ @Override\r
+ public void execute(Object result) {\r
+ t.es.release(9999);\r
+ }\r
+ @Override\r
+ public void exception(Throwable ex) {\r
+ if (ex instanceof DatabaseException)\r
+ t.error = (DatabaseException) ex;\r
+ else {\r
+ t.error = new DatabaseException(ex);\r
+ }\r
+ t.es.release(9999);\r
+ }\r
+ };\r
+\r
+ processor.asyncRequest(request, procedure);\r
+\r
+ // Wait until transaction has started\r
+ try {\r
+ // Sleep this thread until transaction has started\r
+ started.acquire(1);\r
+ } catch (InterruptedException e) {\r
+ throw new DatabaseException("Thread was interrupted.");\r
+ } finally {\r
+ }\r
+ }\r
+ break;\r
+\r
+ case WRITE:\r
+ {\r
+ if (transactions.get()!=null) throw new RuntimeDatabaseException("There is already a transaction.");\r
+ final Semaphore started = new Semaphore(0);\r
+ final TransactionInfo t = new TransactionInfo();\r
+ t.es = new Semaphore(0);\r
+ t.ts = new Semaphore(0);\r
+ transactions.set(t);\r
+\r
+ Callback<DatabaseException> callback = new Callback<DatabaseException>() {\r
+ @Override\r
+ public void run(DatabaseException parameter) {\r
+ t.error = parameter;\r
+ t.es.release(9999);\r
+ }\r
+ };\r
+\r
+ Write request = new Write() { \r
+ @Override\r
+ public void perform(WriteGraph g) throws DatabaseException {\r
+ t.wg = g;\r
+ t.rg = g;\r
+ started.release();\r
+ try {\r
+ t.ts.acquire();\r
+ } catch (InterruptedException e) {\r
+ }\r
+ if (!t.commit) throw new CancelTransactionException();\r
+ }\r
+ @Override\r
+ public UndoTraits getUndoTraits() {\r
+ return null;\r
+ }\r
+ @Override\r
+ public VirtualGraph getProvider() {\r
+ return null;\r
+ }\r
+ };\r
+\r
+ processor.asyncRequest( request, callback );\r
+\r
+ // Wait until transaction has started\r
+ try {\r
+ // Sleep this thread until transaction has started\r
+ started.acquire(1);\r
+ } catch (InterruptedException e) {\r
+ throw new DatabaseException("Thread was interrupted.");\r
+ } finally {\r
+ }\r
+ }\r
+ break;\r
+\r
+ case DELAYED_WRITE:\r
+ {\r
+ if (transactions.get()!=null) throw new RuntimeDatabaseException("There is already a transaction.");\r
+ final Semaphore started = new Semaphore(0);\r
+ final TransactionInfo t = new TransactionInfo();\r
+ t.es = new Semaphore(0);\r
+ t.ts = new Semaphore(0);\r
+ transactions.set(t);\r
+\r
+ Callback<DatabaseException> callback = new Callback<DatabaseException>() {\r
+ @Override\r
+ public void run(DatabaseException parameter) {\r
+ t.error = parameter;\r
+ t.es.release(9999);\r
+ }\r
+ };\r
+\r
+ DelayedWrite request = new DelayedWriteRequest() { \r
+ @Override\r
+ public void perform(WriteGraph g) throws DatabaseException {\r
+ t.wg = g;\r
+ t.rg = g;\r
+ started.release();\r
+ try {\r
+ t.ts.acquire();\r
+ } catch (InterruptedException e) {\r
+ }\r
+ if (!t.commit) throw new CancelTransactionException();\r
+ }\r
+ };\r
+\r
+ processor.asyncRequest( request, callback );\r
+\r
+ // Wait until transaction has started\r
+ try {\r
+ // Sleep this thread until transaction has started\r
+ started.acquire(1);\r
+ } catch (InterruptedException e) {\r
+ throw new DatabaseException("Thread was interrupted.");\r
+ } finally {\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * Commits transaction if no error occurred \r
+ * \r
+ * @throws DatabaseException\r
+ */\r
+ public static void endTransaction() throws DatabaseException {\r
+ TransactionInfo t = transactions.get();\r
+ if (t == null) return; //throw new RuntimeDatabaseException("There is no transaction to commit.");\r
+ \r
+ t.ts.release(9999);\r
+ \r
+ try {\r
+ t.es.acquire();\r
+ } catch (InterruptedException e) {\r
+ throw new DatabaseException(e);\r
+ } \r
+ \r
+ if (t.error!=null) {\r
+ if (t.error instanceof CancelTransactionException==false) throw t.error; \r
+ }\r
+ transactions.set(null);\r
+ }\r
+\r
+ /**\r
+ * Commits transaction \r
+ * \r
+ * @throws DatabaseException\r
+ */\r
+ public static void commit() throws DatabaseException {\r
+ TransactionInfo t = transactions.get();\r
+ if (t == null) throw new RuntimeDatabaseException("There is not transaction to commit.");\r
+ t.commit = true;\r
+ endTransaction();\r
+ }\r
+ \r
+ public static String getURI(Resource resource) throws ResourceNotFoundException, ValidationException, ServiceException {\r
+ return readGraph().getPossibleURI(resource);\r
+ }\r
+ \r
+ public static String getPossibleURI(Resource resource) throws ResourceNotFoundException, ValidationException, ServiceException {\r
+ return readGraph().getPossibleURI(resource);\r
+ }\r
+ \r
+ public static Resource getResource(String uri) throws ResourceNotFoundException, ValidationException, ServiceException \r
+ {\r
+ return readGraph().getResource(uri);\r
+ }\r
+\r
+ public static Resource getPossibleResource(String uri) throws ResourceNotFoundException, ValidationException, ServiceException\r
+ {\r
+ return readGraph().getPossibleResource(uri);\r
+ }\r
+ \r
+ public static Resource getBuiltin(String id) throws ResourceNotFoundException, ServiceException\r
+ {\r
+ return readGraph().getBuiltin(id);\r
+ }\r
+\r
+ public static Collection<Statement> getStatements(Resource subject, Resource relation) throws ManyObjectsForFunctionalRelationException, ServiceException\r
+ {\r
+ return readGraph().getStatements(subject, relation);\r
+ }\r
+\r
+ public static Collection<Statement> getAssertedStatements(Resource subject, Resource relation) throws ManyObjectsForFunctionalRelationException, ServiceException\r
+ {\r
+ return readGraph().getAssertedStatements(subject, relation); \r
+ } \r
+ \r
+ public static Collection<Resource> getPredicates(Resource subject) throws ServiceException\r
+ {\r
+ return readGraph().getPredicates(subject); \r
+ }\r
+\r
+ public static Collection<Resource> getPrincipalTypes(Resource subject) throws ServiceException\r
+ {\r
+ return readGraph().getPrincipalTypes(subject);\r
+ }\r
+\r
+ public static Set<Resource> getTypes(Resource subject) throws ServiceException\r
+ {\r
+ return readGraph().getTypes(subject);\r
+ }\r
+\r
+ public static Set<Resource> getSupertypes(Resource subject) throws ServiceException\r
+ {\r
+ return readGraph().getSupertypes(subject);\r
+ }\r
+\r
+ public static Set<Resource> getSuperrelations(Resource subject) throws ServiceException\r
+ {\r
+ return readGraph().getSuperrelations(subject);\r
+ }\r
+\r
+ public static Collection<Resource> getObjects(Resource subject, Resource relation) throws ManyObjectsForFunctionalRelationException, ServiceException\r
+ {\r
+ return readGraph().getObjects(subject, relation);\r
+ }\r
+\r
+ public static Collection<Resource> getAssertedObjects(Resource subject, Resource relation) throws ManyObjectsForFunctionalRelationException, ServiceException\r
+ {\r
+ return readGraph().getAssertedObjects(subject, relation);\r
+ }\r
+ \r
+ public static Resource getInverse(Resource relation) throws NoInverseException, ManyObjectsForFunctionalRelationException, ServiceException\r
+ {\r
+ return readGraph().getInverse(relation);\r
+ }\r
+ \r
+ public static Resource getSingleObject(Resource subject, Resource relation) throws NoSingleResultException, ManyObjectsForFunctionalRelationException, ServiceException\r
+ {\r
+ return readGraph().getSingleObject(subject, relation);\r
+ }\r
+ \r
+ public static Statement getSingleStatement(Resource subject, Resource relation) throws NoSingleResultException, ManyObjectsForFunctionalRelationException, ServiceException\r
+ {\r
+ return readGraph().getSingleStatement(subject, relation);\r
+ }\r
+\r
+ public static Resource getSingleType(Resource subject) throws NoSingleResultException, ServiceException\r
+ {\r
+ return readGraph().getSingleType(subject);\r
+ }\r
+ \r
+ public static Resource getSingleType(Resource subject, Resource baseType) throws NoSingleResultException, ServiceException\r
+ {\r
+ return readGraph().getSingleType(subject, baseType);\r
+ }\r
+\r
+ public static <T> T getValue(Resource subject) throws DoesNotContainValueException, ServiceException\r
+ {\r
+ return readGraph().<T>getValue(subject);\r
+ }\r
+\r
+ public static <T> T getValue(Resource subject, Binding binding) throws DoesNotContainValueException, BindingException, ServiceException\r
+ {\r
+ return readGraph().<T>getValue(subject, binding);\r
+ }\r
+\r
+ public static <T> T getRelatedValue(Resource subject, Resource relation) throws NoSingleResultException, DoesNotContainValueException, ServiceException\r
+ {\r
+ return readGraph().<T>getRelatedValue(subject, relation);\r
+ }\r
+\r
+ public static <T> T getRelatedValue(Resource subject, Resource relation, Binding binding) throws NoSingleResultException, DoesNotContainValueException, BindingException, ServiceException\r
+ {\r
+ return readGraph().<T>getRelatedValue(subject, relation, binding);\r
+ }\r
+\r
+ public static <T> T adapt(Resource resource, Class<T> clazz) throws AdaptionException, ValidationException, ServiceException\r
+ {\r
+ return readGraph().adapt(resource, clazz);\r
+ }\r
+\r
+ public static <T> T adaptUnique(Resource resource, Class<T> clazz) throws AdaptionException, ValidationException, ServiceException\r
+ {\r
+ return readGraph().adaptUnique(resource, clazz);\r
+ }\r
+ \r
+ public static Resource getPossibleInverse(Resource relation) throws ManyObjectsForFunctionalRelationException, ServiceException\r
+ {\r
+ return readGraph().getPossibleInverse(relation);\r
+ }\r
+ \r
+ public static Resource getPossibleObject(Resource subject, Resource relation) throws ManyObjectsForFunctionalRelationException, ServiceException\r
+ {\r
+ return readGraph().getPossibleObject(subject, relation);\r
+ }\r
+ \r
+ public static Statement getPossibleStatement(Resource subject, Resource relation) throws ManyObjectsForFunctionalRelationException, ServiceException\r
+ {\r
+ return readGraph().getPossibleStatement(subject, relation);\r
+ }\r
+ \r
+ public static Resource getPossibleType(Resource subject, Resource baseType) throws ServiceException\r
+ {\r
+ return readGraph().getPossibleType(subject, baseType);\r
+ }\r
+ \r
+ public static <T> T getPossibleValue(Resource subject) throws ServiceException\r
+ {\r
+ return readGraph().<T>getPossibleValue(subject);\r
+ }\r
+ \r
+ public static <T> T getPossibleValue(Resource subject, Binding binding) throws BindingException, ServiceException\r
+ {\r
+ return readGraph().<T>getPossibleValue(subject, binding);\r
+ }\r
+\r
+ public static <T> T getPossibleRelatedValue(Resource subject, Resource relation) throws ManyObjectsForFunctionalRelationException, ServiceException\r
+ {\r
+ return readGraph().<T>getPossibleRelatedValue(subject, relation);\r
+ }\r
+ \r
+ public static <T> T getPossibleRelatedValue(Resource subject, Resource relation, Binding binding) throws ManyObjectsForFunctionalRelationException, BindingException, ServiceException\r
+ {\r
+ return readGraph().<T>getPossibleRelatedValue(subject, relation, binding);\r
+ }\r
+ \r
+ public static <T> T getPossibleAdapter(Resource resource, Class<T> clazz) throws ValidationException, ServiceException\r
+ {\r
+ return readGraph().<T>getPossibleAdapter(resource, clazz);\r
+ }\r
+ \r
+ public static <T> T getPossibleUniqueAdapter(Resource resource, Class<T> clazz) throws ValidationException, ServiceException\r
+ {\r
+ return readGraph().<T>getPossibleUniqueAdapter(resource, clazz);\r
+ }\r
+ \r
+ public static boolean isInstanceOf(Resource resource, Resource type) throws ServiceException\r
+ {\r
+ return readGraph().isInstanceOf(resource, type);\r
+ }\r
+ \r
+ public static boolean isInheritedFrom(Resource resource, Resource type) throws ServiceException\r
+ {\r
+ return readGraph().isInheritedFrom(resource, type);\r
+ }\r
+ \r
+ public static boolean isSubrelationOf(Resource resource, Resource relation) throws ServiceException\r
+ {\r
+ return readGraph().isSubrelationOf(resource, relation);\r
+ }\r
+ \r
+ public static boolean hasStatement(Resource subject) throws ServiceException\r
+ {\r
+ return readGraph().hasStatement(subject);\r
+ }\r
+ \r
+ public static boolean hasStatement(Resource subject, Resource relation) throws ServiceException\r
+ {\r
+ return readGraph().hasStatement(subject, relation);\r
+ }\r
+ \r
+ public static boolean hasStatement(Resource subject, Resource relation, Resource object) throws ServiceException\r
+ {\r
+ return readGraph().hasStatement(subject, relation, object);\r
+ }\r
+ \r
+ public static boolean hasValue(Resource subject) throws ServiceException\r
+ {\r
+ return readGraph().hasValue(subject);\r
+ }\r
+ \r
+ public static Datatype getDataType(Resource subject) throws DatabaseException\r
+ {\r
+ return readGraph().getDataType(subject);\r
+ }\r
+ \r
+ public static <T extends Accessor> T getAccessor(Resource subject) throws DatabaseException\r
+ {\r
+ return readGraph().<T>getAccessor(subject);\r
+ }\r
+ \r
+ \r
+ /**\r
+ * Makes sure that the statements (s,p,o) and (o,p',s) are found in the\r
+ * graph, where p' is the inverse predicate of p. Contrary to\r
+ * {@link WriteOnlyGraph#claim(Resource, Resource, Resource, Resource)} this\r
+ * method assures that the the statement and its inverse are semantically\r
+ * valid after the invocation of this method.\r
+ * \r
+ * @param subject subject, i.e. source resource of the statement to be\r
+ * claimed\r
+ * @param predicate predicate resource of the statement to be claimed\r
+ * @param object object, i.e. target resource of the statement to be claimed\r
+ * @throws ServiceException\r
+ */\r
+ public static void claim(Resource subject, Resource predicate, Resource object) throws ServiceException {\r
+ writeGraph().claim(subject, predicate, object);\r
+ }\r
+\r
+ /**\r
+ * Sets literal value related to the specified resource with the specified\r
+ * predicate. If such value exists (s,p), the value is overridden with the\r
+ * new specified value.\r
+ * \r
+ * @param resource\r
+ * @param predicate\r
+ * @param value Value of the literal (boxed primitive/String or\r
+ * primitive/String array)\r
+ * @throws ManyObjectsForFunctionalRelationException\r
+ */\r
+ public static void claimValue(Resource resource, Resource predicate, Object value)\r
+ throws ManyObjectsForFunctionalRelationException, ServiceException, DatabaseException {\r
+ writeGraph().claimLiteral(resource, predicate, value);\r
+ }\r
+ public static void claimValue(Resource resource, Resource predicate, Object value, Binding binding)\r
+ throws BindingException, ManyObjectsForFunctionalRelationException, ServiceException, DatabaseException {\r
+ writeGraph().claimValue(resource, value, binding);\r
+ }\r
+ public static void claimValue(Resource resource, Resource predicate, Resource inverse, Resource type, Object value, Binding binding)\r
+ throws BindingException, ManyObjectsForFunctionalRelationException, ServiceException, DatabaseException {\r
+ writeGraph().claimLiteral(resource, predicate, inverse, type, value, binding);\r
+ }\r
+\r
+ /**\r
+ * Makes sure that no statements matching the patterns (s,?p,?o) and\r
+ * (?o,?p',s), where ?p' is the inverse predicate of ?p, exist in the graph.\r
+ * In other words, removes all statements outgoing from the specified\r
+ * resource along with the inverses of those statements.\r
+ * \r
+ * @param subject\r
+ * @throws ServiceException\r
+ */\r
+ public static void deny(Resource subject) throws ServiceException {\r
+ writeGraph().deny(subject);\r
+ }\r
+\r
+ /**\r
+ * Makes sure that no statements matching the patterns (s,p,?o) and\r
+ * (?o,p',s), where p' is the inverse predicate of p, exist in the graph.\r
+ * Also statements where <code>isSubrelationOf(p, predicate)</code> returns\r
+ * <code>true</code> shall be removed. In other words, removes all\r
+ * statements outgoing from the specified resource with the specified\r
+ * predicate or any of its subrelations, along with the inverses of those\r
+ * statements.\r
+ * \r
+ * @param subject\r
+ * @throws ServiceException\r
+ */\r
+ public static void deny(Resource subject, Resource predicate) throws ServiceException {\r
+ writeGraph().deny(subject, predicate);\r
+ }\r
+\r
+ /**\r
+ * Makes sure that no statements matching the patterns (s,p,o) and (o,p',s),\r
+ * where p' is the inverse predicate of p, exist in the graph. Contrary to\r
+ * {@link #denyStatement(Resource, Resource, Resource)}, all statements\r
+ * where <code>isSubrelationOf(p, predicate)</code> returns\r
+ * <code>true</code> shall be removed. In other words, removes all\r
+ * statements between the specified subject and object with the specified\r
+ * predicate or any of its subrelations, along with the inverses of those\r
+ * statements.\r
+ * \r
+ * @param subject\r
+ * @param predicate\r
+ * @param object\r
+ * @throws ServiceException\r
+ */\r
+ public static void deny(Resource subject, Resource predicate, Resource object) throws ServiceException {\r
+ writeGraph().deny(subject, predicate, object);\r
+ }\r
+\r
+ /**\r
+ * Makes sure that no statements matching the patterns (s,p,o) and (o,p',s),\r
+ * where p' is the inverse predicate of p, exist in the graph. In other\r
+ * words, removes the specified statement and its possible inverse.\r
+ * \r
+ * <p>\r
+ * This method behaves exactly like {@link #deny(Statement)}, it just takes\r
+ * the arguments as resources instead of a statement.\r
+ * \r
+ * @param subject\r
+ * @throws ServiceException\r
+ * \r
+ * @see {@link #deny(Statement)}\r
+ */\r
+ public static void denyStatement(Resource subject, Resource predicate, Resource object) throws ServiceException {\r
+ writeGraph().denyStatement(subject, predicate, object);\r
+ }\r
+\r
+ /**\r
+ * Makes sure that the specified statements (s,p,o) and its inverse\r
+ * statements (o,p',s), where p' is the inverse predicate of p, do not exist\r
+ * in the graph.\r
+ * \r
+ * <p>\r
+ * This method behaves exactly like\r
+ * {@link #denyStatement(Resource, Resource, Resource)}, it just takes the\r
+ * arguments as a statement instead of 3 resources.\r
+ * \r
+ * @param statement\r
+ * \r
+ * @see #denyStatement(Resource, Resource, Resource)\r
+ */\r
+ public static void deny(Statement statement) throws ServiceException {\r
+ writeGraph().deny(statement);\r
+ }\r
+\r
+ /**\r
+ * Removes all statements (resource,predicate,?o) and literal contained by\r
+ * ?o.\r
+ * \r
+ * @param resource\r
+ * @param predicate\r
+ * @throws ManyObjectsForFunctionalRelationException\r
+ */\r
+ public static void denyValue(Resource resource, Resource predicate) throws ManyObjectsForFunctionalRelationException, ServiceException {\r
+ writeGraph().denyValue(resource, predicate);\r
+ }\r
+ \r
+}\r
+\r