X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;ds=inline;f=bundles%2Forg.simantics.db.common%2Fsrc%2Forg%2Fsimantics%2Fdb%2Fcommon%2Futils%2FOrderedSetUtils.java;h=eb0ca24b6a5fa32e318936dfbfe54ce5a8a42f79;hb=ba771b441183e53a5fa12b013ad3710ed2da32e1;hp=3e2331a8c63f66a0291a9928369c5136be6b4438;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git
diff --git a/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/OrderedSetUtils.java b/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/OrderedSetUtils.java
index 3e2331a8c..eb0ca24b6 100644
--- a/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/OrderedSetUtils.java
+++ b/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/OrderedSetUtils.java
@@ -1,626 +1,626 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management
- * in Industry THTH ry.
- * 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.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Set;
-
-import org.simantics.databoard.Bindings;
-import org.simantics.db.AsyncReadGraph;
-import org.simantics.db.ReadGraph;
-import org.simantics.db.Resource;
-import org.simantics.db.WriteGraph;
-import org.simantics.db.WriteOnlyGraph;
-import org.simantics.db.common.request.ReadRequest;
-import org.simantics.db.exception.DatabaseException;
-import org.simantics.db.exception.RuntimeDatabaseException;
-import org.simantics.db.exception.ValidationException;
-import org.simantics.db.function.DbFunction;
-import org.simantics.db.procedure.AsyncMultiProcedure;
-import org.simantics.layer0.Layer0;
-import org.simantics.utils.datastructures.Pair;
-
-public class OrderedSetUtils {
-
- /**
- * Returns true, if l contains the element el.
- */
- public static boolean contains(ReadGraph g, Resource l, Resource el) throws DatabaseException {
- return g.hasStatement(el, l) && !l.equals(el);
- }
-
- /**
- * Returns the next element in the ordered set or l,
- * if el is the last element. Called for el, returns
- * the first element in the set.
- */
- public static Resource next(ReadGraph g, Resource l, Resource el) throws DatabaseException {
- Collection nexts = g.getObjects(el, l);
- if(nexts.size() != 1)
- throw new InvalidOrderedSetException("Invalid list element: " + l + " " + el + " " + nexts.size() + " successors.");
- for(Resource r : nexts)
- return r;
- return null;
- }
-
- public static void forNext(AsyncReadGraph g, final Resource l, Resource el, final AsyncMultiProcedure procedure) {
- g.forEachObject(el, l, new AsyncMultiProcedure() {
-
- @Override
- public void exception(AsyncReadGraph graph, Throwable t) {
- procedure.exception(graph, t);
- }
-
- @Override
- public void finished(AsyncReadGraph graph) {
- }
-
- @Override
- public void execute(AsyncReadGraph graph, Resource nel) {
- if(!nel.equals(l)) {
- procedure.execute(graph, nel);
- forNext(graph, l, nel, procedure);
- }
- }
- });
-// Collection nexts = g.getObjects(el, l);
-// if(nexts.size() != 1)
-// throw new NoSingleResultException("Invalid list element: " + nexts.size() + " successors.");
-// for(Resource r : nexts)
-// return r;
-// return null;
- }
-
- /**
- * Returns the previouse element in the ordered set or l,
- * if el is the first element. Called for el, returns
- * the last element in the set.
- */
- public static Resource prev(ReadGraph g, Resource l, Resource el) throws DatabaseException {
- Collection prevs = g.getObjects(el, g.getInverse(l));
- if(prevs.size() != 1) {
- throw new InvalidOrderedSetException("Invalid list element, " + prevs.size() + " predecessors.");
- }
- for(Resource r : prevs)
- return r;
- return null;
- }
-
- /**
- * Adds a given elements el to the list l. Returns
- * true, if the element was really added.
- */
- public static boolean add(WriteGraph g, Resource l, Resource el) throws DatabaseException {
- if(g.hasStatement(el, l))
- return false;
- Resource back = prev(g, l, l);
- g.denyStatement(back, l, l);
- g.claim(back, l, el);
- g.claim(el, l, l);
- return true;
- }
-
- /**
- * Adds a given elements el to the list l. Returns
- * true, if the element was really added.
- */
- public static boolean addFirst(WriteGraph g, Resource l, Resource el) throws DatabaseException {
- return addAfter(g, l, l, el);
- }
-
- public static boolean addAll(WriteGraph g, Resource l, Iterable els) throws DatabaseException {
- for(Resource r : els)
- if(g.hasStatement(r, l))
- return false;
- Resource cur = prev(g, l, l);
- g.denyStatement(cur, l, l);
- for(Resource r : els) {
- g.claim(cur, l, r);
- cur = r;
- }
- g.claim(cur, l, l);
- return true;
- }
-
- public static boolean addAllNew(WriteGraph g, Resource l, Iterable els) throws DatabaseException {
- Resource cur = prev(g, l, l);
- Resource inv = g.getInverse(l);
- g.deny(cur, l, inv, l);
- for(Resource r : els) {
- g.claim(cur, l, inv, r);
- cur = r;
- }
- g.claim(cur, l, inv, l);
- return true;
- }
-
- public static boolean addAfter(WriteGraph g, Resource l, Resource pos, Resource el) throws DatabaseException {
- if(g.hasStatement(el, l))
- return false;
- Resource next = next(g, l, pos);
- g.denyStatement(pos, l, next);
- g.claim(pos, l, el);
- g.claim(el, l, next);
- return true;
- }
-
- public static boolean addBefore(WriteGraph g, Resource l, Resource pos, Resource el) throws DatabaseException {
- if(g.hasStatement(el, l))
- return false;
- Resource prev = prev(g, l, pos);
- g.denyStatement(prev, l, pos);
- g.claim(prev, l, el);
- g.claim(el, l, pos);
- return true;
- }
-
- /**
- * Removes a given elements el from the list l. Returns
- * true, if the element was really removed.
- */
- public static boolean remove(WriteGraph g, Resource l, Resource el) throws DatabaseException {
- Collection nexts = g.getObjects(el, l);
- if(nexts.size() == 0)
- return false;
- if(nexts.size() != 1)
- throw new InvalidOrderedSetException("Invalid list element.");
- Collection prevs = g.getObjects(el, g.getInverse(l));
- if(prevs.size() != 1)
- throw new InvalidOrderedSetException("Invalid list element.");
-
- for(Resource p : prevs)
- for(Resource n : nexts) {
- g.denyStatement(p, l, el);
- g.denyStatement(el, l, n);
- g.claim(p, l, n);
- return true;
- }
- return true;
- }
-
- public static List removeList(WriteGraph g, Resource l) throws DatabaseException {
- List els = toList(g, l);
- for(Resource el : els)
- g.deny(el, l);
- g.deny(l, l);
- Resource inv = g.getInverse(l);
- g.deny(l);
- g.deny(inv);
- return els;
- }
-
- public static void replace(WriteGraph g, Resource l, Resource oldEl, Resource newEl) throws DatabaseException {
- Collection nexts = g.getObjects(oldEl, l);
- if(nexts.size() != 1)
- throw new InvalidOrderedSetException("Invalid list element.");
- Collection prevs = g.getObjects(oldEl, g.getInverse(l));
- if(prevs.size() != 1)
- throw new InvalidOrderedSetException("Invalid list element.");
-
- for(Resource p : prevs)
- for(Resource n : nexts) {
- g.denyStatement(p, l, oldEl);
- g.denyStatement(oldEl, l, n);
- g.claim(p, l, newEl);
- g.claim(newEl, l, n);
- return;
- }
- }
-
- /**
- * Converts ordered set into a list.
- */
- public static List toList(ReadGraph g, Resource l) throws DatabaseException {
- ArrayList ret = new ArrayList();
- Resource cur = l;
- while(true) {
- cur = next(g, l, cur);
- if(cur.equals(l))
- return ret;
- ret.add(cur);
- }
- }
-
- /**
- * Converts ordered set into a list.
- */
- public static void forEach(AsyncReadGraph g, final Resource l, final AsyncMultiProcedure procedure) {
- g.asyncRequest(new ReadRequest() {
-
- @Override
- public void run(ReadGraph graph) throws DatabaseException {
- for(Resource r : toList(graph, l))
- procedure.execute(graph, r);
- }
-
- });
- }
-
- /**
- * Creates an empty ordered set.
- */
- public static Resource create(WriteOnlyGraph g, Resource type) throws DatabaseException {
- Layer0 l0 = g.getService(Layer0.class);
- Resource l = g.newResource();
- g.claim(l, l0.InstanceOf, null, type);
- g.claim(l, l0.SubrelationOf, null, l0.HasNext);
- Resource invL = g.newResource();
- g.claim(invL, l0.SubrelationOf, null, l0.HasPrevious);
- g.claim(l, l0.InverseOf, l0.InverseOf, invL);
- g.claim(l, l, invL, l);
- return l;
- }
-
- /**
- * Creates an ordered set containing the given elements.
- * It is assumed that the elements do not contain duplicates.
- */
- @Deprecated
- public static Resource create(WriteOnlyGraph g, Resource type, Iterable c) throws DatabaseException {
- Layer0 l0 = g.getService(Layer0.class);
- Resource l = g.newResource();
- g.claim(l, l0.InstanceOf, null, type);
- g.claim(l, l0.SubrelationOf, null, l0.HasNext);
- Resource invL = g.newResource();
- g.claim(invL, l0.SubrelationOf, null, l0.HasPrevious);
- g.claim(l, l0.InverseOf, l0.InverseOf, invL);
- Resource cur = l;
- for(Resource r : c) {
- g.claim(cur, l, invL, r);
- cur = r;
- }
- g.claim(cur, l, invL, l);
- return l;
- }
-
- public static Resource create(WriteOnlyGraph g, Resource type, String name, Iterable c) throws DatabaseException {
- return createExisting(g, g.newResource(), type, name, c);
- }
-
- public static Resource createExisting(WriteOnlyGraph g, Resource l, Resource type, String name, Iterable c) throws DatabaseException {
- Layer0 l0 = g.getService(Layer0.class);
- g.claim(l, l0.InstanceOf, null, type);
- g.claim(l, l0.SubrelationOf, null, l0.HasNext);
- g.addLiteral(l, l0.HasName, l0.NameOf, l0.String, name, Bindings.STRING);
- Resource invL = g.newResource();
- g.claim(invL, l0.SubrelationOf, null, l0.HasPrevious);
- g.addLiteral(invL, l0.HasName, l0.NameOf, l0.String, "Inverse", Bindings.STRING);
- g.claim(l, l0.InverseOf, l0.InverseOf, invL);
- g.claim(l, l0.ConsistsOf, l0.PartOf, invL);
- Resource cur = l;
- for(Resource r : c) {
- g.claim(cur, l, invL, r);
- cur = r;
- }
- g.claim(cur, l, invL, l);
- return l;
- }
-
- public static Resource create(WriteOnlyGraph g, Resource type, Resource ... c) throws DatabaseException {
- Layer0 l0 = g.getService(Layer0.class);
- Resource l = g.newResource();
- g.claim(l, l0.InstanceOf, null, type);
- g.claim(l, l0.SubrelationOf, null, l0.HasNext);
- Resource invL = g.newResource();
- g.claim(invL, l0.SubrelationOf, null, l0.HasPrevious);
- g.claim(l, l0.InverseOf, l0.InverseOf, invL);
- Resource cur = l;
- for(Resource r : c) {
- g.claim(cur, l, invL, r);
- cur = r;
- }
- g.claim(cur, l, invL, l);
- return l;
- }
-
- public static Resource createExisting(WriteGraph g, Resource l, Resource ... c) throws DatabaseException {
- Layer0 l0 = Layer0.getInstance(g);
- g.claim(l, l0.SubrelationOf, null, l0.HasNext);
- Resource invL = g.newResource();
- g.claim(invL, l0.SubrelationOf, null, l0.HasPrevious);
- g.claim(l, l0.InverseOf, l0.InverseOf, invL);
- Resource cur = l;
- for(Resource r : c) {
- g.claim(cur, l, invL, r);
- cur = r;
- }
- g.claim(cur, l, invL, l);
- return l;
- }
-
-// public static Resource create(GraphWriter graph, Resource type, Iterable c) throws DatabaseException {
-// ReadGraph g = w.getGraph();
-// Builtins b = g.getBuiltins();
-// Resource l = w.create(type).get();
-// w.let(b.SubrelationOf, b.IsRelatedTo);
-// w.createInverse(l).let(b.SubrelationOf, g.getInverse(b.IsRelatedTo));
-//
-// Resource cur = l;
-// for(Resource r : c) {
-// w.stat(cur, l, r);
-// cur = r;
-// }
-// w.stat(cur, l, l);
-// return l;
-// }
-
- public static class OrderedSetIterator implements ListIterator {
-
- ReadGraph g;
- Resource l;
- Resource prev;
- Resource next;
- int index;
- boolean direction;
-
- WriteGraph getWriteGraph() {
- if (!(g instanceof WriteGraph))
- throw new UnsupportedOperationException("");
- return (WriteGraph) g;
- }
-
- public OrderedSetIterator(ReadGraph g, Resource l) throws DatabaseException {
- this.g = g;
- this.l = l;
- this.prev = l;
- this.next = OrderedSetUtils.next(g, l, l);
- this.index = 0;
- }
-
- @Override
- public boolean hasNext() {
- return !next.equals(l);
- }
-
- @Override
- public Resource next() {
- prev = next;
- try {
- next = OrderedSetUtils.next(g, l, next);
- } catch (DatabaseException e) {
- throw new RuntimeDatabaseException(e);
- }
- ++index;
- direction = true;
- return prev;
- }
-
- @Override
- public void remove() {
- try {
- WriteGraph wg = getWriteGraph();
- if(direction) {
- OrderedSetUtils.remove(wg, l, prev);
- prev = OrderedSetUtils.prev(wg, l, next);
- }
- else {
- OrderedSetUtils.remove(wg, l, next);
- next = OrderedSetUtils.next(wg, l, prev);
- }
- } catch (DatabaseException e) {
- throw new RuntimeDatabaseException(e);
- }
- }
-
- @Override
- public void add(Resource e) {
- try {
- WriteGraph wg = getWriteGraph();
- wg.denyStatement(prev, l, next);
- wg.claim(prev, l, e);
- wg.claim(e, l, next);
- prev = e;
- } catch (DatabaseException ex) {
- throw new RuntimeDatabaseException(ex);
- }
- }
-
- @Override
- public boolean hasPrevious() {
- return !prev.equals(l);
- }
-
- @Override
- public int nextIndex() {
- return index;
- }
-
- @Override
- public Resource previous() {
- try {
- next = prev;
- prev = OrderedSetUtils.prev(g, l, prev);
- --index;
- direction = false;
- return next;
- } catch (DatabaseException ex) {
- throw new RuntimeDatabaseException(ex);
- }
- }
-
- @Override
- public int previousIndex() {
- return index-1;
- }
-
- @Override
- public void set(Resource e) {
- try {
- WriteGraph wg = getWriteGraph();
- if(direction) {
- OrderedSetUtils.replace(wg, l, prev, e);
- prev = e;
- }
- else {
- OrderedSetUtils.replace(wg, l, next, e);
- next = e;
- }
- } catch (DatabaseException ex) {
- throw new RuntimeDatabaseException(ex);
- }
- }
-
- }
-
- public static ListIterator iterator(ReadGraph g, Resource l) throws DatabaseException {
- return new OrderedSetIterator(g, l);
- }
-
- public static boolean set(WriteGraph g, Resource l, Iterable els) throws DatabaseException {
-
- // Compute delta
- Set> removed = new HashSet>();
- Collection> added = new ArrayList>();
- Resource cur = l;
- do {
- Resource temp = next(g, l, cur);
- removed.add(new Pair(cur, temp));
- cur = temp;
- } while(!cur.equals(l));
-
- cur = l;
- for(Resource temp : els) {
- Pair pair = new Pair(cur, temp);
- if(!removed.remove(pair))
- added.add(pair);
- cur = temp;
- }
-
- {
- Pair pair = new Pair(cur, l);
- if(!removed.remove(pair))
- added.add(pair);
- }
-
- // Apply
- if(added.isEmpty() && removed.isEmpty())
- return false;
- for(Pair pair : removed)
- g.denyStatement(pair.first, l, pair.second);
- for(Pair pair : added)
- g.claim(pair.first, l, pair.second);
- return true;
- }
-
- /**
- * Retrieves the owner list the specified list element
- *
- * @param g
- * @param el a possible element of a list of the specified type
- * @param listBaseRelation a base relation of the list to look for
- * @return
- */
- public static Resource getSingleOwnerList(ReadGraph g, Resource el, Resource listBaseRelation) throws DatabaseException {
- Collection result = getOwnerLists(g, el, listBaseRelation);
- if (result.size() != 1)
- throw new ValidationException(NameUtils.getSafeName(g, el) + " is part of " + result.size() + " lists of base type " + NameUtils.getSafeName(g, listBaseRelation) + ", expected only one list.");
- return result.iterator().next();
- }
-
- public static Resource getSingleOwnerList(ReadGraph g, Resource el) throws DatabaseException {
- Layer0 l0 = Layer0.getInstance(g);
- Collection result = getOwnerLists(g, el, l0.OrderedSet);
- if (result.size() != 1)
- throw new ValidationException(NameUtils.getSafeName(g, el) + " is part of " + result.size() + " lists of base type L0.OrderedSet, expected only one list.");
- return result.iterator().next();
- }
-
- public static Collection getSubjects(ReadGraph g, Resource object) throws DatabaseException {
- Collection result = new ArrayList(1);
- Layer0 l0 = Layer0.getInstance(g);
- for(Resource pred : g.getPredicates(object)) {
- if(g.isInstanceOf(pred, l0.OrderedSet) && !pred.equals(object))
- result.add(pred);
- }
- return result;
- }
-
- private static void forSubjects(ReadGraph g, Resource object, DbFunction consumer) throws DatabaseException {
- for (Resource pred : g.getPredicates(object)) {
- if (!pred.equals(object))
- if (!consumer.apply(pred))
- break;
- }
- }
-
- /**
- * Retrieves the owner list the specified list element
- *
- * @param g
- * @param el a possible element of a list of the specified type
- * @param listBaseRelation a base relation of the list to look for
- * @return
- */
- public static Collection getOwnerLists(ReadGraph g, Resource el, Resource listBaseRelation) throws DatabaseException {
- Collection result = null;
- Collection rs = getSubjects(g, el);
- for (Resource r : rs) {
- if (g.isInstanceOf(r, listBaseRelation)) {
- if (result == null)
- result = new ArrayList(2);
- result.add(r);
- }
- }
- if (result == null)
- result = Collections.emptyList();
- return result;
- }
-
- private static class PossibleOwnerList implements DbFunction {
- private ReadGraph graph;
- private final Resource listBaseRelation;
- public Layer0 L0;
- public Resource result;
-
- PossibleOwnerList(ReadGraph graph, Resource listBaseRelation) {
- this.graph = graph;
- this.listBaseRelation = listBaseRelation;
- this.L0 = Layer0.getInstance(graph);
- }
-
- @Override
- public Boolean apply(Resource t) throws DatabaseException {
- Set types = graph.getTypes(t);
- if (types.contains(L0.OrderedSet) && types.contains(listBaseRelation)) {
- if (result != null) {
- result = null;
- return false;
- }
- result = t;
- }
- return true;
- }
- }
-
- /**
- * Retrieves a possible single owner list the specified list element
- *
- * @param g
- * @param el
- * a possible element of a list of the specified type
- * @param listBaseRelation
- * a base relation of the list to look for
- * @return null
if there is zero or more than one owner lists
- * with specified base relation
- */
- public static Resource getPossibleOwnerList(ReadGraph g, Resource el, Resource listBaseRelation) throws DatabaseException {
- PossibleOwnerList proc = new PossibleOwnerList(g, listBaseRelation);
- forSubjects(g, el, proc);
- return proc.result;
- }
-
-}
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * 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.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Set;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.db.AsyncReadGraph;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.WriteOnlyGraph;
+import org.simantics.db.common.request.ReadRequest;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.RuntimeDatabaseException;
+import org.simantics.db.exception.ValidationException;
+import org.simantics.db.function.DbFunction;
+import org.simantics.db.procedure.AsyncMultiProcedure;
+import org.simantics.layer0.Layer0;
+import org.simantics.utils.datastructures.Pair;
+
+public class OrderedSetUtils {
+
+ /**
+ * Returns true, if l contains the element el.
+ */
+ public static boolean contains(ReadGraph g, Resource l, Resource el) throws DatabaseException {
+ return g.hasStatement(el, l) && !l.equals(el);
+ }
+
+ /**
+ * Returns the next element in the ordered set or l,
+ * if el is the last element. Called for el, returns
+ * the first element in the set.
+ */
+ public static Resource next(ReadGraph g, Resource l, Resource el) throws DatabaseException {
+ Collection nexts = g.getObjects(el, l);
+ if(nexts.size() != 1)
+ throw new InvalidOrderedSetException("Invalid list element: " + l + " " + el + " " + nexts.size() + " successors.");
+ for(Resource r : nexts)
+ return r;
+ return null;
+ }
+
+ public static void forNext(AsyncReadGraph g, final Resource l, Resource el, final AsyncMultiProcedure procedure) {
+ g.forEachObject(el, l, new AsyncMultiProcedure() {
+
+ @Override
+ public void exception(AsyncReadGraph graph, Throwable t) {
+ procedure.exception(graph, t);
+ }
+
+ @Override
+ public void finished(AsyncReadGraph graph) {
+ }
+
+ @Override
+ public void execute(AsyncReadGraph graph, Resource nel) {
+ if(!nel.equals(l)) {
+ procedure.execute(graph, nel);
+ forNext(graph, l, nel, procedure);
+ }
+ }
+ });
+// Collection nexts = g.getObjects(el, l);
+// if(nexts.size() != 1)
+// throw new NoSingleResultException("Invalid list element: " + nexts.size() + " successors.");
+// for(Resource r : nexts)
+// return r;
+// return null;
+ }
+
+ /**
+ * Returns the previouse element in the ordered set or l,
+ * if el is the first element. Called for el, returns
+ * the last element in the set.
+ */
+ public static Resource prev(ReadGraph g, Resource l, Resource el) throws DatabaseException {
+ Collection prevs = g.getObjects(el, g.getInverse(l));
+ if(prevs.size() != 1) {
+ throw new InvalidOrderedSetException("Invalid list element, " + prevs.size() + " predecessors.");
+ }
+ for(Resource r : prevs)
+ return r;
+ return null;
+ }
+
+ /**
+ * Adds a given elements el to the list l. Returns
+ * true, if the element was really added.
+ */
+ public static boolean add(WriteGraph g, Resource l, Resource el) throws DatabaseException {
+ if(g.hasStatement(el, l))
+ return false;
+ Resource back = prev(g, l, l);
+ g.denyStatement(back, l, l);
+ g.claim(back, l, el);
+ g.claim(el, l, l);
+ return true;
+ }
+
+ /**
+ * Adds a given elements el to the list l. Returns
+ * true, if the element was really added.
+ */
+ public static boolean addFirst(WriteGraph g, Resource l, Resource el) throws DatabaseException {
+ return addAfter(g, l, l, el);
+ }
+
+ public static boolean addAll(WriteGraph g, Resource l, Iterable els) throws DatabaseException {
+ for(Resource r : els)
+ if(g.hasStatement(r, l))
+ return false;
+ Resource cur = prev(g, l, l);
+ g.denyStatement(cur, l, l);
+ for(Resource r : els) {
+ g.claim(cur, l, r);
+ cur = r;
+ }
+ g.claim(cur, l, l);
+ return true;
+ }
+
+ public static boolean addAllNew(WriteGraph g, Resource l, Iterable els) throws DatabaseException {
+ Resource cur = prev(g, l, l);
+ Resource inv = g.getInverse(l);
+ g.deny(cur, l, inv, l);
+ for(Resource r : els) {
+ g.claim(cur, l, inv, r);
+ cur = r;
+ }
+ g.claim(cur, l, inv, l);
+ return true;
+ }
+
+ public static boolean addAfter(WriteGraph g, Resource l, Resource pos, Resource el) throws DatabaseException {
+ if(g.hasStatement(el, l))
+ return false;
+ Resource next = next(g, l, pos);
+ g.denyStatement(pos, l, next);
+ g.claim(pos, l, el);
+ g.claim(el, l, next);
+ return true;
+ }
+
+ public static boolean addBefore(WriteGraph g, Resource l, Resource pos, Resource el) throws DatabaseException {
+ if(g.hasStatement(el, l))
+ return false;
+ Resource prev = prev(g, l, pos);
+ g.denyStatement(prev, l, pos);
+ g.claim(prev, l, el);
+ g.claim(el, l, pos);
+ return true;
+ }
+
+ /**
+ * Removes a given elements el from the list l. Returns
+ * true, if the element was really removed.
+ */
+ public static boolean remove(WriteGraph g, Resource l, Resource el) throws DatabaseException {
+ Collection nexts = g.getObjects(el, l);
+ if(nexts.size() == 0)
+ return false;
+ if(nexts.size() != 1)
+ throw new InvalidOrderedSetException("Invalid list element.");
+ Collection prevs = g.getObjects(el, g.getInverse(l));
+ if(prevs.size() != 1)
+ throw new InvalidOrderedSetException("Invalid list element.");
+
+ for(Resource p : prevs)
+ for(Resource n : nexts) {
+ g.denyStatement(p, l, el);
+ g.denyStatement(el, l, n);
+ g.claim(p, l, n);
+ return true;
+ }
+ return true;
+ }
+
+ public static List removeList(WriteGraph g, Resource l) throws DatabaseException {
+ List els = toList(g, l);
+ for(Resource el : els)
+ g.deny(el, l);
+ g.deny(l, l);
+ Resource inv = g.getInverse(l);
+ g.deny(l);
+ g.deny(inv);
+ return els;
+ }
+
+ public static void replace(WriteGraph g, Resource l, Resource oldEl, Resource newEl) throws DatabaseException {
+ Collection nexts = g.getObjects(oldEl, l);
+ if(nexts.size() != 1)
+ throw new InvalidOrderedSetException("Invalid list element.");
+ Collection prevs = g.getObjects(oldEl, g.getInverse(l));
+ if(prevs.size() != 1)
+ throw new InvalidOrderedSetException("Invalid list element.");
+
+ for(Resource p : prevs)
+ for(Resource n : nexts) {
+ g.denyStatement(p, l, oldEl);
+ g.denyStatement(oldEl, l, n);
+ g.claim(p, l, newEl);
+ g.claim(newEl, l, n);
+ return;
+ }
+ }
+
+ /**
+ * Converts ordered set into a list.
+ */
+ public static List toList(ReadGraph g, Resource l) throws DatabaseException {
+ ArrayList ret = new ArrayList();
+ Resource cur = l;
+ while(true) {
+ cur = next(g, l, cur);
+ if(cur.equals(l))
+ return ret;
+ ret.add(cur);
+ }
+ }
+
+ /**
+ * Converts ordered set into a list.
+ */
+ public static void forEach(AsyncReadGraph g, final Resource l, final AsyncMultiProcedure procedure) {
+ g.asyncRequest(new ReadRequest() {
+
+ @Override
+ public void run(ReadGraph graph) throws DatabaseException {
+ for(Resource r : toList(graph, l))
+ procedure.execute(graph, r);
+ }
+
+ });
+ }
+
+ /**
+ * Creates an empty ordered set.
+ */
+ public static Resource create(WriteOnlyGraph g, Resource type) throws DatabaseException {
+ Layer0 l0 = g.getService(Layer0.class);
+ Resource l = g.newResource();
+ g.claim(l, l0.InstanceOf, null, type);
+ g.claim(l, l0.SubrelationOf, null, l0.HasNext);
+ Resource invL = g.newResource();
+ g.claim(invL, l0.SubrelationOf, null, l0.HasPrevious);
+ g.claim(l, l0.InverseOf, l0.InverseOf, invL);
+ g.claim(l, l, invL, l);
+ return l;
+ }
+
+ /**
+ * Creates an ordered set containing the given elements.
+ * It is assumed that the elements do not contain duplicates.
+ */
+ @Deprecated
+ public static Resource create(WriteOnlyGraph g, Resource type, Iterable c) throws DatabaseException {
+ Layer0 l0 = g.getService(Layer0.class);
+ Resource l = g.newResource();
+ g.claim(l, l0.InstanceOf, null, type);
+ g.claim(l, l0.SubrelationOf, null, l0.HasNext);
+ Resource invL = g.newResource();
+ g.claim(invL, l0.SubrelationOf, null, l0.HasPrevious);
+ g.claim(l, l0.InverseOf, l0.InverseOf, invL);
+ Resource cur = l;
+ for(Resource r : c) {
+ g.claim(cur, l, invL, r);
+ cur = r;
+ }
+ g.claim(cur, l, invL, l);
+ return l;
+ }
+
+ public static Resource create(WriteOnlyGraph g, Resource type, String name, Iterable c) throws DatabaseException {
+ return createExisting(g, g.newResource(), type, name, c);
+ }
+
+ public static Resource createExisting(WriteOnlyGraph g, Resource l, Resource type, String name, Iterable c) throws DatabaseException {
+ Layer0 l0 = g.getService(Layer0.class);
+ g.claim(l, l0.InstanceOf, null, type);
+ g.claim(l, l0.SubrelationOf, null, l0.HasNext);
+ g.addLiteral(l, l0.HasName, l0.NameOf, l0.String, name, Bindings.STRING);
+ Resource invL = g.newResource();
+ g.claim(invL, l0.SubrelationOf, null, l0.HasPrevious);
+ g.addLiteral(invL, l0.HasName, l0.NameOf, l0.String, "Inverse", Bindings.STRING);
+ g.claim(l, l0.InverseOf, l0.InverseOf, invL);
+ g.claim(l, l0.ConsistsOf, l0.PartOf, invL);
+ Resource cur = l;
+ for(Resource r : c) {
+ g.claim(cur, l, invL, r);
+ cur = r;
+ }
+ g.claim(cur, l, invL, l);
+ return l;
+ }
+
+ public static Resource create(WriteOnlyGraph g, Resource type, Resource ... c) throws DatabaseException {
+ Layer0 l0 = g.getService(Layer0.class);
+ Resource l = g.newResource();
+ g.claim(l, l0.InstanceOf, null, type);
+ g.claim(l, l0.SubrelationOf, null, l0.HasNext);
+ Resource invL = g.newResource();
+ g.claim(invL, l0.SubrelationOf, null, l0.HasPrevious);
+ g.claim(l, l0.InverseOf, l0.InverseOf, invL);
+ Resource cur = l;
+ for(Resource r : c) {
+ g.claim(cur, l, invL, r);
+ cur = r;
+ }
+ g.claim(cur, l, invL, l);
+ return l;
+ }
+
+ public static Resource createExisting(WriteGraph g, Resource l, Resource ... c) throws DatabaseException {
+ Layer0 l0 = Layer0.getInstance(g);
+ g.claim(l, l0.SubrelationOf, null, l0.HasNext);
+ Resource invL = g.newResource();
+ g.claim(invL, l0.SubrelationOf, null, l0.HasPrevious);
+ g.claim(l, l0.InverseOf, l0.InverseOf, invL);
+ Resource cur = l;
+ for(Resource r : c) {
+ g.claim(cur, l, invL, r);
+ cur = r;
+ }
+ g.claim(cur, l, invL, l);
+ return l;
+ }
+
+// public static Resource create(GraphWriter graph, Resource type, Iterable c) throws DatabaseException {
+// ReadGraph g = w.getGraph();
+// Builtins b = g.getBuiltins();
+// Resource l = w.create(type).get();
+// w.let(b.SubrelationOf, b.IsRelatedTo);
+// w.createInverse(l).let(b.SubrelationOf, g.getInverse(b.IsRelatedTo));
+//
+// Resource cur = l;
+// for(Resource r : c) {
+// w.stat(cur, l, r);
+// cur = r;
+// }
+// w.stat(cur, l, l);
+// return l;
+// }
+
+ public static class OrderedSetIterator implements ListIterator {
+
+ ReadGraph g;
+ Resource l;
+ Resource prev;
+ Resource next;
+ int index;
+ boolean direction;
+
+ WriteGraph getWriteGraph() {
+ if (!(g instanceof WriteGraph))
+ throw new UnsupportedOperationException("");
+ return (WriteGraph) g;
+ }
+
+ public OrderedSetIterator(ReadGraph g, Resource l) throws DatabaseException {
+ this.g = g;
+ this.l = l;
+ this.prev = l;
+ this.next = OrderedSetUtils.next(g, l, l);
+ this.index = 0;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return !next.equals(l);
+ }
+
+ @Override
+ public Resource next() {
+ prev = next;
+ try {
+ next = OrderedSetUtils.next(g, l, next);
+ } catch (DatabaseException e) {
+ throw new RuntimeDatabaseException(e);
+ }
+ ++index;
+ direction = true;
+ return prev;
+ }
+
+ @Override
+ public void remove() {
+ try {
+ WriteGraph wg = getWriteGraph();
+ if(direction) {
+ OrderedSetUtils.remove(wg, l, prev);
+ prev = OrderedSetUtils.prev(wg, l, next);
+ }
+ else {
+ OrderedSetUtils.remove(wg, l, next);
+ next = OrderedSetUtils.next(wg, l, prev);
+ }
+ } catch (DatabaseException e) {
+ throw new RuntimeDatabaseException(e);
+ }
+ }
+
+ @Override
+ public void add(Resource e) {
+ try {
+ WriteGraph wg = getWriteGraph();
+ wg.denyStatement(prev, l, next);
+ wg.claim(prev, l, e);
+ wg.claim(e, l, next);
+ prev = e;
+ } catch (DatabaseException ex) {
+ throw new RuntimeDatabaseException(ex);
+ }
+ }
+
+ @Override
+ public boolean hasPrevious() {
+ return !prev.equals(l);
+ }
+
+ @Override
+ public int nextIndex() {
+ return index;
+ }
+
+ @Override
+ public Resource previous() {
+ try {
+ next = prev;
+ prev = OrderedSetUtils.prev(g, l, prev);
+ --index;
+ direction = false;
+ return next;
+ } catch (DatabaseException ex) {
+ throw new RuntimeDatabaseException(ex);
+ }
+ }
+
+ @Override
+ public int previousIndex() {
+ return index-1;
+ }
+
+ @Override
+ public void set(Resource e) {
+ try {
+ WriteGraph wg = getWriteGraph();
+ if(direction) {
+ OrderedSetUtils.replace(wg, l, prev, e);
+ prev = e;
+ }
+ else {
+ OrderedSetUtils.replace(wg, l, next, e);
+ next = e;
+ }
+ } catch (DatabaseException ex) {
+ throw new RuntimeDatabaseException(ex);
+ }
+ }
+
+ }
+
+ public static ListIterator iterator(ReadGraph g, Resource l) throws DatabaseException {
+ return new OrderedSetIterator(g, l);
+ }
+
+ public static boolean set(WriteGraph g, Resource l, Iterable els) throws DatabaseException {
+
+ // Compute delta
+ Set> removed = new HashSet>();
+ Collection> added = new ArrayList>();
+ Resource cur = l;
+ do {
+ Resource temp = next(g, l, cur);
+ removed.add(new Pair(cur, temp));
+ cur = temp;
+ } while(!cur.equals(l));
+
+ cur = l;
+ for(Resource temp : els) {
+ Pair pair = new Pair(cur, temp);
+ if(!removed.remove(pair))
+ added.add(pair);
+ cur = temp;
+ }
+
+ {
+ Pair pair = new Pair(cur, l);
+ if(!removed.remove(pair))
+ added.add(pair);
+ }
+
+ // Apply
+ if(added.isEmpty() && removed.isEmpty())
+ return false;
+ for(Pair pair : removed)
+ g.denyStatement(pair.first, l, pair.second);
+ for(Pair pair : added)
+ g.claim(pair.first, l, pair.second);
+ return true;
+ }
+
+ /**
+ * Retrieves the owner list the specified list element
+ *
+ * @param g
+ * @param el a possible element of a list of the specified type
+ * @param listBaseRelation a base relation of the list to look for
+ * @return
+ */
+ public static Resource getSingleOwnerList(ReadGraph g, Resource el, Resource listBaseRelation) throws DatabaseException {
+ Collection result = getOwnerLists(g, el, listBaseRelation);
+ if (result.size() != 1)
+ throw new ValidationException(NameUtils.getSafeName(g, el) + " is part of " + result.size() + " lists of base type " + NameUtils.getSafeName(g, listBaseRelation) + ", expected only one list.");
+ return result.iterator().next();
+ }
+
+ public static Resource getSingleOwnerList(ReadGraph g, Resource el) throws DatabaseException {
+ Layer0 l0 = Layer0.getInstance(g);
+ Collection result = getOwnerLists(g, el, l0.OrderedSet);
+ if (result.size() != 1)
+ throw new ValidationException(NameUtils.getSafeName(g, el) + " is part of " + result.size() + " lists of base type L0.OrderedSet, expected only one list.");
+ return result.iterator().next();
+ }
+
+ public static Collection getSubjects(ReadGraph g, Resource object) throws DatabaseException {
+ Collection result = new ArrayList(1);
+ Layer0 l0 = Layer0.getInstance(g);
+ for(Resource pred : g.getPredicates(object)) {
+ if(g.isInstanceOf(pred, l0.OrderedSet) && !pred.equals(object))
+ result.add(pred);
+ }
+ return result;
+ }
+
+ private static void forSubjects(ReadGraph g, Resource object, DbFunction consumer) throws DatabaseException {
+ for (Resource pred : g.getPredicates(object)) {
+ if (!pred.equals(object))
+ if (!consumer.apply(pred))
+ break;
+ }
+ }
+
+ /**
+ * Retrieves the owner list the specified list element
+ *
+ * @param g
+ * @param el a possible element of a list of the specified type
+ * @param listBaseRelation a base relation of the list to look for
+ * @return
+ */
+ public static Collection getOwnerLists(ReadGraph g, Resource el, Resource listBaseRelation) throws DatabaseException {
+ Collection result = null;
+ Collection rs = getSubjects(g, el);
+ for (Resource r : rs) {
+ if (g.isInstanceOf(r, listBaseRelation)) {
+ if (result == null)
+ result = new ArrayList(2);
+ result.add(r);
+ }
+ }
+ if (result == null)
+ result = Collections.emptyList();
+ return result;
+ }
+
+ private static class PossibleOwnerList implements DbFunction {
+ private ReadGraph graph;
+ private final Resource listBaseRelation;
+ public Layer0 L0;
+ public Resource result;
+
+ PossibleOwnerList(ReadGraph graph, Resource listBaseRelation) {
+ this.graph = graph;
+ this.listBaseRelation = listBaseRelation;
+ this.L0 = Layer0.getInstance(graph);
+ }
+
+ @Override
+ public Boolean apply(Resource t) throws DatabaseException {
+ Set types = graph.getTypes(t);
+ if (types.contains(L0.OrderedSet) && types.contains(listBaseRelation)) {
+ if (result != null) {
+ result = null;
+ return false;
+ }
+ result = t;
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Retrieves a possible single owner list the specified list element
+ *
+ * @param g
+ * @param el
+ * a possible element of a list of the specified type
+ * @param listBaseRelation
+ * a base relation of the list to look for
+ * @return null
if there is zero or more than one owner lists
+ * with specified base relation
+ */
+ public static Resource getPossibleOwnerList(ReadGraph g, Resource el, Resource listBaseRelation) throws DatabaseException {
+ PossibleOwnerList proc = new PossibleOwnerList(g, listBaseRelation);
+ forSubjects(g, el, proc);
+ return proc.result;
+ }
+
+}