1 package fi.vtt.simantics.procore.internal;
3 import java.lang.reflect.Array;
4 import java.util.ArrayList;
5 import java.util.Collection;
6 import java.util.Collections;
7 import java.util.Comparator;
8 import java.util.HashSet;
9 import java.util.Iterator;
10 import java.util.List;
11 import java.util.ListIterator;
13 import java.util.NoSuchElementException;
15 import java.util.function.Consumer;
17 import org.simantics.db.ReadGraph;
18 import org.simantics.db.Resource;
19 import org.simantics.db.Statement;
20 import org.simantics.db.exception.ResourceNotFoundException;
21 import org.simantics.db.impl.ResourceImpl;
22 import org.simantics.db.impl.graph.ReadGraphImpl;
23 import org.simantics.db.impl.query.IntSet;
24 import org.simantics.db.service.CollectionSupport;
26 import gnu.trove.impl.Constants;
27 import gnu.trove.iterator.TIntIterator;
28 import gnu.trove.list.array.TIntArrayList;
29 import gnu.trove.map.hash.TIntIntHashMap;
30 import gnu.trove.map.hash.TIntObjectHashMap;
31 import gnu.trove.procedure.TIntObjectProcedure;
32 import gnu.trove.procedure.TIntProcedure;
33 import gnu.trove.set.hash.TIntHashSet;
35 public class CollectionSupportImpl implements CollectionSupport {
37 final private SessionImplSocket session;
39 CollectionSupportImpl(SessionImplSocket session) {
40 this.session = session;
43 static final class IntResourceMap {
45 final private SessionImplSocket session;
46 final private TIntIntHashMap backend = new TIntIntHashMap(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, -1, 0);
48 IntResourceMap(SessionImplSocket session) {
49 this.session = session;
53 return backend.size();
56 public boolean isEmpty() {
57 return backend.isEmpty();
60 public boolean containsKey(int key) {
61 return backend.containsKey(key);
64 public boolean containsValue(int value) {
65 return backend.containsValue(value);
68 public Resource get(int key) {
70 return session.getResourceByKey(backend.get(key));
71 } catch (ResourceNotFoundException e) {
77 public Resource put(int key, Resource value) {
78 ResourceImpl impl = (ResourceImpl) value;
79 int i = backend.put(key, impl.id);
84 return session.getResourceByKey(i);
85 } catch (ResourceNotFoundException e) {
91 public Resource remove(int key) {
92 throw new UnsupportedOperationException("remove not supported");
96 public int hashCode() {
97 return backend.hashCode();
101 public boolean equals(Object obj) {
106 if (getClass() != obj.getClass())
108 IntResourceMap other = (IntResourceMap) obj;
109 return session == other.session && backend.equals(other.backend);
113 public IntResourceMap createIntResourceMap() {
114 return new IntResourceMap(session);
117 @SuppressWarnings("unchecked")
119 public <T, I> T createObjectResourceMap(Class<I> clazz) {
120 return (T)new ObjectResourceMap<I>(session);
123 @SuppressWarnings("unchecked")
125 public <T, I> T createObjectResourceMap(Class<I> clazz, int capacity) {
126 return (T)new ObjectResourceMap<I>(session, capacity);
129 static final class ResourceMap<T> implements org.simantics.db.ResourceMap<T> {
131 final private SessionImplSocket session;
132 final private TIntObjectHashMap<T> backend = new TIntObjectHashMap<T>();
134 ResourceMap(SessionImplSocket session) {
135 this.session = session;
139 public void clear() {
140 throw new UnsupportedOperationException("Not implemented");
144 public boolean containsKey(Object resource) {
145 ResourceImpl impl = (ResourceImpl)resource;
146 return backend.containsKey(impl.id);
149 @SuppressWarnings("unchecked")
151 public boolean containsValue(Object value) {
152 return backend.containsValue((T)value);
156 public Set<java.util.Map.Entry<Resource, T>> entrySet() {
157 final HashSet<java.util.Map.Entry<Resource, T>> result = new HashSet<java.util.Map.Entry<Resource, T>>();
158 backend.forEachEntry(new TIntObjectProcedure<T>() {
161 public boolean execute(final int a, final T b) {
162 result.add(new Map.Entry<Resource, T>() {
165 public Resource getKey() {
166 return new ResourceImpl(session.resourceSupport, a);
170 public T getValue() {
175 public T setValue(T arg0) {
176 throw new UnsupportedOperationException("Not supported");
188 public T get(Object resource) {
189 ResourceImpl impl = (ResourceImpl)resource;
190 return backend.get(impl.id);
194 public boolean isEmpty() {
195 return backend.isEmpty();
198 public class CallbackEntry<E> implements ResourceMapEntry<E> {
204 public Resource getKey() {
205 return new ResourceImpl(session.resourceSupport, id);
209 public E getValue() {
216 public void iterateEntries(final Consumer<ResourceMapEntry<T>> callback) {
217 final CallbackEntry<T> entry = new CallbackEntry<T>();
218 backend.forEach(new TIntProcedure() {
221 public boolean execute(int value) {
223 entry.value = backend.get(value);
224 callback.accept(entry);
231 public Set<Resource> keySet() {
232 final ResourceSet result = new ResourceSet(session);
233 backend.forEach(new TIntProcedure() {
236 public boolean execute(int value) {
245 public T put(Resource resource, T value) {
246 ResourceImpl impl = (ResourceImpl)resource;
247 return backend.put(impl.id, value);
251 public void putAll(Map<? extends Resource, ? extends T> map) {
252 @SuppressWarnings("unchecked")
253 ResourceMap<T> other = (ResourceMap<T>)map;
254 other.backend.forEachEntry(new TIntObjectProcedure<T>() {
257 public boolean execute(int a, T b) {
266 public T remove(Object key) {
267 if (key instanceof ResourceImpl) {
268 ResourceImpl impl = (ResourceImpl)key;
269 return backend.remove(impl.id);
276 return backend.size();
279 @SuppressWarnings("unchecked")
281 public Collection<T> values() {
282 ArrayList<T> result = new ArrayList<>();
283 for(Object o : backend.values()) result.add((T)o);
288 public int hashCode() {
289 return backend.hashCode();
293 public boolean equals(Object obj) {
298 if (getClass() != obj.getClass()) {
299 if (obj instanceof Map) {
300 // Nonoptimal fallback for comparing against generic Map
301 Map<?,?> m = (Map<?,?>) obj;
302 if (m.size() != size())
305 Iterator<Entry<Resource,T>> i = entrySet().iterator();
306 while (i.hasNext()) {
307 Entry<Resource,T> e = i.next();
308 Resource key = e.getKey();
309 T value = e.getValue();
311 if (!(m.get(key)==null && m.containsKey(key)))
314 if (!value.equals(m.get(key)))
319 } catch (ClassCastException unused) {
321 } catch (NullPointerException unused) {
327 ResourceMap<?> other = (ResourceMap<?>) obj;
328 return session == other.session && backend.equals(other.backend);
333 @SuppressWarnings("unchecked")
335 public <T, I> T createMap(Class<I> clazz) {
336 return (T)new ResourceMap<I>(session);
339 static final class ResourceSet implements Set<Resource> {
341 final private SessionImplSocket session;
342 final private TIntHashSet backend;
344 ResourceSet(SessionImplSocket session) {
345 this.session = session;
346 backend = new TIntHashSet();
349 ResourceSet(SessionImplSocket session, int capacity) {
350 this.session = session;
351 backend = new TIntHashSet(capacity);
355 public void clear() {
361 return backend.size();
365 public boolean add(Resource resource) {
366 ResourceImpl impl = (ResourceImpl)resource;
367 return backend.add(impl.id);
370 boolean add(int id) {
371 return backend.add(id);
375 public boolean addAll(Collection<? extends Resource> rs) {
376 boolean result = false;
377 for(Resource r : rs) result |= add(r);
382 public boolean contains(Object resource) {
383 ResourceImpl impl = (ResourceImpl)resource;
384 return backend.contains(impl.id);
388 public boolean containsAll(Collection<?> rs) {
396 public boolean isEmpty() {
397 return backend.isEmpty();
401 public Iterator<Resource> iterator() {
402 return new Iterator<Resource>() {
404 TIntIterator it = backend.iterator();
407 public boolean hasNext() {
412 public Resource next() {
413 return new ResourceImpl(session.resourceSupport, it.next());
417 public void remove() {
425 public boolean remove(Object resource) {
426 ResourceImpl impl = (ResourceImpl)resource;
427 return backend.remove(impl.id);
431 public boolean removeAll(Collection<?> rs) {
432 boolean result = false;
433 for(Object r : rs) result |= remove(r);
438 public boolean retainAll(Collection<?> arg0) {
439 throw new UnsupportedOperationException("Not implemented");
443 public Object[] toArray() {
444 return toArray(new Object[backend.size()]);
447 @SuppressWarnings("unchecked")
449 public <T> T[] toArray(T[] a) {
450 int size = backend.size();
451 T[] r = a.length >= size ? a :
452 (T[])Array.newInstance(a.getClass().getComponentType(), size);
453 backend.forEach(new TIntProcedure() {
458 public boolean execute(int value) {
459 r[index++] = (T)new ResourceImpl(session.resourceSupport, value);
467 public int hashCode() {
468 return backend.hashCode();
472 public boolean equals(Object obj) {
477 if (getClass() != obj.getClass()) {
478 if (obj instanceof Set) {
479 // Nonoptimal fallback for comparing against generic Set
480 Collection<?> c = (Collection<?>) obj;
481 if (c.size() != size())
484 return containsAll(c);
485 } catch (ClassCastException unused) {
487 } catch (NullPointerException unused) {
493 ResourceSet other = (ResourceSet) obj;
494 return session == other.session && backend.equals(other.backend);
500 public Set<Resource> createSet() {
501 return new ResourceSet(session);
505 public Set<Resource> createSet(int capacity) {
506 return new ResourceSet(session, capacity);
509 static final class ResourceList implements List<Resource> {
511 final private SessionImplSocket session;
512 final private TIntArrayList backend;
514 ResourceList(SessionImplSocket session) {
515 this.session = session;
516 this.backend = new TIntArrayList();
519 ResourceList(SessionImplSocket session, int capacity) {
520 this.session = session;
521 this.backend = new TIntArrayList(capacity);
524 ResourceList(SessionImplSocket session, Collection<Resource> rs) {
525 this.session = session;
526 this.backend = new TIntArrayList(rs.size());
531 public void clear() {
532 throw new UnsupportedOperationException("Not implemented");
537 return backend.size();
541 public boolean add(Resource resource) {
542 if(resource == null) {
545 ResourceImpl impl = (ResourceImpl)resource;
546 backend.add(impl.id);
552 public boolean addAll(Collection<? extends Resource> rs) {
553 if(rs instanceof ResourceList) {
554 ResourceList rl = (ResourceList)rs;
555 backend.addAll(rl.backend);
556 return !rl.isEmpty();
558 boolean result = true;
559 for(Resource r : rs) result &= add(r);
564 public boolean contains(Object resource) {
565 ResourceImpl impl = (ResourceImpl)resource;
566 return backend.contains(impl.id);
570 public boolean containsAll(Collection<?> rs) {
571 boolean result = true;
572 for(Object r : rs) result &= contains(r);
577 public boolean isEmpty() {
578 return backend.isEmpty();
582 public Iterator<Resource> iterator() {
583 return new Iterator<Resource>() {
586 int max = backend.size();
589 public boolean hasNext() {
594 public Resource next() {
597 throw new NoSuchElementException();
598 int id = backend.getQuick(i);
600 return new ResourceImpl(session.resourceSupport, id);
604 public void remove() {
605 throw new UnsupportedOperationException("remove not supported");
612 public boolean remove(Object resource) {
613 if(!(resource instanceof ResourceImpl)) return false;
614 ResourceImpl impl = (ResourceImpl)resource;
615 return backend.remove(impl.id);
619 public boolean removeAll(Collection<?> rs) {
620 boolean modified = false;
622 modified |= remove(o);
627 public boolean retainAll(Collection<?> arg0) {
628 throw new UnsupportedOperationException("Not implemented");
632 public Object[] toArray() {
633 return toArray(new Object[backend.size()]);
636 @SuppressWarnings("unchecked")
638 public <T> T[] toArray(T[] a) {
639 int size = backend.size();
640 T[] r = a.length >= size ? a :
641 (T[])Array.newInstance(a.getClass().getComponentType(), size);
642 backend.forEach(new TIntProcedure() {
647 public boolean execute(int value) {
648 r[index++] = (T)new ResourceImpl(session.resourceSupport, value);
660 public boolean addAll(int index, Collection<? extends Resource> rs) {
661 if(rs.isEmpty()) return false;
663 for(Resource r : rs) {
670 public Resource get(int index) {
671 int id = backend.get(index);
672 if(id == 0) return null;
673 return new ResourceImpl(session.resourceSupport, id);
677 public Resource set(int index, Resource resource) {
678 ResourceImpl impl = (ResourceImpl)resource;
679 int old = backend.set(index, impl.id);
680 if(old == 0) return null;
681 return new ResourceImpl(session.resourceSupport, old);
685 public void add(int index, Resource resource) {
686 ResourceImpl impl = (ResourceImpl)resource;
687 backend.insert(index, impl.id);
691 public Resource remove(int index) {
692 int id = backend.removeAt(index);
693 return new ResourceImpl(session.resourceSupport, id);
697 public int indexOf(Object o) {
698 if(!(o instanceof ResourceImpl)) return -1;
699 ResourceImpl impl = (ResourceImpl)o;
700 return backend.indexOf(impl.id);
704 public int lastIndexOf(Object o) {
705 if(!(o instanceof ResourceImpl)) return -1;
706 ResourceImpl impl = (ResourceImpl)o;
707 return backend.lastIndexOf(impl.id);
710 private class ListItr implements ListIterator<Resource> {
715 public ListItr(int index) {
721 public boolean hasNext() {
726 public Resource next() {
729 throw new NoSuchElementException();
730 int id = backend.getQuick(index);
732 return new ResourceImpl(session.resourceSupport, id);
736 public boolean hasPrevious() {
741 public Resource previous() {
744 throw new NoSuchElementException();
745 int id = backend.getQuick(index);
747 return new ResourceImpl(session.resourceSupport, id);
751 public int nextIndex() {
756 public int previousIndex() {
761 public void remove() {
762 throw new UnsupportedOperationException("remove not supported");
766 public void set(Resource e) {
767 throw new UnsupportedOperationException("set not supported");
771 public void add(Resource e) {
772 throw new UnsupportedOperationException("add not supported");
777 public ListIterator<Resource> listIterator() {
778 return new ListItr(0);
782 public ListIterator<Resource> listIterator(int index) {
783 if (index < 0 || index > backend.size())
784 throw new IndexOutOfBoundsException("Index: "+index);
785 return new ListItr(index);
789 public List<Resource> subList(int fromIndex, int toIndex) {
790 ResourceList result = new ResourceList(session);
791 for(int i=fromIndex;i<toIndex;i++)
797 public int hashCode() {
798 return backend.hashCode();
802 public boolean equals(Object obj) {
807 if (getClass() != obj.getClass()) {
808 if (obj instanceof List) {
809 // Nonoptimal fallback for comparing against generic List
810 ListIterator<?> e1 = listIterator();
811 ListIterator<?> e2 = ((List<?>) obj).listIterator();
812 while (e1.hasNext() && e2.hasNext()) {
813 Object o1 = e1.next();
814 Object o2 = e2.next();
815 if (!(o1==null ? o2==null : o1.equals(o2)))
818 return !(e1.hasNext() || e2.hasNext());
822 ResourceList other = (ResourceList) obj;
823 return session == other.session && backend.equals(other.backend);
829 public List<Resource> createList() {
830 return new ResourceList(session);
834 public List<Resource> createList(int capacity) {
835 return new ResourceList(session, capacity);
838 static final class StatementList implements Collection<Statement> {
840 final private SessionImplSocket session;
841 final private TIntArrayList backend = new TIntArrayList();
843 StatementList(SessionImplSocket session) {
844 this.session = session;
848 public void clear() {
849 throw new UnsupportedOperationException("Not implemented");
854 return backend.size() / 3;
858 public boolean add(Statement stm) {
859 ResourceImpl s = (ResourceImpl)stm.getSubject();
860 ResourceImpl p = (ResourceImpl)stm.getPredicate();
861 ResourceImpl o = (ResourceImpl)stm.getObject();
869 public boolean addAll(Collection<? extends Statement> rs) {
870 boolean result = false;
871 for(Statement r : rs) result |= add(r);
876 public boolean contains(Object statement) {
877 throw new UnsupportedOperationException("Not implemented");
881 public boolean containsAll(Collection<?> rs) {
882 throw new UnsupportedOperationException("Not implemented");
886 public boolean isEmpty() {
887 return backend.isEmpty();
891 public Iterator<Statement> iterator() {
892 return new Iterator<Statement>() {
895 int max = backend.size();
898 public boolean hasNext() {
903 public Statement next() {
904 return new DirectStatementImpl(session.resourceSupport, backend.getQuick(index++), backend.getQuick(index++), backend.getQuick(index++));
908 public void remove() {
909 throw new UnsupportedOperationException("Not supported");
916 public boolean remove(Object resource) {
917 throw new UnsupportedOperationException("Not implemented");
921 public boolean removeAll(Collection<?> rs) {
922 throw new UnsupportedOperationException("Not implemented");
926 public boolean retainAll(Collection<?> arg0) {
927 throw new UnsupportedOperationException("Not implemented");
931 public Object[] toArray() {
932 int stms = backend.size() / 3;
933 return toArray(new Object[stms]);
936 @SuppressWarnings("unchecked")
938 public <T> T[] toArray(T[] a) {
939 int size = backend.size();
941 T[] r = a.length >= size ? a :
942 (T[])Array.newInstance(a.getClass().getComponentType(), stms);
944 for (int i = 0; i < size; i += 3) {
945 r[index++] = (T) new DirectStatementImpl(session.resourceSupport, backend.getQuick(i), backend.getQuick(i+1), backend.getQuick(i+2));
951 public int hashCode() {
952 return backend.hashCode();
956 public boolean equals(Object obj) {
961 if (getClass() != obj.getClass()) {
962 if (obj instanceof Collection) {
963 // Nonoptimal fallback for comparing against generic Collection
964 Iterator<?> e1 = iterator();
965 Iterator<?> e2 = ((Collection<?>) obj).iterator();
966 while (e1.hasNext() && e2.hasNext()) {
967 Object o1 = e1.next();
968 Object o2 = e2.next();
969 if (!(o1==null ? o2==null : o1.equals(o2)))
972 return !(e1.hasNext() || e2.hasNext());
976 StatementList other = (StatementList) obj;
977 return session == other.session && backend.equals(other.backend);
983 public Collection<Statement> createStatementList() {
984 return new StatementList(session);
987 private static Comparator<Resource> RESOURCE_COMPARATOR = (o1, o2) -> {
988 ResourceImpl r1 = (ResourceImpl)o1;
989 ResourceImpl r2 = (ResourceImpl)o2;
990 return Integer.compare(r1.id, r2.id);
994 public void sort(List<Resource> list) {
995 if(list instanceof ResourceList) {
996 ((ResourceList) list).sort();
998 Collections.sort(list, RESOURCE_COMPARATOR);
1003 public List<Resource> asSortedList(Collection<Resource> rs) {
1004 ResourceList result = new ResourceList(session, rs);
1010 public org.simantics.db.ResourceSet getResourceSet(ReadGraph graph, Collection<Resource> resources) {
1011 if(resources instanceof ResourceSet) return (org.simantics.db.ResourceSet)resources;
1012 org.simantics.db.ResourceSet result = new IntSet(((ReadGraphImpl)graph).processor.querySupport);
1013 for(Resource r : resources) result.add(r);
1018 public org.simantics.db.ResourceSet getResourceSet(ReadGraph graph, Resource ... rs) {
1019 org.simantics.db.ResourceSet result = new IntSet(((ReadGraphImpl)graph).processor.querySupport);
1020 for(Resource r : rs) result.add(r);