]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ObjectResourceMap.java
Multiple reader thread support for db client
[simantics/platform.git] / bundles / org.simantics.db.procore / src / fi / vtt / simantics / procore / internal / ObjectResourceMap.java
diff --git a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ObjectResourceMap.java b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ObjectResourceMap.java
new file mode 100644 (file)
index 0000000..8b26442
--- /dev/null
@@ -0,0 +1,218 @@
+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> {
+
+       private final SessionImplSocket session;
+       private final TObjectIntHashMap<T> backend;
+
+       ObjectResourceMap(SessionImplSocket session) {
+               this.session = session;
+               backend = new TObjectIntHashMap<>(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, 0);
+       }
+
+       ObjectResourceMap(SessionImplSocket session, int capacity) {
+               this.session = session;
+               backend = new TObjectIntHashMap<>(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<>();
+               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<>();
+               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<>();
+               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