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, Collection<Resource> rs) {
637 this.session = session;
638 this.backend = new TIntArrayList(rs.size());
643 public void clear() {
644 throw new UnsupportedOperationException("Not implemented");
649 return backend.size();
653 public boolean add(Resource resource) {
654 if(resource == null) {
657 ResourceImpl impl = (ResourceImpl)resource;
658 backend.add(impl.id);
664 public boolean addAll(Collection<? extends Resource> rs) {
665 if(rs instanceof ResourceList) {
666 ResourceList rl = (ResourceList)rs;
667 backend.addAll(rl.backend);
668 return !rl.isEmpty();
670 boolean result = true;
671 for(Resource r : rs) result &= add(r);
676 public boolean contains(Object resource) {
677 ResourceImpl impl = (ResourceImpl)resource;
678 return backend.contains(impl.id);
682 public boolean containsAll(Collection<?> rs) {
683 boolean result = true;
684 for(Object r : rs) result &= contains(r);
689 public boolean isEmpty() {
690 return backend.isEmpty();
694 public Iterator<Resource> iterator() {
695 return new Iterator<Resource>() {
697 int index = backend.size();
700 public boolean hasNext() {
705 public Resource next() {
706 return new ResourceImpl(session.resourceSupport, backend.getQuick(--index));
710 public void remove() {
711 throw new UnsupportedOperationException("Not supported");
718 public boolean remove(Object resource) {
719 if(!(resource instanceof ResourceImpl)) return false;
720 ResourceImpl impl = (ResourceImpl)resource;
721 return backend.remove(impl.id);
725 public boolean removeAll(Collection<?> rs) {
726 boolean modified = false;
728 modified |= remove(o);
733 public boolean retainAll(Collection<?> arg0) {
734 throw new UnsupportedOperationException("Not implemented");
738 public Object[] toArray() {
739 return toArray(new Object[backend.size()]);
742 @SuppressWarnings("unchecked")
744 public <T> T[] toArray(T[] arg0) {
745 final T[] result = (T[])Array.newInstance(arg0.getClass().getComponentType(), backend.size());
746 backend.forEach(new TIntProcedure() {
751 public boolean execute(int value) {
752 result[index++] = (T)new ResourceImpl(session.resourceSupport, value);
764 public boolean addAll(int index, Collection<? extends Resource> rs) {
765 if(rs.isEmpty()) return false;
767 for(Resource r : rs) {
774 public Resource get(int index) {
775 int id = backend.get(index);
776 if(id == 0) return null;
777 return new ResourceImpl(session.resourceSupport, id);
781 public Resource set(int index, Resource resource) {
782 ResourceImpl impl = (ResourceImpl)resource;
783 int old = backend.set(index, impl.id);
784 if(old == 0) return null;
785 return new ResourceImpl(session.resourceSupport, old);
789 public void add(int index, Resource resource) {
790 ResourceImpl impl = (ResourceImpl)resource;
791 backend.insert(index, impl.id);
795 public Resource remove(int index) {
796 int id = backend.removeAt(index);
797 return new ResourceImpl(session.resourceSupport, id);
801 public int indexOf(Object o) {
802 if(!(o instanceof ResourceImpl)) return -1;
803 ResourceImpl impl = (ResourceImpl)o;
804 return backend.indexOf(impl.id);
808 public int lastIndexOf(Object o) {
809 if(!(o instanceof ResourceImpl)) return -1;
810 ResourceImpl impl = (ResourceImpl)o;
811 return backend.lastIndexOf(impl.id);
815 public ListIterator<Resource> listIterator() {
816 throw new UnsupportedOperationException("Not implemented");
820 public ListIterator<Resource> listIterator(int index) {
821 throw new UnsupportedOperationException("Not implemented");
825 public List<Resource> subList(int fromIndex, int toIndex) {
826 ResourceList result = new ResourceList(session);
827 for(int i=fromIndex;i<toIndex;i++)
833 public int hashCode() {
834 return backend.hashCode();
838 public boolean equals(Object obj) {
843 if (getClass() != obj.getClass())
845 ResourceList other = (ResourceList) obj;
846 return session == other.session && backend.equals(other.backend);
852 public List<Resource> createList() {
853 return new ResourceList(session);
856 static final class StatementList implements Collection<Statement> {
858 final private SessionImplSocket session;
859 final private TIntArrayList backend = new TIntArrayList();
861 StatementList(SessionImplSocket session) {
862 this.session = session;
866 public void clear() {
867 throw new UnsupportedOperationException("Not implemented");
872 return backend.size() / 3;
876 public boolean add(Statement stm) {
877 ResourceImpl s = (ResourceImpl)stm.getSubject();
878 ResourceImpl p = (ResourceImpl)stm.getPredicate();
879 ResourceImpl o = (ResourceImpl)stm.getObject();
887 public boolean addAll(Collection<? extends Statement> rs) {
888 boolean result = true;
889 for(Statement r : rs) result &= add(r);
894 public boolean contains(Object statement) {
895 throw new UnsupportedOperationException("Not implemented");
899 public boolean containsAll(Collection<?> rs) {
900 throw new UnsupportedOperationException("Not implemented");
904 public boolean isEmpty() {
905 return backend.isEmpty();
909 public Iterator<Statement> iterator() {
910 return new Iterator<Statement>() {
913 int max = backend.size();
916 public boolean hasNext() {
921 public Statement next() {
922 return new DirectStatementImpl(session.resourceSupport, backend.getQuick(index++), backend.getQuick(index++), backend.getQuick(index++));
926 public void remove() {
927 throw new UnsupportedOperationException("Not supported");
934 public boolean remove(Object resource) {
935 throw new UnsupportedOperationException("Not implemented");
939 public boolean removeAll(Collection<?> rs) {
940 throw new UnsupportedOperationException("Not implemented");
944 public boolean retainAll(Collection<?> arg0) {
945 throw new UnsupportedOperationException("Not implemented");
949 public Object[] toArray() {
950 throw new UnsupportedOperationException("Not implemented");
953 @SuppressWarnings("unchecked")
955 public <T> T[] toArray(T[] arg0) {
956 final T[] result = (T[])Array.newInstance(arg0.getClass().getComponentType(), backend.size());
957 backend.forEach(new TIntProcedure() {
962 public boolean execute(int value) {
963 result[index++] = (T)new ResourceImpl(session.resourceSupport, value);
971 public int hashCode() {
972 return backend.hashCode();
976 public boolean equals(Object obj) {
981 if (getClass() != obj.getClass())
983 StatementList other = (StatementList) obj;
984 return session == other.session && backend.equals(other.backend);
990 public Collection<Statement> createStatementList() {
991 return new StatementList(session);
994 private static Comparator<Resource> RESOURCE_COMPARATOR = new Comparator<Resource>() {
996 public int compare(Resource o1, Resource o2) {
997 ResourceImpl r1 = (ResourceImpl)o1;
998 ResourceImpl r2 = (ResourceImpl)o2;
999 return compare(r1.id, r2.id);
1002 private int compare(int x, int y) {
1003 return (x < y) ? -1 : ((x == y) ? 0 : 1);
1008 public void sort(List<Resource> list) {
1009 if(list instanceof ResourceList) {
1010 ((ResourceList) list).sort();
1012 Collections.sort(list, RESOURCE_COMPARATOR);
1017 public List<Resource> asSortedList(Collection<Resource> rs) {
1018 ResourceList result = new ResourceList(session, rs);
1024 public org.simantics.db.ResourceSet getResourceSet(ReadGraph graph, Collection<Resource> resources) {
1025 if(resources instanceof ResourceSet) return (org.simantics.db.ResourceSet)resources;
1026 org.simantics.db.ResourceSet result = new IntSet(((ReadGraphImpl)graph).processor.querySupport);
1027 for(Resource r : resources) result.add(r);
1032 public org.simantics.db.ResourceSet getResourceSet(ReadGraph graph, Resource ... rs) {
1033 org.simantics.db.ResourceSet result = new IntSet(((ReadGraphImpl)graph).processor.querySupport);
1034 for(Resource r : rs) result.add(r);