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 implements Map, ObjectResourceIdMap { private final SessionImplSocket session; private final TObjectIntHashMap 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 map) { @SuppressWarnings("unchecked") ObjectResourceMap other = (ObjectResourceMap) map; other.backend.forEachEntry(new TObjectIntProcedure() { @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 keySet() { final Set result = new HashSet<>(); backend.forEach(new TObjectProcedure() { @Override public boolean execute(T object) { result.add(object); return true; } }); return result; } @Override public Collection values() { ArrayList result = new ArrayList<>(); for (int key : backend.values()) { try { result.add(session.getResourceByKey(key)); } catch (ResourceNotFoundException e) { e.printStackTrace(); } } return result; } @Override public Set> entrySet() { final HashSet> result = new HashSet<>(); backend.forEachEntry(new TObjectIntProcedure() { @Override public boolean execute(final T a, final int b) { return result.add(new Map.Entry() { @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> i = entrySet().iterator(); while (i.hasNext()) { Entry 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); } }