]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.common/src/org/simantics/db/common/utils/ListUtils.java
ListUtils.create(g,elements) creates a list without element inverses
[simantics/platform.git] / bundles / org.simantics.db.common / src / org / simantics / db / common / utils / ListUtils.java
1 package org.simantics.db.common.utils;
2
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.List;
6 import java.util.Set;
7
8 import org.simantics.db.ReadGraph;
9 import org.simantics.db.Resource;
10 import org.simantics.db.WriteGraph;
11 import org.simantics.db.WriteOnlyGraph;
12 import org.simantics.db.exception.DatabaseException;
13 import org.simantics.layer0.Layer0;
14
15 public class ListUtils {
16
17     /**
18      * Inserts {@code elements} between list nodes 
19      * {@code before} and {@code after}.
20      */
21     private static void insertBetween(
22             WriteGraph g, Layer0 L0, Resource list,
23             Resource before, Resource after, 
24             Iterable<Resource> elements) throws DatabaseException {
25         Resource elementPredicate = getElementPredicate(g, list);
26         for(Resource item : elements) {
27             Resource cur = g.newResource();
28             g.claim(cur, L0.InstanceOf, null, L0.List_Entry);
29             g.claim(cur, L0.IsOwnedBy, L0.IsComposedOf, list);
30             g.claim(before, L0.List_Next, L0.List_Previous, cur);
31             g.claim(cur, elementPredicate, item);
32             before = cur;
33         }  
34         g.claim(before, L0.List_Next, L0.List_Previous, after);
35     }
36
37     private static void insertBetween(
38             WriteGraph g, Layer0 L0, Resource list, 
39             Resource before, Resource after, 
40             Resource[] elements) throws DatabaseException {
41         Resource elementPredicate = getElementPredicate(g, list);
42         for(Resource item : elements) {
43             Resource cur = g.newResource();
44             g.claim(cur, L0.InstanceOf, null, L0.List_Entry);
45             g.claim(cur, L0.IsOwnedBy, L0.IsComposedOf, list);
46             g.claim(before, L0.List_Next, L0.List_Previous, cur);
47             g.claim(cur, elementPredicate, item);
48             before = cur;
49         }  
50         g.claim(before, L0.List_Next, L0.List_Previous, after);
51     }
52     
53     /**
54      * Creates a list containing the given {@code elements}.
55      */
56     public static Resource create(WriteGraph g, Iterable<Resource> elements) throws DatabaseException {
57         Layer0 L0 = Layer0.getInstance(g);
58         return ListUtils.create(g,L0.List, L0.List_Element, null, elements);
59     }
60     
61     public static Resource createWithInverses(WriteGraph g, Iterable<Resource> elements) throws DatabaseException {
62         Layer0 L0 = Layer0.getInstance(g);
63         return ListUtils.create(g,L0.ListWithInverses, L0.List_ElementWithInverse, L0.List_ElementWithInverse_Inverse, elements);
64     }
65     
66     /**
67      * Creates a list of the given list type containing the given {@code elements}.
68      */
69     public static Resource create(WriteGraph g, Resource type, Iterable<Resource> elements) throws DatabaseException {
70         Layer0 L0 = Layer0.getInstance(g);
71         
72         Resource list = g.newResource();
73         g.claim(list, L0.InstanceOf, null, type);
74         
75         insertBetween(g, L0, list, list, list, elements);
76         return list;
77     }
78
79     public static Resource create(WriteGraph g, Resource type, Resource ... elements) throws DatabaseException {
80         Layer0 L0 = Layer0.getInstance(g);
81         
82         Resource list = g.newResource();
83         g.claim(list, L0.InstanceOf, null, type);
84         
85         insertBetween(g, L0, list, list, list, elements);
86         return list;
87     }
88
89     public static Resource create(WriteOnlyGraph g, Resource type, Resource elementPredicate, Resource elementPredicateInverse, Iterable<Resource> elements) throws DatabaseException {
90         Layer0 L0 = g.getService(Layer0.class);
91         Resource list = g.newResource();
92         g.claim(list, L0.InstanceOf, null, type);
93         if (!elementPredicate.equals(L0.List_Element))
94                 g.claim(list, L0.List_ElementPredicate, L0.List_ElementPredicate_Inverse, elementPredicate);
95         createExisting(g, list, elementPredicate, elementPredicateInverse, elements);
96         return list;
97     }
98
99     public static Resource create(WriteOnlyGraph g, Resource type, Resource elementPredicate, Resource elementPredicateInverse, Resource... elements) throws DatabaseException {
100         return create(g, type, elementPredicate, elementPredicateInverse, Arrays.asList(elements));
101     }
102
103     /**
104      * Inserts given {@code elements} into the front of the list.
105      */
106     public static void insertFront(WriteGraph g, Resource list, Iterable<Resource> elements) throws DatabaseException {
107         if (!elements.iterator().hasNext())
108             return;
109         Layer0 L0 = Layer0.getInstance(g);
110
111         Resource first = g.getSingleObject(list, L0.List_Next);
112         g.deny(list, L0.List_Next, L0.List_Previous, first);
113         insertBetween(g, L0, list, list, first, elements);
114     }
115
116     public static void createExisting(WriteOnlyGraph g, Resource list, Iterable<Resource> elements) throws DatabaseException {
117         createExisting(g, list, false, elements);
118     }
119
120     public static void createExisting(WriteOnlyGraph g, Resource list, boolean withInverses, Iterable<Resource> elements) throws DatabaseException {
121         Layer0 L0 = g.getService(Layer0.class);
122         Resource elementPredicate = withInverses ? L0.List_ElementWithInverse : L0.List_Element;
123         Resource elementPredicateInverse = withInverses ? L0.List_ElementWithInverse_Inverse : null;
124         createExisting(g, list, elementPredicate, elementPredicateInverse, elements);
125     }
126
127     public static void createExisting(WriteOnlyGraph g, Resource list, Resource elementPredicate, Resource elementPredicateInverse, Iterable<Resource> elements) throws DatabaseException {
128         Layer0 L0 = g.getService(Layer0.class);
129         Resource before = list;
130         for(Resource item : elements) {
131             Resource cur = g.newResource();
132             g.claim(cur, L0.InstanceOf, null, L0.List_Entry);
133             g.claim(cur, L0.IsOwnedBy, L0.IsComposedOf, list);
134             g.claim(before, L0.List_Next, L0.List_Previous, cur);
135             g.claim(cur, elementPredicate, elementPredicateInverse, item);
136             before = cur;
137         }  
138         g.claim(before, L0.List_Next, L0.List_Previous, list);
139     }
140
141     public static void createExisting(WriteOnlyGraph g, Resource list, Resource elementPredicate, Resource elementPredicateInverse, Resource... elements) throws DatabaseException {
142         createExisting(g, list, elementPredicate, elementPredicateInverse, Arrays.asList(elements));
143     }
144
145     /**
146      * Inserts given {@code elements} into the back of the list.
147      */
148     public static void insertBack(WriteGraph g, Resource list, Iterable<Resource> elements) throws DatabaseException {
149         if (!elements.iterator().hasNext())
150             return;
151         Layer0 L0 = Layer0.getInstance(g);
152         
153         Resource last = g.getSingleObject(list, L0.List_Previous);        
154         g.deny(last, L0.List_Next, L0.List_Previous, list);        
155         insertBetween(g, L0, list, last, list, elements);
156     }
157     
158     /**
159      * Replaces a given element in the a given list
160      * @param g WriteGraph
161      * @param list List resource
162      * @param element Element to be replaced
163      * @param replacement Resource that replaces element
164      * @return true if successful replacement, false otherwise
165      * @throws DatabaseException
166      */
167     public static boolean replace(WriteGraph g, Resource list, Resource element, Resource replacement) throws DatabaseException {
168         if(list == null || element == null || replacement == null)
169             return false;
170         
171         Layer0 L0 = Layer0.getInstance(g);
172
173         Resource node = getNode(g, list, element);
174         if(node != null) {
175             Resource elementPredicate = getElementPredicate(g, list);
176             g.deny(node, L0.List_Element);
177             g.claim(node, elementPredicate, replacement);
178             return true;
179         } else {
180             return false;
181         }
182     }
183     
184     private static void toList(ReadGraph g, List<Resource> result, Resource list) throws DatabaseException {
185         
186         Layer0 L0 = Layer0.getInstance(g);
187         
188         Resource cur = g.getSingleObject(list, L0.List_Next);
189         while(!cur.equals(list)) {
190             Resource el = g.getPossibleObject(cur, L0.List_Element);
191             if(el != null)
192                 result.add(el);
193             cur = g.getSingleObject(cur, L0.List_Next);
194         }
195         
196     }
197     
198     /**
199      * Converts a list in the graph to a Java List.
200      */
201     public static List<Resource> toList(ReadGraph g, Resource list) throws DatabaseException {
202         ArrayList<Resource> result = new ArrayList<Resource>();
203         toList(g, result, list);
204         return result;
205     }
206
207     public static List<Resource> toPossibleList(ReadGraph g, Resource list) throws DatabaseException {
208         try {
209                 return toList(g, list);
210         } catch (DatabaseException e) {
211                 return null;
212         }
213     }
214
215     /**
216      * Removes an element from a list. Returns true if actually removed something.
217      */
218     public static boolean removeElement(WriteGraph g, Resource list, Resource element) throws DatabaseException {
219         Layer0 L0 = Layer0.getInstance(g);
220         Resource prev = list;
221         Resource cur = g.getSingleObject(list, L0.List_Next);
222         while(!cur.equals(list)) {
223             Resource el = g.getPossibleObject(cur, L0.List_Element);
224             Resource next = g.getSingleObject(cur, L0.List_Next);
225             if(element.equals(el)) {
226                 g.deny(cur);
227                 g.claim(prev, L0.List_Next, next);
228                 return true;
229             }
230             prev = cur;
231             cur = next;
232         }
233         return false;
234     }
235     
236     /**
237      * Removes an elements from a list. Returns true if actually removed something.
238      */
239     public static boolean removeElements(WriteGraph g, Resource list, Set<Resource> elements) throws DatabaseException {
240         Layer0 L0 = Layer0.getInstance(g);
241         Resource prev = list;
242         Resource cur = g.getSingleObject(list, L0.List_Next);
243         boolean removed = false;
244         while(!cur.equals(list)) {
245             Resource el = g.getPossibleObject(cur, L0.List_Element);
246             Resource next = g.getSingleObject(cur, L0.List_Next);
247             if(elements.contains(el)) {
248                 g.deny(cur);
249                 g.claim(prev, L0.List_Next, next);
250                 removed = true;
251             }
252             else
253                 prev = cur;
254             cur = next;
255         }
256         return removed;
257     }
258     
259     private static void getListNodes(ReadGraph g, List<Resource> result, Resource list) throws DatabaseException {
260         
261         Layer0 L0 = Layer0.getInstance(g);
262         
263         Resource cur = g.getSingleObject(list, L0.List_Next);
264         while(!cur.equals(list)) {
265             result.add(cur);
266             cur = g.getSingleObject(cur, L0.List_Next);
267         }
268         
269     }
270     
271     public static List<Resource> getListNodes(ReadGraph g, Resource list) throws DatabaseException {
272         ArrayList<Resource> result = new ArrayList<Resource>();
273         getListNodes(g, result, list);
274         return result;
275     }
276     
277     public static Resource getNode(ReadGraph g, Resource list, Resource element) throws DatabaseException {
278         Layer0 L0 = Layer0.getInstance(g);
279         
280         Resource cur = g.getSingleObject(list, L0.List_Next);
281         while(!cur.equals(list)) {
282             Resource el = g.getPossibleObject(cur, L0.List_Element);
283             if(element.equals(el))
284                 return cur;
285             cur = g.getSingleObject(cur, L0.List_Next);
286         }
287         return null;
288     }     
289     
290     public static boolean swapWithPrevious(WriteGraph g, Resource list, Resource element) throws DatabaseException {
291         Resource node = getNode(g, list, element);
292         if(node == null)
293             return false;
294         Layer0 L0 = Layer0.getInstance(g);
295         Resource prev = g.getSingleObject(node, L0.List_Previous);
296         if(list.equals(prev))
297             return false;
298         swap(g, list, node, prev);
299         return true;
300     }
301     
302     public static boolean swapWithNext(WriteGraph g, Resource list, Resource element) throws DatabaseException {
303         Resource node = getNode(g, list, element);
304         if(node == null)
305             return false;
306         Layer0 L0 = Layer0.getInstance(g);
307         Resource next = g.getSingleObject(node, L0.List_Next);
308         if(list.equals(next))
309             return false;
310         swap(g, list, node, next);
311         return true;
312     }
313
314     private static void swap(WriteGraph g, Resource list, Resource a, Resource b) throws DatabaseException {
315         Layer0 L0 = Layer0.getInstance(g);
316         Resource ea = g.getPossibleObject(a, L0.List_Element);
317         Resource eb = g.getPossibleObject(b, L0.List_Element);
318         
319         g.deny(a, L0.List_Element);
320         g.deny(b, L0.List_Element);
321         
322         Resource elementPredicate = getElementPredicate(g, list);
323         
324         if(eb != null)
325             g.claim(a, elementPredicate, eb);
326         if(ea != null)
327             g.claim(b, elementPredicate, ea);
328     }
329
330     public static Resource getElementPredicate(ReadGraph g, Resource list) throws DatabaseException {
331         Layer0 L0 = Layer0.getInstance(g);
332         Resource predicate = g.getPossibleObject(list, L0.List_ElementPredicate);
333         if(predicate != null) return predicate;
334         return g.isInstanceOf(list, L0.ListWithInverses) ?
335                 L0.List_ElementWithInverse : L0.List_Element; 
336     }
337
338     public static Resource getListElementList(ReadGraph g, Resource element) throws DatabaseException {
339         Layer0 L0 = Layer0.getInstance(g);
340         return g.getSingleObject(element, L0.IsOwnedBy);
341     }
342
343 }