+package fi.vtt.simantics.procore.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.simantics.db.ObjectResourceIdMap;
+import org.simantics.db.Resource;
+import org.simantics.db.exception.ResourceNotFoundException;
+import org.simantics.db.impl.ResourceImpl;
+
+import gnu.trove.impl.Constants;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.procedure.TObjectIntProcedure;
+import gnu.trove.procedure.TObjectProcedure;
+
+final class ObjectResourceMap<T> implements Map<T, Resource>, ObjectResourceIdMap<T> {
+
+ final private SessionImplSocket session;
+ final private TObjectIntHashMap<T> backend;
+
+ ObjectResourceMap(SessionImplSocket session) {
+ this.session = session;
+ backend = new TObjectIntHashMap<T>(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, 0);
+ }
+
+ ObjectResourceMap(SessionImplSocket session, int capacity) {
+ this.session = session;
+ backend = new TObjectIntHashMap<T>(capacity, Constants.DEFAULT_LOAD_FACTOR, 0);
+ }
+
+ @Override
+ public int size() {
+ return backend.size();
+ }
+ @Override
+ public boolean isEmpty() {
+ return backend.isEmpty();
+ }
+
+ @Override
+ public boolean containsKey(Object key) {
+ return backend.contains(key);
+ }
+
+ @Override
+ public boolean containsValue(Object value) {
+ ResourceImpl impl = (ResourceImpl) value;
+ return backend.containsValue(impl.id);
+ }
+
+ @Override
+ public Resource get(Object key) {
+ try {
+ int result = backend.get(key);
+ if (result == 0)
+ return null;
+ return session.getResourceByKey(result);
+ } catch (ResourceNotFoundException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ @Override
+ public Resource put(T key, Resource value) {
+ ResourceImpl impl = (ResourceImpl) value;
+ int i = backend.put(key, impl.id);
+ if (i == 0)
+ return null;
+ else
+ try {
+ return session.getResourceByKey(i);
+ } catch (ResourceNotFoundException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ @Override
+ public Resource remove(Object key) {
+ throw new UnsupportedOperationException("remove not supported, structure is immutable");
+ }
+
+ @Override
+ public void putAll(Map<? extends T, ? extends Resource> map) {
+ @SuppressWarnings("unchecked")
+ ObjectResourceMap<T> other = (ObjectResourceMap<T>) map;
+ other.backend.forEachEntry(new TObjectIntProcedure<T>() {
+
+ @Override
+ public boolean execute(T a, int b) {
+ backend.put(a, b);
+ return true;
+ }
+ });
+ }
+
+ @Override
+ public void clear() {
+ throw new UnsupportedOperationException("clear not supported, structure is immutable");
+ }
+
+ @Override
+ public Set<T> keySet() {
+ final Set<T> result = new HashSet<T>();
+ backend.forEach(new TObjectProcedure<T>() {
+
+ @Override
+ public boolean execute(T object) {
+ result.add(object);
+ return true;
+ }
+ });
+ return result;
+ }
+
+ @Override
+ public Collection<Resource> values() {
+ ArrayList<Resource> result = new ArrayList<Resource>();
+ for (int key : backend.values()) {
+ try {
+ result.add(session.getResourceByKey(key));
+ } catch (ResourceNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public Set<java.util.Map.Entry<T, Resource>> entrySet() {
+ final HashSet<java.util.Map.Entry<T, Resource>> result = new HashSet<java.util.Map.Entry<T, Resource>>();
+ backend.forEachEntry(new TObjectIntProcedure<T>() {
+
+ @Override
+ public boolean execute(final T a, final int b) {
+ return result.add(new Map.Entry<T, Resource>() {
+
+ @Override
+ public T getKey() {
+ return a;
+ }
+
+ @Override
+ public Resource getValue() {
+ return new ResourceImpl(session.resourceSupport, b);
+ }
+
+ @Override
+ public Resource setValue(Resource value) {
+ throw new UnsupportedOperationException("Map.Entry.setValue not supported, structure is immutable");
+ }
+
+ });
+ }
+ });
+ return result;
+ }
+
+ @Override
+ public int hashCode() {
+ return backend.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass()) {
+ if (obj instanceof Map) {
+ // Nonoptimal fallback for comparing against generic Map
+ Map<?,?> m = (Map<?,?>) obj;
+ if (m.size() != size())
+ return false;
+ try {
+ Iterator<Entry<T,Resource>> i = entrySet().iterator();
+ while (i.hasNext()) {
+ Entry<T,Resource> e = i.next();
+ T key = e.getKey();
+ Resource value = e.getValue();
+ if (value == null) {
+ if (!(m.get(key)==null && m.containsKey(key)))
+ return false;
+ } else {
+ if (!value.equals(m.get(key)))
+ return false;
+ }
+ }
+ return true;
+ } catch (ClassCastException unused) {
+ return false;
+ } catch (NullPointerException unused) {
+ return false;
+ }
+ }
+ return false;
+ }
+ ObjectResourceMap<?> other = (ObjectResourceMap<?>) obj;
+ return session == other.session && backend.equals(other.backend);
+ }
+
+ @Override
+ public void putId(T t, int r) {
+ backend.put(t, r);
+ }
+
+ @Override
+ public int getId(T t) {
+ return backend.get(t);
+ }
+
+}
\ No newline at end of file