1 package org.simantics.db.common.utils;
3 import java.util.AbstractSequentialList;
4 import java.util.ListIterator;
5 import java.util.NoSuchElementException;
7 import org.simantics.db.ReadGraph;
8 import org.simantics.db.Resource;
9 import org.simantics.db.WriteGraph;
10 import org.simantics.db.exception.DatabaseException;
11 import org.simantics.layer0.Layer0;
12 import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory;
16 * Java List interface to linked lists in Simantics DB.
18 public class GraphList extends AbstractSequentialList<Resource> {
20 private final static Logger LOGGER = LoggerFactory.getLogger(GraphList.class);
22 private final ReadGraph graph;
23 private final Layer0 L0;
24 private final Resource root;
25 private final Resource elementRelation;
27 public GraphList(ReadGraph graph, Resource root, Resource elementRelation) {
29 this.L0 = Layer0.getInstance(graph);
31 this.elementRelation = elementRelation;
34 public GraphList(ReadGraph graph, Resource root) throws DatabaseException {
36 this.L0 = Layer0.getInstance(graph);
38 this.elementRelation = graph.getSingleObject(root, L0.List_ElementPredicate);
41 class GraphListIterator implements ListIterator<Resource> {
42 private Resource prev;
43 private Resource next;
47 public GraphListIterator(Resource prev, Resource next, int id) {
48 LOGGER.info("GraphListIterator root="+root+" prev=" + prev + " next=" + next);
56 public boolean hasNext() {
57 LOGGER.info("hasNext root="+root+" prev=" + prev + " next=" + next);
62 LOGGER.info("goNext prev=" + prev + " next=" + next);
65 throw new NoSuchElementException();
68 next = browseNext(next);
71 LOGGER.info(" prev=" + prev + " next=" + next);
77 throw new NoSuchElementException();
80 prev = browsePrev(prev);
86 public Resource next() {
88 return browseElement(prev);
92 public boolean hasPrevious() {
97 public Resource previous() {
99 return browseElement(next);
103 public int nextIndex() {
108 public int previousIndex() {
113 public void remove() {
117 prev = browsePrev(prev);
119 else if(lastOp == -1) {
121 next = browseNext(next);
124 throw new UnsupportedOperationException("Cannot remove element, when no previous next/prev call.");
125 doRemove(prev, target, next);
130 public void set(Resource e) {
134 else if(lastOp == -1)
137 throw new UnsupportedOperationException("Cannot remove element, when no previous next/prev call.");
142 public void add(Resource e) {
143 addBetween(prev, next, e);
149 public ListIterator<Resource> listIterator(int index) {
150 GraphListIterator it = new GraphListIterator(root, browseNext(root), 0);
158 private Resource browseNext(Resource cur) {
160 return graph.getSingleObject(cur, L0.List_Next);
161 } catch(DatabaseException e) {
162 throw new RuntimeException(e);
166 private Resource browsePrev(Resource cur) {
168 return graph.getSingleObject(cur, L0.List_Previous);
169 } catch(DatabaseException e) {
170 throw new RuntimeException(e);
174 private Resource browseElement(Resource cur) {
176 LOGGER.info("browseElement " + cur);
177 return graph.getSingleObject(cur, elementRelation);
178 } catch(DatabaseException e) {
179 throw new RuntimeException(e);
183 private void addBetween(Resource prev, Resource next, Resource element) {
186 graph = (WriteGraph)this.graph;
187 } catch(ClassCastException e) {
188 throw new UnsupportedOperationException("Cannot add element in read transaction.");
191 graph.deny(prev, L0.List_Next, L0.List_Previous, next);
193 Resource newEntry = graph.newResource();
194 graph.claim(newEntry, L0.InstanceOf, L0.List_Entry);
195 graph.claim(newEntry, elementRelation, element);
196 graph.claim(newEntry, L0.IsOwnedBy, L0.IsComposedOf, root);
197 graph.claim(prev, L0.List_Next, L0.List_Previous, newEntry);
198 graph.claim(newEntry, L0.List_Next, L0.List_Previous, next);
199 } catch(DatabaseException e) {
200 throw new RuntimeException(e);
204 private void doSet(Resource target, Resource resource) {
207 graph = (WriteGraph)this.graph;
208 } catch(ClassCastException e) {
209 throw new UnsupportedOperationException("Cannot set element in read transaction.");
212 graph.deny(target, elementRelation);
213 graph.claim(target, elementRelation, resource);
214 } catch(DatabaseException e) {
215 throw new RuntimeException(e);
219 private void doRemove(Resource prev, Resource target, Resource next) {
222 graph = (WriteGraph)this.graph;
223 } catch(ClassCastException e) {
224 throw new UnsupportedOperationException("Cannot remove element in read transaction.");
228 graph.claim(prev, L0.List_Next, L0.List_Previous, next);
229 } catch(DatabaseException e) {
230 throw new RuntimeException(e);
237 for(Resource cur=browseNext(root);cur!=root;cur=browseNext(cur))
243 public boolean isEmpty() {
245 return graph.hasStatement(root, L0.List_Next, root);
246 } catch (DatabaseException e) {
247 throw new RuntimeException(e);