--- /dev/null
+package org.simantics.db.common.utils;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.Set;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.WriteOnlyGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+\r
+public class ListUtils {\r
+\r
+ /**\r
+ * Inserts {@code elements} between list nodes \r
+ * {@code before} and {@code after}.\r
+ */\r
+ private static void insertBetween(\r
+ WriteGraph g, Layer0 L0, Resource list,\r
+ Resource before, Resource after, \r
+ Iterable<Resource> elements) throws DatabaseException {\r
+ for(Resource item : elements) {\r
+ Resource cur = g.newResource();\r
+ g.claim(cur, L0.InstanceOf, null, L0.List_Entry);\r
+ g.claim(cur, L0.IsOwnedBy, L0.IsComposedOf, list);\r
+ g.claim(before, L0.List_Next, L0.List_Previous, cur);\r
+ g.claim(cur, L0.List_Element, item);\r
+ before = cur;\r
+ } \r
+ g.claim(before, L0.List_Next, L0.List_Previous, after);\r
+ }\r
+\r
+ private static void insertBetween(\r
+ WriteGraph g, Layer0 L0, Resource list, \r
+ Resource before, Resource after, \r
+ Resource[] elements) throws DatabaseException {\r
+ for(Resource item : elements) {\r
+ Resource cur = g.newResource();\r
+ g.claim(cur, L0.InstanceOf, null, L0.List_Entry);\r
+ g.claim(cur, L0.IsOwnedBy, L0.IsComposedOf, list);\r
+ g.claim(before, L0.List_Next, L0.List_Previous, cur);\r
+ g.claim(cur, L0.List_Element, item);\r
+ before = cur;\r
+ } \r
+ g.claim(before, L0.List_Next, L0.List_Previous, after);\r
+ }\r
+ \r
+ /**\r
+ * Creates a list containing the givens {@code elements}.\r
+ */\r
+ public static Resource create(WriteGraph g, Iterable<Resource> elements) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ \r
+ Resource list = g.newResource();\r
+ g.claim(list, L0.InstanceOf, L0.List);\r
+ \r
+ insertBetween(g, L0, list, list, list, elements);\r
+ return list;\r
+ }\r
+\r
+ /**\r
+ * Creates a list containing the givens {@code elements}.\r
+ */\r
+ public static Resource create(WriteGraph g, Resource type, Iterable<Resource> elements) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ \r
+ Resource list = g.newResource();\r
+ g.claim(list, L0.InstanceOf, null, type);\r
+ \r
+ insertBetween(g, L0, list, list, list, elements);\r
+ return list;\r
+ }\r
+\r
+ public static Resource create(WriteGraph g, Resource type, Resource ... elements) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ \r
+ Resource list = g.newResource();\r
+ g.claim(list, L0.InstanceOf, null, type);\r
+ \r
+ insertBetween(g, L0, list, list, list, elements);\r
+ return list;\r
+ }\r
+ \r
+ /**\r
+ * Inserts given {@code elements} into the front of the list.\r
+ */\r
+ public static void insertFront(WriteGraph g, Resource list, Iterable<Resource> elements) throws DatabaseException {\r
+ if (!elements.iterator().hasNext())\r
+ return;\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ \r
+ Resource first = g.getSingleObject(list, L0.List_Next); \r
+ g.deny(list, L0.List_Next, L0.List_Previous, first); \r
+ insertBetween(g, L0, list, list, first, elements);\r
+ }\r
+ \r
+ public static void createExisting(WriteOnlyGraph g, Resource list, Iterable<Resource> elements) throws DatabaseException {\r
+ \r
+ Layer0 L0 = g.getService(Layer0.class);\r
+ Resource before = list;\r
+ for(Resource item : elements) {\r
+ Resource cur = g.newResource();\r
+ g.claim(cur, L0.InstanceOf, null, L0.List_Entry);\r
+ g.claim(cur, L0.IsOwnedBy, L0.IsComposedOf, list);\r
+ g.claim(before, L0.List_Next, L0.List_Previous, cur);\r
+ g.claim(cur, L0.List_Element, null, item);\r
+ before = cur;\r
+ } \r
+ g.claim(before, L0.List_Next, L0.List_Previous, list);\r
+ \r
+ }\r
+ \r
+ /**\r
+ * Inserts given {@code elements} into the back of the list.\r
+ */\r
+ public static void insertBack(WriteGraph g, Resource list, Iterable<Resource> elements) throws DatabaseException {\r
+ if (!elements.iterator().hasNext())\r
+ return;\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ \r
+ Resource last = g.getSingleObject(list, L0.List_Previous); \r
+ g.deny(last, L0.List_Next, L0.List_Previous, list); \r
+ insertBetween(g, L0, list, last, list, elements);\r
+ }\r
+ \r
+ /**\r
+ * Replaces a given element in the a given list\r
+ * @param g WriteGraph\r
+ * @param list List resource\r
+ * @param element Element to be replaced\r
+ * @param replacement Resource that replaces element\r
+ * @return true if successful replacement, false otherwise\r
+ * @throws DatabaseException\r
+ */\r
+ public static boolean replace(WriteGraph g, Resource list, Resource element, Resource replacement) throws DatabaseException {\r
+ if(list == null || element == null || replacement == null)\r
+ return false;\r
+ \r
+ Layer0 L0 = Layer0.getInstance(g);\r
+\r
+ Resource node = getNode(g, list, element);\r
+ if(node != null) {\r
+ g.deny(node, L0.List_Element);\r
+ g.claim(node, L0.List_Element, replacement);\r
+ return true;\r
+ } else {\r
+ return false;\r
+ }\r
+ }\r
+ \r
+ private static void toList(ReadGraph g, List<Resource> result, Resource list) throws DatabaseException {\r
+ \r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ \r
+ Resource cur = g.getSingleObject(list, L0.List_Next);\r
+ while(!cur.equals(list)) {\r
+ Resource el = g.getPossibleObject(cur, L0.List_Element);\r
+ if(el != null)\r
+ result.add(el);\r
+ cur = g.getSingleObject(cur, L0.List_Next);\r
+ }\r
+ \r
+ }\r
+ \r
+ /**\r
+ * Converts a list in the graph to a Java List.\r
+ */\r
+ public static List<Resource> toList(ReadGraph g, Resource list) throws DatabaseException {\r
+ ArrayList<Resource> result = new ArrayList<Resource>();\r
+ toList(g, result, list);\r
+ return result;\r
+ }\r
+\r
+ public static List<Resource> toPossibleList(ReadGraph g, Resource list) throws DatabaseException {\r
+ try {\r
+ return toList(g, list);\r
+ } catch (DatabaseException e) {\r
+ return null;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Removes an element from a list. Returns true if actually removed something.\r
+ */\r
+ public static boolean removeElement(WriteGraph g, Resource list, Resource element) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ Resource prev = list;\r
+ Resource cur = g.getSingleObject(list, L0.List_Next);\r
+ while(!cur.equals(list)) {\r
+ Resource el = g.getPossibleObject(cur, L0.List_Element);\r
+ Resource next = g.getSingleObject(cur, L0.List_Next);\r
+ if(element.equals(el)) { \r
+ g.deny(cur);\r
+ g.claim(prev, L0.List_Next, next);\r
+ return true;\r
+ }\r
+ prev = cur;\r
+ cur = next;\r
+ }\r
+ return false;\r
+ }\r
+ \r
+ /**\r
+ * Removes an elements from a list. Returns true if actually removed something.\r
+ */\r
+ public static boolean removeElements(WriteGraph g, Resource list, Set<Resource> elements) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ Resource prev = list;\r
+ Resource cur = g.getSingleObject(list, L0.List_Next);\r
+ boolean removed = false;\r
+ while(!cur.equals(list)) {\r
+ Resource el = g.getPossibleObject(cur, L0.List_Element);\r
+ Resource next = g.getSingleObject(cur, L0.List_Next);\r
+ if(elements.contains(el)) { \r
+ g.deny(cur);\r
+ g.claim(prev, L0.List_Next, next);\r
+ removed = true;\r
+ }\r
+ else\r
+ prev = cur;\r
+ cur = next;\r
+ }\r
+ return removed;\r
+ }\r
+ \r
+ private static void getListNodes(ReadGraph g, List<Resource> result, Resource list) throws DatabaseException {\r
+ \r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ \r
+ Resource cur = g.getSingleObject(list, L0.List_Next);\r
+ while(!cur.equals(list)) {\r
+ result.add(cur);\r
+ cur = g.getSingleObject(cur, L0.List_Next);\r
+ }\r
+ \r
+ }\r
+ \r
+ public static List<Resource> getListNodes(ReadGraph g, Resource list) throws DatabaseException {\r
+ ArrayList<Resource> result = new ArrayList<Resource>();\r
+ getListNodes(g, result, list);\r
+ return result;\r
+ }\r
+ \r
+ public static Resource getNode(ReadGraph g, Resource list, Resource element) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ \r
+ Resource cur = g.getSingleObject(list, L0.List_Next);\r
+ while(!cur.equals(list)) {\r
+ Resource el = g.getPossibleObject(cur, L0.List_Element);\r
+ if(element.equals(el))\r
+ return cur;\r
+ cur = g.getSingleObject(cur, L0.List_Next);\r
+ }\r
+ return null;\r
+ } \r
+ \r
+ public static boolean swapWithPrevious(WriteGraph g, Resource list, Resource element) throws DatabaseException {\r
+ Resource node = getNode(g, list, element);\r
+ if(node == null)\r
+ return false;\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ Resource prev = g.getSingleObject(node, L0.List_Previous);\r
+ if(list.equals(prev))\r
+ return false;\r
+ swap(g, node, prev);\r
+ return true;\r
+ }\r
+ \r
+ public static boolean swapWithNext(WriteGraph g, Resource list, Resource element) throws DatabaseException {\r
+ Resource node = getNode(g, list, element);\r
+ if(node == null)\r
+ return false;\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ Resource next = g.getSingleObject(node, L0.List_Next);\r
+ if(list.equals(next))\r
+ return false;\r
+ swap(g, node, next);\r
+ return true;\r
+ }\r
+\r
+ private static void swap(WriteGraph g, Resource a, Resource b) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ Resource ea = g.getPossibleObject(a, L0.List_Element);\r
+ Resource eb = g.getPossibleObject(b, L0.List_Element);\r
+ \r
+ g.deny(a, L0.List_Element);\r
+ g.deny(b, L0.List_Element);\r
+ \r
+ if(eb != null)\r
+ g.claim(a, L0.List_Element, eb);\r
+ if(ea != null)\r
+ g.claim(b, L0.List_Element, ea);\r
+ }\r
+\r
+ \r
+}\r