X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.db.common%2Fsrc%2Forg%2Fsimantics%2Fdb%2Fcommon%2Futils%2FTransaction.java;h=96d915482e53b91efb9f5e536d7d0e0d480a3868;hb=0d9b90834ce56b292c00b1a39850ed842c3e4d42;hp=f3d38c5eb5256262a7151e50cddef35c3efdd26a;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/Transaction.java b/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/Transaction.java index f3d38c5eb..96d915482 100644 --- a/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/Transaction.java +++ b/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/Transaction.java @@ -1,702 +1,687 @@ -/******************************************************************************* - * 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 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.VirtualGraph; -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.UndoTraits; -import org.simantics.db.request.Write; -import org.simantics.utils.datastructures.Callback; - -/** - * Synchronous Transaction.

- * - * 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 - */ -public class Transaction { - - public static enum Type { - READ, - WRITE, - DELAYED_WRITE - } - - /** Thread local transactions */ - private static ThreadLocal transactions = new ThreadLocal(); - - 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 request = new Read() { - @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 procedure = new Procedure() { - @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); - - Callback callback = new Callback() { - @Override - public void run(DatabaseException 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(); - } - @Override - public UndoTraits getUndoTraits() { - return null; - } - @Override - public VirtualGraph getProvider() { - return null; - } - }; - - 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); - - Callback callback = new Callback() { - @Override - public void run(DatabaseException 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 getStatements(Resource subject, Resource relation) throws ManyObjectsForFunctionalRelationException, ServiceException - { - return readGraph().getStatements(subject, relation); - } - - public static Collection getAssertedStatements(Resource subject, Resource relation) throws ManyObjectsForFunctionalRelationException, ServiceException - { - return readGraph().getAssertedStatements(subject, relation); - } - - public static Collection getPredicates(Resource subject) throws ServiceException - { - return readGraph().getPredicates(subject); - } - - public static Collection getPrincipalTypes(Resource subject) throws ServiceException - { - return readGraph().getPrincipalTypes(subject); - } - - public static Set getTypes(Resource subject) throws ServiceException - { - return readGraph().getTypes(subject); - } - - public static Set getSupertypes(Resource subject) throws ServiceException - { - return readGraph().getSupertypes(subject); - } - - public static Set getSuperrelations(Resource subject) throws ServiceException - { - return readGraph().getSuperrelations(subject); - } - - public static Collection getObjects(Resource subject, Resource relation) throws ManyObjectsForFunctionalRelationException, ServiceException - { - return readGraph().getObjects(subject, relation); - } - - public static Collection 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 getValue(Resource subject) throws DoesNotContainValueException, ServiceException - { - return readGraph().getValue(subject); - } - - public static T getValue(Resource subject, Binding binding) throws DoesNotContainValueException, BindingException, ServiceException - { - return readGraph().getValue(subject, binding); - } - - public static T getRelatedValue(Resource subject, Resource relation) throws NoSingleResultException, DoesNotContainValueException, ServiceException - { - return readGraph().getRelatedValue(subject, relation); - } - - public static T getRelatedValue(Resource subject, Resource relation, Binding binding) throws NoSingleResultException, DoesNotContainValueException, BindingException, ServiceException - { - return readGraph().getRelatedValue(subject, relation, binding); - } - - public static T adapt(Resource resource, Class clazz) throws AdaptionException, ValidationException, ServiceException - { - return readGraph().adapt(resource, clazz); - } - - public static T adaptUnique(Resource resource, Class 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 getPossibleValue(Resource subject) throws ServiceException - { - return readGraph().getPossibleValue(subject); - } - - public static T getPossibleValue(Resource subject, Binding binding) throws BindingException, ServiceException - { - return readGraph().getPossibleValue(subject, binding); - } - - public static T getPossibleRelatedValue(Resource subject, Resource relation) throws ManyObjectsForFunctionalRelationException, ServiceException - { - return readGraph().getPossibleRelatedValue(subject, relation); - } - - public static T getPossibleRelatedValue(Resource subject, Resource relation, Binding binding) throws ManyObjectsForFunctionalRelationException, BindingException, ServiceException - { - return readGraph().getPossibleRelatedValue(subject, relation, binding); - } - - public static T getPossibleAdapter(Resource resource, Class clazz) throws ValidationException, ServiceException - { - return readGraph().getPossibleAdapter(resource, clazz); - } - - public static T getPossibleUniqueAdapter(Resource resource, Class clazz) throws ValidationException, ServiceException - { - return readGraph().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 getAccessor(Resource subject) throws DatabaseException - { - return readGraph().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 isSubrelationOf(p, predicate) returns - * true 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 isSubrelationOf(p, predicate) returns - * true 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. - * - *

- * 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. - * - *

- * 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); - } - -} - +/******************************************************************************* + * 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.AsyncRequestProcessor; +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.

+ * + * 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 + */ +public class Transaction { + + public static enum Type { + READ, + WRITE, + DELAYED_WRITE + } + + /** Thread local transactions */ + private static ThreadLocal transactions = new ThreadLocal(); + + 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(AsyncRequestProcessor processor, boolean write) throws DatabaseException { + startTransaction(processor, write ? Type.WRITE : Type.READ); + } + + public static void startTransaction(AsyncRequestProcessor 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 request = new Read() { + @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 procedure = new Procedure() { + @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 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 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 getStatements(Resource subject, Resource relation) throws ManyObjectsForFunctionalRelationException, ServiceException + { + return readGraph().getStatements(subject, relation); + } + + public static Collection getAssertedStatements(Resource subject, Resource relation) throws ManyObjectsForFunctionalRelationException, ServiceException + { + return readGraph().getAssertedStatements(subject, relation); + } + + public static Collection getPredicates(Resource subject) throws ServiceException + { + return readGraph().getPredicates(subject); + } + + public static Collection getPrincipalTypes(Resource subject) throws ServiceException + { + return readGraph().getPrincipalTypes(subject); + } + + public static Set getTypes(Resource subject) throws ServiceException + { + return readGraph().getTypes(subject); + } + + public static Set getSupertypes(Resource subject) throws ServiceException + { + return readGraph().getSupertypes(subject); + } + + public static Set getSuperrelations(Resource subject) throws ServiceException + { + return readGraph().getSuperrelations(subject); + } + + public static Collection getObjects(Resource subject, Resource relation) throws ManyObjectsForFunctionalRelationException, ServiceException + { + return readGraph().getObjects(subject, relation); + } + + public static Collection 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 getValue(Resource subject) throws DoesNotContainValueException, ServiceException + { + return readGraph().getValue(subject); + } + + public static T getValue(Resource subject, Binding binding) throws DoesNotContainValueException, BindingException, ServiceException + { + return readGraph().getValue(subject, binding); + } + + public static T getRelatedValue(Resource subject, Resource relation) throws NoSingleResultException, DoesNotContainValueException, ServiceException + { + return readGraph().getRelatedValue(subject, relation); + } + + public static T getRelatedValue(Resource subject, Resource relation, Binding binding) throws NoSingleResultException, DoesNotContainValueException, BindingException, ServiceException + { + return readGraph().getRelatedValue(subject, relation, binding); + } + + public static T adapt(Resource resource, Class clazz) throws AdaptionException, ValidationException, ServiceException + { + return readGraph().adapt(resource, clazz); + } + + public static T adaptUnique(Resource resource, Class 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 getPossibleValue(Resource subject) throws ServiceException + { + return readGraph().getPossibleValue(subject); + } + + public static T getPossibleValue(Resource subject, Binding binding) throws BindingException, ServiceException + { + return readGraph().getPossibleValue(subject, binding); + } + + public static T getPossibleRelatedValue(Resource subject, Resource relation) throws ManyObjectsForFunctionalRelationException, ServiceException + { + return readGraph().getPossibleRelatedValue(subject, relation); + } + + public static T getPossibleRelatedValue(Resource subject, Resource relation, Binding binding) throws ManyObjectsForFunctionalRelationException, BindingException, ServiceException + { + return readGraph().getPossibleRelatedValue(subject, relation, binding); + } + + public static T getPossibleAdapter(Resource resource, Class clazz) throws ValidationException, ServiceException + { + return readGraph().getPossibleAdapter(resource, clazz); + } + + public static T getPossibleUniqueAdapter(Resource resource, Class clazz) throws ValidationException, ServiceException + { + return readGraph().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 getAccessor(Resource subject) throws DatabaseException + { + return readGraph().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 isSubrelationOf(p, predicate) returns + * true 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 isSubrelationOf(p, predicate) returns + * true 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. + * + *

+ * 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. + * + *

+ * 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); + } + +} +