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;
15 import org.simantics.db.ReadGraph;
16 import org.simantics.db.Resource;
17 import org.simantics.db.Statement;
18 import org.simantics.db.exception.ResourceNotFoundException;
19 import org.simantics.db.impl.ResourceImpl;
20 import org.simantics.db.impl.graph.ReadGraphImpl;
21 import org.simantics.db.impl.query.IntSet;
22 import org.simantics.db.service.CollectionSupport;
23 import org.simantics.utils.datastructures.Callback;
25 import gnu.trove.impl.Constants;
26 import gnu.trove.iterator.TIntIterator;
27 import gnu.trove.list.array.TIntArrayList;
28 import gnu.trove.map.hash.TIntIntHashMap;
29 import gnu.trove.map.hash.TIntObjectHashMap;
30 import gnu.trove.map.hash.TObjectIntHashMap;
31 import gnu.trove.procedure.TIntObjectProcedure;
32 import gnu.trove.procedure.TIntProcedure;
33 import gnu.trove.procedure.TObjectIntProcedure;
34 import gnu.trove.procedure.TObjectProcedure;
35 import gnu.trove.set.hash.TIntHashSet;
37 public class CollectionSupportImpl implements CollectionSupport {
39 final private SessionImplSocket session;
41 CollectionSupportImpl(SessionImplSocket session) {
42 this.session = session;
45 static final class IntResourceMap {
47 final private SessionImplSocket session;
48 final private TIntIntHashMap backend = new TIntIntHashMap(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, -1, 0);
50 IntResourceMap(SessionImplSocket session) {
51 this.session = session;
55 return backend.size();
58 public boolean isEmpty() {
59 return backend.isEmpty();
62 public boolean containsKey(int key) {
63 return backend.containsKey(key);
66 public boolean containsValue(int value) {
67 return backend.containsValue(value);
70 public Resource get(int key) {
72 return session.getResourceByKey(backend.get(key));
73 } catch (ResourceNotFoundException e) {
79 public Resource put(int key, Resource value) {
80 ResourceImpl impl = (ResourceImpl) value;
81 int i = backend.put(key, impl.id);
86 return session.getResourceByKey(i);
87 } catch (ResourceNotFoundException e) {
93 public Resource remove(int key) {
94 throw new UnsupportedOperationException("remove not supported");
98 public int hashCode() {
99 return backend.hashCode();
103 public boolean equals(Object obj) {
108 if (getClass() != obj.getClass())
110 IntResourceMap other = (IntResourceMap) obj;
111 return session == other.session && backend.equals(other.backend);
115 public IntResourceMap createIntResourceMap() {
116 return new IntResourceMap(session);
119 static final class ObjectResourceMap<T> implements Map<T, Resource> {
121 final private SessionImplSocket session;
122 final private TObjectIntHashMap<T> backend;
124 ObjectResourceMap(SessionImplSocket session) {
125 this.session = session;
126 backend = new TObjectIntHashMap<T>(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, 0);
129 ObjectResourceMap(SessionImplSocket session, int capacity) {
130 this.session = session;
131 backend = new TObjectIntHashMap<T>(capacity, Constants.DEFAULT_LOAD_FACTOR, 0);
136 return backend.size();
139 public boolean isEmpty() {
140 return backend.isEmpty();
144 public boolean containsKey(Object key) {
145 return backend.contains(key);
149 public boolean containsValue(Object value) {
150 ResourceImpl impl = (ResourceImpl) value;
151 return backend.containsValue(impl.id);
155 public Resource get(Object key) {
157 int result = backend.get(key);
160 return session.getResourceByKey(result);
161 } catch (ResourceNotFoundException e) {
168 public Resource put(T key, Resource value) {
169 ResourceImpl impl = (ResourceImpl) value;
170 int i = backend.put(key, impl.id);
175 return session.getResourceByKey(i);
176 } catch (ResourceNotFoundException e) {
183 public Resource remove(Object key) {
184 throw new UnsupportedOperationException("remove not supported, structure is immutable");
188 public void putAll(Map<? extends T, ? extends Resource> map) {
189 @SuppressWarnings("unchecked")
190 ObjectResourceMap<T> other = (ObjectResourceMap<T>) map;
191 other.backend.forEachEntry(new TObjectIntProcedure<T>() {
194 public boolean execute(T a, int b) {
202 public void clear() {
203 throw new UnsupportedOperationException("clear not supported, structure is immutable");
207 public Set<T> keySet() {
208 final Set<T> result = new HashSet<T>();
209 backend.forEach(new TObjectProcedure<T>() {
212 public boolean execute(T object) {
221 public Collection<Resource> values() {
222 ArrayList<Resource> result = new ArrayList<Resource>();
223 for (int key : backend.values()) {
225 result.add(session.getResourceByKey(key));
226 } catch (ResourceNotFoundException e) {
234 public Set<java.util.Map.Entry<T, Resource>> entrySet() {
235 final HashSet<java.util.Map.Entry<T, Resource>> result = new HashSet<java.util.Map.Entry<T, Resource>>();
236 backend.forEachEntry(new TObjectIntProcedure<T>() {
239 public boolean execute(final T a, final int b) {
240 return result.add(new Map.Entry<T, Resource>() {
248 public Resource getValue() {
249 return new ResourceImpl(session.resourceSupport, b);
253 public Resource setValue(Resource value) {
254 throw new UnsupportedOperationException("Map.Entry.setValue not supported, structure is immutable");
264 public int hashCode() {
265 return backend.hashCode();
269 public boolean equals(Object obj) {
274 if (getClass() != obj.getClass())
276 ObjectResourceMap<?> other = (ObjectResourceMap<?>) obj;
277 return session == other.session && backend.equals(other.backend);
282 @SuppressWarnings("unchecked")
284 public <T, I> T createObjectResourceMap(Class<I> clazz) {
285 return (T)new ObjectResourceMap<I>(session);
288 @SuppressWarnings("unchecked")
290 public <T, I> T createObjectResourceMap(Class<I> clazz, int capacity) {
291 return (T)new ObjectResourceMap<I>(session, capacity);
294 static final class ResourceMap<T> implements org.simantics.db.ResourceMap<T> {
296 final private SessionImplSocket session;
297 final private TIntObjectHashMap<T> backend = new TIntObjectHashMap<T>();
299 ResourceMap(SessionImplSocket session) {
300 this.session = session;
304 public void clear() {
305 throw new UnsupportedOperationException("Not implemented");
309 public boolean containsKey(Object resource) {
310 ResourceImpl impl = (ResourceImpl)resource;
311 return backend.containsKey(impl.id);
314 @SuppressWarnings("unchecked")
316 public boolean containsValue(Object value) {
317 return backend.containsValue((T)value);
321 public Set<java.util.Map.Entry<Resource, T>> entrySet() {
322 final HashSet<java.util.Map.Entry<Resource, T>> result = new HashSet<java.util.Map.Entry<Resource, T>>();
323 backend.forEachEntry(new TIntObjectProcedure<T>() {
326 public boolean execute(final int a, final T b) {
327 result.add(new Map.Entry<Resource, T>() {
330 public Resource getKey() {
331 return new ResourceImpl(session.resourceSupport, a);
335 public T getValue() {
340 public T setValue(T arg0) {
341 throw new UnsupportedOperationException("Not supported");
353 public T get(Object resource) {
354 ResourceImpl impl = (ResourceImpl)resource;
355 return backend.get(impl.id);
359 public boolean isEmpty() {
360 return backend.isEmpty();
363 public class CallbackEntry<E> implements ResourceMapEntry<E> {
369 public Resource getKey() {
370 return new ResourceImpl(session.resourceSupport, id);
374 public E getValue() {
381 public void iterateEntries(final Callback<ResourceMapEntry<T>> callback) {
382 final CallbackEntry<T> entry = new CallbackEntry<T>();
383 backend.forEach(new TIntProcedure() {
386 public boolean execute(int value) {
388 entry.value = backend.get(value);
396 public Set<Resource> keySet() {
397 final ResourceSet result = new ResourceSet(session);
398 backend.forEach(new TIntProcedure() {
401 public boolean execute(int value) {
410 public T put(Resource resource, T value) {
411 ResourceImpl impl = (ResourceImpl)resource;
412 return backend.put(impl.id, value);
416 public void putAll(Map<? extends Resource, ? extends T> map) {
417 @SuppressWarnings("unchecked")
418 ResourceMap<T> other = (ResourceMap<T>)map;
419 other.backend.forEachEntry(new TIntObjectProcedure<T>() {
422 public boolean execute(int a, T b) {
431 public T remove(Object arg0) {
432 throw new UnsupportedOperationException("Not implemented");
437 return backend.size();
440 @SuppressWarnings("unchecked")
442 public Collection<T> values() {
443 ArrayList<T> result = new ArrayList<T>();
444 for(Object o : backend.values()) result.add((T)o);
449 public int hashCode() {
450 return backend.hashCode();
454 public boolean equals(Object obj) {
459 if (getClass() != obj.getClass())
461 ResourceMap<?> other = (ResourceMap<?>) obj;
462 return session == other.session && backend.equals(other.backend);
467 @SuppressWarnings("unchecked")
469 public <T, I> T createMap(Class<I> clazz) {
470 return (T)new ResourceMap<I>(session);
473 static final class ResourceSet implements Set<Resource> {
475 final private SessionImplSocket session;
476 final private TIntHashSet backend;
478 ResourceSet(SessionImplSocket session) {
479 this.session = session;
480 backend = new TIntHashSet();
483 ResourceSet(SessionImplSocket session, int capacity) {
484 this.session = session;
485 backend = new TIntHashSet(capacity);
489 public void clear() {
495 return backend.size();
499 public boolean add(Resource resource) {
500 ResourceImpl impl = (ResourceImpl)resource;
501 return backend.add(impl.id);
504 boolean add(int id) {
505 return backend.add(id);
509 public boolean addAll(Collection<? extends Resource> rs) {
510 boolean result = true;
511 for(Resource r : rs) result &= add(r);
516 public boolean contains(Object resource) {
517 ResourceImpl impl = (ResourceImpl)resource;
518 return backend.contains(impl.id);
522 public boolean containsAll(Collection<?> rs) {
523 boolean result = true;
524 for(Object r : rs) result &= contains(r);
529 public boolean isEmpty() {
530 return backend.isEmpty();
534 public Iterator<Resource> iterator() {
535 return new Iterator<Resource>() {
537 TIntIterator it = backend.iterator();
540 public boolean hasNext() {
545 public Resource next() {
546 return new ResourceImpl(session.resourceSupport, it.next());
550 public void remove() {
558 public boolean remove(Object resource) {
559 ResourceImpl impl = (ResourceImpl)resource;
560 return backend.remove(impl.id);
564 public boolean removeAll(Collection<?> rs) {
565 boolean result = true;
566 for(Object r : rs) result &= remove(r);
571 public boolean retainAll(Collection<?> arg0) {
572 throw new UnsupportedOperationException("Not implemented");
576 public Object[] toArray() {
577 throw new UnsupportedOperationException("Not implemented");
580 @SuppressWarnings("unchecked")
582 public <T> T[] toArray(T[] arg0) {
583 final T[] result = (T[])Array.newInstance(arg0.getClass().getComponentType(), backend.size());
584 backend.forEach(new TIntProcedure() {
589 public boolean execute(int value) {
590 result[index++] = (T)new ResourceImpl(session.resourceSupport, value);
598 public int hashCode() {
599 return backend.hashCode();
603 public boolean equals(Object obj) {
608 if (getClass() != obj.getClass())
610 ResourceSet other = (ResourceSet) obj;
611 return session == other.session && backend.equals(other.backend);
617 public Set<Resource> createSet() {
618 return new ResourceSet(session);
622 public Set<Resource> createSet(int capacity) {
623 return new ResourceSet(session, capacity);
626 static final class ResourceList implements List<Resource> {
628 final private SessionImplSocket session;
629 final private TIntArrayList backend;
631 ResourceList(SessionImplSocket session) {
632 this.session = session;
633 this.backend = new TIntArrayList();
636 ResourceList(SessionImplSocket session, int capacity) {
637 this.session = session;
638 this.backend = new TIntArrayList(capacity);
641 ResourceList(SessionImplSocket session, Collection<Resource> rs) {
642 this.session = session;
643 this.backend = new TIntArrayList(rs.size());
648 public void clear() {
649 throw new UnsupportedOperationException("Not implemented");
654 return backend.size();
658 public boolean add(Resource resource) {
659 if(resource == null) {
662 ResourceImpl impl = (ResourceImpl)resource;
663 backend.add(impl.id);
669 public boolean addAll(Collection<? extends Resource> rs) {
670 if(rs instanceof ResourceList) {
671 ResourceList rl = (ResourceList)rs;
672 backend.addAll(rl.backend);
673 return !rl.isEmpty();
675 boolean result = true;
676 for(Resource r : rs) result &= add(r);
681 public boolean contains(Object resource) {
682 ResourceImpl impl = (ResourceImpl)resource;
683 return backend.contains(impl.id);
687 public boolean containsAll(Collection<?> rs) {
688 boolean result = true;
689 for(Object r : rs) result &= contains(r);
694 public boolean isEmpty() {
695 return backend.isEmpty();
699 public Iterator<Resource> iterator() {
700 return new Iterator<Resource>() {
702 int index = backend.size();
705 public boolean hasNext() {
710 public Resource next() {
711 return new ResourceImpl(session.resourceSupport, backend.getQuick(--index));
715 public void remove() {
716 throw new UnsupportedOperationException("Not supported");
723 public boolean remove(Object resource) {
724 if(!(resource instanceof ResourceImpl)) return false;
725 ResourceImpl impl = (ResourceImpl)resource;
726 return backend.remove(impl.id);
730 public boolean removeAll(Collection<?> rs) {
731 boolean modified = false;
733 modified |= remove(o);
738 public boolean retainAll(Collection<?> arg0) {
739 throw new UnsupportedOperationException("Not implemented");
743 public Object[] toArray() {
744 return toArray(new Object[backend.size()]);
747 @SuppressWarnings("unchecked")
749 public <T> T[] toArray(T[] arg0) {
750 final T[] result = (T[])Array.newInstance(arg0.getClass().getComponentType(), backend.size());
751 backend.forEach(new TIntProcedure() {
756 public boolean execute(int value) {
757 result[index++] = (T)new ResourceImpl(session.resourceSupport, value);
769 public boolean addAll(int index, Collection<? extends Resource> rs) {
770 if(rs.isEmpty()) return false;
772 for(Resource r : rs) {
779 public Resource get(int index) {
780 int id = backend.get(index);
781 if(id == 0) return null;
782 return new ResourceImpl(session.resourceSupport, id);
786 public Resource set(int index, Resource resource) {
787 ResourceImpl impl = (ResourceImpl)resource;
788 int old = backend.set(index, impl.id);
789 if(old == 0) return null;
790 return new ResourceImpl(session.resourceSupport, old);
794 public void add(int index, Resource resource) {
795 ResourceImpl impl = (ResourceImpl)resource;
796 backend.insert(index, impl.id);
800 public Resource remove(int index) {
801 int id = backend.removeAt(index);
802 return new ResourceImpl(session.resourceSupport, id);
806 public int indexOf(Object o) {
807 if(!(o instanceof ResourceImpl)) return -1;
808 ResourceImpl impl = (ResourceImpl)o;
809 return backend.indexOf(impl.id);
813 public int lastIndexOf(Object o) {
814 if(!(o instanceof ResourceImpl)) return -1;
815 ResourceImpl impl = (ResourceImpl)o;
816 return backend.lastIndexOf(impl.id);
820 public ListIterator<Resource> listIterator() {
821 throw new UnsupportedOperationException("Not implemented");
825 public ListIterator<Resource> listIterator(int index) {
826 throw new UnsupportedOperationException("Not implemented");
830 public List<Resource> subList(int fromIndex, int toIndex) {
831 ResourceList result = new ResourceList(session);
832 for(int i=fromIndex;i<toIndex;i++)
838 public int hashCode() {
839 return backend.hashCode();
843 public boolean equals(Object obj) {
848 if (getClass() != obj.getClass())
850 ResourceList other = (ResourceList) obj;
851 return session == other.session && backend.equals(other.backend);
857 public List<Resource> createList() {
858 return new ResourceList(session);
862 public List<Resource> createList(int capacity) {
863 return new ResourceList(session, capacity);
866 static final class StatementList implements Collection<Statement> {
868 final private SessionImplSocket session;
869 final private TIntArrayList backend = new TIntArrayList();
871 StatementList(SessionImplSocket session) {
872 this.session = session;
876 public void clear() {
877 throw new UnsupportedOperationException("Not implemented");
882 return backend.size() / 3;
886 public boolean add(Statement stm) {
887 ResourceImpl s = (ResourceImpl)stm.getSubject();
888 ResourceImpl p = (ResourceImpl)stm.getPredicate();
889 ResourceImpl o = (ResourceImpl)stm.getObject();
897 public boolean addAll(Collection<? extends Statement> rs) {
898 boolean result = true;
899 for(Statement r : rs) result &= add(r);
904 public boolean contains(Object statement) {
905 throw new UnsupportedOperationException("Not implemented");
909 public boolean containsAll(Collection<?> rs) {
910 throw new UnsupportedOperationException("Not implemented");
914 public boolean isEmpty() {
915 return backend.isEmpty();
919 public Iterator<Statement> iterator() {
920 return new Iterator<Statement>() {
923 int max = backend.size();
926 public boolean hasNext() {
931 public Statement next() {
932 return new DirectStatementImpl(session.resourceSupport, backend.getQuick(index++), backend.getQuick(index++), backend.getQuick(index++));
936 public void remove() {
937 throw new UnsupportedOperationException("Not supported");
944 public boolean remove(Object resource) {
945 throw new UnsupportedOperationException("Not implemented");
949 public boolean removeAll(Collection<?> rs) {
950 throw new UnsupportedOperationException("Not implemented");
954 public boolean retainAll(Collection<?> arg0) {
955 throw new UnsupportedOperationException("Not implemented");
959 public Object[] toArray() {
960 throw new UnsupportedOperationException("Not implemented");
963 @SuppressWarnings("unchecked")
965 public <T> T[] toArray(T[] arg0) {
966 final T[] result = (T[])Array.newInstance(arg0.getClass().getComponentType(), backend.size());
967 backend.forEach(new TIntProcedure() {
972 public boolean execute(int value) {
973 result[index++] = (T)new ResourceImpl(session.resourceSupport, value);
981 public int hashCode() {
982 return backend.hashCode();
986 public boolean equals(Object obj) {
991 if (getClass() != obj.getClass())
993 StatementList other = (StatementList) obj;
994 return session == other.session && backend.equals(other.backend);
1000 public Collection<Statement> createStatementList() {
1001 return new StatementList(session);
1004 private static Comparator<Resource> RESOURCE_COMPARATOR = new Comparator<Resource>() {
1006 public int compare(Resource o1, Resource o2) {
1007 ResourceImpl r1 = (ResourceImpl)o1;
1008 ResourceImpl r2 = (ResourceImpl)o2;
1009 return compare(r1.id, r2.id);
1012 private int compare(int x, int y) {
1013 return (x < y) ? -1 : ((x == y) ? 0 : 1);
1018 public void sort(List<Resource> list) {
1019 if(list instanceof ResourceList) {
1020 ((ResourceList) list).sort();
1022 Collections.sort(list, RESOURCE_COMPARATOR);
1027 public List<Resource> asSortedList(Collection<Resource> rs) {
1028 ResourceList result = new ResourceList(session, rs);
1034 public org.simantics.db.ResourceSet getResourceSet(ReadGraph graph, Collection<Resource> resources) {
1035 if(resources instanceof ResourceSet) return (org.simantics.db.ResourceSet)resources;
1036 org.simantics.db.ResourceSet result = new IntSet(((ReadGraphImpl)graph).processor.querySupport);
1037 for(Resource r : resources) result.add(r);
1042 public org.simantics.db.ResourceSet getResourceSet(ReadGraph graph, Resource ... rs) {
1043 org.simantics.db.ResourceSet result = new IntSet(((ReadGraphImpl)graph).processor.querySupport);
1044 for(Resource r : rs) result.add(r);