]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 package fi.vtt.simantics.procore.internal;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.HashSet;
6 import java.util.Iterator;
7 import java.util.Map;
8 import java.util.Set;
9
10 import org.simantics.db.ObjectResourceIdMap;
11 import org.simantics.db.Resource;
12 import org.simantics.db.exception.ResourceNotFoundException;
13 import org.simantics.db.impl.ResourceImpl;
14
15 import gnu.trove.impl.Constants;
16 import gnu.trove.map.hash.TObjectIntHashMap;
17 import gnu.trove.procedure.TObjectIntProcedure;
18 import gnu.trove.procedure.TObjectProcedure;
19
20 final class ObjectResourceMap<T> implements Map<T, Resource>, ObjectResourceIdMap<T> {
21
22         private final SessionImplSocket session;
23         private final TObjectIntHashMap<T> backend;
24
25         ObjectResourceMap(SessionImplSocket session) {
26                 this.session = session;
27                 backend = new TObjectIntHashMap<>(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, 0);
28         }
29
30         ObjectResourceMap(SessionImplSocket session, int capacity) {
31                 this.session = session;
32                 backend = new TObjectIntHashMap<>(capacity, Constants.DEFAULT_LOAD_FACTOR, 0);
33         }
34
35         @Override
36         public int size() {
37                 return backend.size();
38         }
39         @Override
40         public boolean isEmpty() {
41                 return backend.isEmpty();
42         }
43
44         @Override
45         public boolean containsKey(Object key) {
46                 return backend.contains(key);
47         }
48
49         @Override
50         public boolean containsValue(Object value) {
51                 ResourceImpl impl = (ResourceImpl) value;
52                 return backend.containsValue(impl.id);
53         }
54
55         @Override
56         public Resource get(Object key) {
57                 try {
58                         int result = backend.get(key);
59                         if (result == 0)
60                                 return null;
61                         return session.getResourceByKey(result);
62                 } catch (ResourceNotFoundException e) {
63                         e.printStackTrace();
64                 }
65                 return null;
66         }
67
68         @Override
69         public Resource put(T key, Resource value) {
70                 ResourceImpl impl = (ResourceImpl) value;
71                 int i = backend.put(key, impl.id);
72                 if (i == 0)
73                         return null;
74                 else
75                         try {
76                                 return session.getResourceByKey(i);
77                         } catch (ResourceNotFoundException e) {
78                                 e.printStackTrace();
79                         }
80                 return null;
81         }
82
83         @Override
84         public Resource remove(Object key) {
85                 throw new UnsupportedOperationException("remove not supported, structure is immutable");
86         }
87
88         @Override
89         public void putAll(Map<? extends T, ? extends Resource> map) {
90                 @SuppressWarnings("unchecked")
91                 ObjectResourceMap<T> other = (ObjectResourceMap<T>) map;
92                 other.backend.forEachEntry(new TObjectIntProcedure<T>() {
93
94                         @Override
95                         public boolean execute(T a, int b) {
96                                 backend.put(a, b);
97                                 return true;
98                         }
99                 });
100         }
101
102         @Override
103         public void clear() {
104                 throw new UnsupportedOperationException("clear not supported, structure is immutable");
105         }
106
107         @Override
108         public Set<T> keySet() {
109                 final Set<T> result = new HashSet<>();
110                 backend.forEach(new TObjectProcedure<T>() {
111
112                         @Override
113                         public boolean execute(T object) {
114                                 result.add(object);
115                                 return true;
116                         }
117                 });
118                 return result;
119         }
120
121         @Override
122         public Collection<Resource> values() {
123                 ArrayList<Resource> result = new ArrayList<>();
124                 for (int key : backend.values()) {
125                         try {
126                                 result.add(session.getResourceByKey(key));
127                         } catch (ResourceNotFoundException e) {
128                                 e.printStackTrace();
129                         }
130                 }
131                 return result;
132         }
133
134         @Override
135         public Set<java.util.Map.Entry<T, Resource>> entrySet() {
136                 final HashSet<java.util.Map.Entry<T, Resource>> result = new HashSet<>();
137                 backend.forEachEntry(new TObjectIntProcedure<T>() {
138
139                         @Override
140                         public boolean execute(final T a, final int b) {
141                                 return result.add(new Map.Entry<T, Resource>() {
142
143                                         @Override
144                                         public T getKey() {
145                                                 return a;
146                                         }
147
148                                         @Override
149                                         public Resource getValue() {
150                                                 return new ResourceImpl(session.resourceSupport, b);
151                                         }
152
153                                         @Override
154                                         public Resource setValue(Resource value) {
155                                                 throw new UnsupportedOperationException("Map.Entry.setValue not supported, structure is immutable");
156                                         }
157
158                                 });
159                         }
160                 });
161                 return result;
162         }
163
164         @Override
165         public int hashCode() {
166                 return backend.hashCode();
167         }
168
169         @Override
170         public boolean equals(Object obj) {
171                 if (this == obj)
172                         return true;
173                 if (obj == null)
174                         return false;
175                 if (getClass() != obj.getClass()) {
176                         if (obj instanceof Map) {
177                                 // Nonoptimal fallback for comparing against generic Map
178                                 Map<?,?> m = (Map<?,?>) obj;
179                                 if (m.size() != size())
180                                         return false;
181                                 try {
182                                         Iterator<Entry<T,Resource>> i = entrySet().iterator();
183                                         while (i.hasNext()) {
184                                                 Entry<T,Resource> e = i.next();
185                                                 T key = e.getKey();
186                                                 Resource value = e.getValue();
187                                                 if (value == null) {
188                                                         if (!(m.get(key)==null && m.containsKey(key)))
189                                                                 return false;
190                                                 } else {
191                                                         if (!value.equals(m.get(key)))
192                                                                 return false;
193                                                 }
194                                         }
195                                         return true;
196                                 } catch (ClassCastException unused) {
197                                         return false;
198                                 } catch (NullPointerException unused) {
199                                         return false;
200                                 }
201                         }
202                         return false;
203                 }
204                 ObjectResourceMap<?> other = (ObjectResourceMap<?>) obj;
205                 return session == other.session && backend.equals(other.backend);
206         }
207
208         @Override
209         public void putId(T t, int r) {
210                 backend.put(t, r);
211         }
212
213         @Override
214         public int getId(T t) {
215                 return backend.get(t);
216         }
217
218 }