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