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