aboutsummaryrefslogtreecommitdiffstats
path: root/store/src/main
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2021-10-02 20:51:58 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2021-10-02 20:51:58 +0200
commit9b8236dd7499510577c32f0d87dfd52d34f6b023 (patch)
treed9e35fa5692e3b08d0bcf1fbbd538c65ed4b58e1 /store/src/main
parentbuild: simplify Eclipse project generation (diff)
downloadrefinery-9b8236dd7499510577c32f0d87dfd52d34f6b023.tar.gz
refinery-9b8236dd7499510577c32f0d87dfd52d34f6b023.tar.zst
refinery-9b8236dd7499510577c32f0d87dfd52d34f6b023.zip
chore: fix Java 17 Sonar warnings
Had to disable code coverage measurement in the Quality Gate, we should switch it on again once we have a complete test suite.
Diffstat (limited to 'store/src/main')
-rw-r--r--store/src/main/java/org/eclipse/viatra/solver/data/map/internal/HashClash.java18
-rw-r--r--store/src/main/java/org/eclipse/viatra/solver/data/map/internal/ImmutableNode.java255
-rw-r--r--store/src/main/java/org/eclipse/viatra/solver/data/map/internal/MapDiffCursor.java125
-rw-r--r--store/src/main/java/org/eclipse/viatra/solver/data/map/internal/MutableNode.java45
-rw-r--r--store/src/main/java/org/eclipse/viatra/solver/data/model/ModelStoreImpl.java26
-rw-r--r--store/src/main/java/org/eclipse/viatra/solver/data/model/representation/TruthValue.java47
-rw-r--r--store/src/main/java/org/eclipse/viatra/solver/data/query/building/PredicateAtom.java19
-rw-r--r--store/src/main/java/org/eclipse/viatra/solver/data/query/building/RelationAtom.java16
-rw-r--r--store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalRuntimeContext.java4
9 files changed, 299 insertions, 256 deletions
diff --git a/store/src/main/java/org/eclipse/viatra/solver/data/map/internal/HashClash.java b/store/src/main/java/org/eclipse/viatra/solver/data/map/internal/HashClash.java
new file mode 100644
index 00000000..c70fb8b8
--- /dev/null
+++ b/store/src/main/java/org/eclipse/viatra/solver/data/map/internal/HashClash.java
@@ -0,0 +1,18 @@
1package org.eclipse.viatra.solver.data.map.internal;
2
3enum HashClash {
4 /**
5 * Not stuck.
6 */
7 NONE,
8
9 /**
10 * Clashed, next we should return the key of cursor 1.
11 */
12 STUCK_CURSOR_1,
13
14 /**
15 * Clashed, next we should return the key of cursor 2.
16 */
17 STUCK_CURSOR_2
18}
diff --git a/store/src/main/java/org/eclipse/viatra/solver/data/map/internal/ImmutableNode.java b/store/src/main/java/org/eclipse/viatra/solver/data/map/internal/ImmutableNode.java
index 04a9b19a..b507763f 100644
--- a/store/src/main/java/org/eclipse/viatra/solver/data/map/internal/ImmutableNode.java
+++ b/store/src/main/java/org/eclipse/viatra/solver/data/map/internal/ImmutableNode.java
@@ -15,15 +15,16 @@ public class ImmutableNode<K, V> extends Node<K, V> {
15 */ 15 */
16 final int nodeMap; 16 final int nodeMap;
17 /** 17 /**
18 * Stores Keys, Values, and subnodes. Structure: (K,V)*,NODE; NODES are stored backwards. 18 * Stores Keys, Values, and subnodes. Structure: (K,V)*,NODE; NODES are stored
19 * backwards.
19 */ 20 */
20 final Object[] content; 21 final Object[] content;
21 22
22 /** 23 /**
23 * Hash code derived from immutable hash code 24 * Hash code derived from immutable hash code
24 */ 25 */
25 final int precalculatedHash; 26 final int precalculatedHash;
26 27
27 private ImmutableNode(int dataMap, int nodeMap, Object[] content, int precalculatedHash) { 28 private ImmutableNode(int dataMap, int nodeMap, Object[] content, int precalculatedHash) {
28 super(); 29 super();
29 this.dataMap = dataMap; 30 this.dataMap = dataMap;
@@ -41,83 +42,87 @@ public class ImmutableNode<K, V> extends Node<K, V> {
41 * available. 42 * available.
42 * @return an immutable version of the input node. 43 * @return an immutable version of the input node.
43 */ 44 */
44 @SuppressWarnings("unchecked") 45 static <K, V> ImmutableNode<K, V> constructImmutable(MutableNode<K, V> node,
45 static <K,V> ImmutableNode<K,V> constructImmutable(MutableNode<K,V> node, Map<Node<K, V>, ImmutableNode<K, V>> cache) { 46 Map<Node<K, V>, ImmutableNode<K, V>> cache) {
46 // 1. try to return from cache 47 // 1. try to return from cache
47 if(cache != null) { 48 if (cache != null) {
48 ImmutableNode<K, V> cachedResult = cache.get(node); 49 ImmutableNode<K, V> cachedResult = cache.get(node);
49 if(cachedResult != null) { 50 if (cachedResult != null) {
50 // 1.1 Already cached, return from cache. 51 // 1.1 Already cached, return from cache.
51 return cachedResult; 52 return cachedResult;
52 } 53 }
53 } 54 }
54 55
55 // 2. otherwise construct a new ImmutableNode 56 // 2. otherwise construct a new ImmutableNode
56 int size = 0; 57 int size = 0;
57 for(int i = 0; i<node.content.length; i++) { 58 for (int i = 0; i < node.content.length; i++) {
58 if(node.content[i]!=null) { 59 if (node.content[i] != null) {
59 size++; 60 size++;
60 } 61 }
61 } 62 }
62 63
63 int datas = 0; 64 int datas = 0;
64 int nodes = 0; 65 int nodes = 0;
65 int resultDataMap = 0; 66 int resultDataMap = 0;
66 int resultNodeMap = 0; 67 int resultNodeMap = 0;
67 final Object[] resultContent = new Object[size]; 68 final Object[] resultContent = new Object[size];
68 int bitposition = 1; 69 int bitposition = 1;
69 for(int i = 0; i<FACTOR; i++) { 70 for (int i = 0; i < FACTOR; i++) {
70 Object key = node.content[i*2]; 71 Object key = node.content[i * 2];
71 if(key != null) { 72 if (key != null) {
72 resultDataMap |= bitposition; 73 resultDataMap |= bitposition;
73 resultContent[datas*2] = key; 74 resultContent[datas * 2] = key;
74 resultContent[datas*2+1] = node.content[i*2+1]; 75 resultContent[datas * 2 + 1] = node.content[i * 2 + 1];
75 datas++; 76 datas++;
76 } else { 77 } else {
77 Node<K,V> subnode = (Node<K, V>) node.content[i*2+1]; 78 @SuppressWarnings("unchecked")
78 if(subnode != null) { 79 var subnode = (Node<K, V>) node.content[i * 2 + 1];
80 if (subnode != null) {
79 ImmutableNode<K, V> immutableSubnode = subnode.toImmutable(cache); 81 ImmutableNode<K, V> immutableSubnode = subnode.toImmutable(cache);
80 resultNodeMap |=bitposition; 82 resultNodeMap |= bitposition;
81 resultContent[size-1-nodes] = immutableSubnode; 83 resultContent[size - 1 - nodes] = immutableSubnode;
82 nodes++; 84 nodes++;
83 } 85 }
84 } 86 }
85 bitposition<<=1; 87 bitposition <<= 1;
86 } 88 }
87 final int resultHash = node.hashCode(); 89 final int resultHash = node.hashCode();
88 ImmutableNode<K,V> newImmutable = new ImmutableNode<>(resultDataMap, resultNodeMap, resultContent, resultHash); 90 var newImmutable = new ImmutableNode<K, V>(resultDataMap, resultNodeMap, resultContent, resultHash);
89 91
90 // 3. save new immutable. 92 // 3. save new immutable.
91 if(cache != null) { 93 if (cache != null) {
92 cache.put(newImmutable, newImmutable); 94 cache.put(newImmutable, newImmutable);
93 } 95 }
94 return newImmutable; 96 return newImmutable;
95 } 97 }
96 98
97 private int index(int bitmap, int bitpos) { 99 private int index(int bitmap, int bitpos) {
98 return Integer.bitCount(bitmap & (bitpos-1)); 100 return Integer.bitCount(bitmap & (bitpos - 1));
99 } 101 }
100 102
101 @SuppressWarnings("unchecked")
102 @Override 103 @Override
103 public V getValue(K key, ContinousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth) { 104 public V getValue(K key, ContinousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth) {
104 int selectedHashFragment = hashFragment(hash,shiftDepth(depth)); 105 int selectedHashFragment = hashFragment(hash, shiftDepth(depth));
105 int bitposition = 1 << selectedHashFragment; 106 int bitposition = 1 << selectedHashFragment;
106 // If the key is stored as a data 107 // If the key is stored as a data
107 if((dataMap & bitposition) != 0) { 108 if ((dataMap & bitposition) != 0) {
108 int keyIndex = 2*index(dataMap, bitposition); 109 int keyIndex = 2 * index(dataMap, bitposition);
110 @SuppressWarnings("unchecked")
109 K keyCandidate = (K) content[keyIndex]; 111 K keyCandidate = (K) content[keyIndex];
110 if(keyCandidate.equals(key)) { 112 if (keyCandidate.equals(key)) {
111 return (V) content[keyIndex+1]; 113 @SuppressWarnings("unchecked")
114 V value = (V) content[keyIndex + 1];
115 return value;
112 } else { 116 } else {
113 return defaultValue; 117 return defaultValue;
114 } 118 }
115 } 119 }
116 // the key is stored as a node 120 // the key is stored as a node
117 else if((nodeMap & bitposition) != 0) { 121 else if ((nodeMap & bitposition) != 0) {
118 int keyIndex = content.length-1-index(nodeMap, bitposition); 122 int keyIndex = content.length - 1 - index(nodeMap, bitposition);
119 ImmutableNode<K,V> subNode = (ImmutableNode<K,V>) content[keyIndex]; 123 @SuppressWarnings("unchecked")
120 int newDepth = depth+1; 124 var subNode = (ImmutableNode<K, V>) content[keyIndex];
125 int newDepth = depth + 1;
121 int newHash = newHash(hashProvider, key, hash, newDepth); 126 int newHash = newHash(hashProvider, key, hash, newDepth);
122 return subNode.getValue(key, hashProvider, defaultValue, newHash, newDepth); 127 return subNode.getValue(key, hashProvider, defaultValue, newHash, newDepth);
123 } 128 }
@@ -126,21 +131,22 @@ public class ImmutableNode<K, V> extends Node<K, V> {
126 return defaultValue; 131 return defaultValue;
127 } 132 }
128 } 133 }
129 134
130 @SuppressWarnings("unchecked")
131 @Override 135 @Override
132 public Node<K,V> putValue(K key, V value, OldValueBox<V> oldValue, ContinousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth) { 136 public Node<K, V> putValue(K key, V value, OldValueBox<V> oldValue, ContinousHashProvider<? super K> hashProvider,
133 int selectedHashFragment = hashFragment(hash,shiftDepth(depth)); 137 V defaultValue, int hash, int depth) {
138 int selectedHashFragment = hashFragment(hash, shiftDepth(depth));
134 int bitposition = 1 << selectedHashFragment; 139 int bitposition = 1 << selectedHashFragment;
135 if((dataMap & bitposition) != 0) { 140 if ((dataMap & bitposition) != 0) {
136 int keyIndex = 2*index(dataMap, bitposition); 141 int keyIndex = 2 * index(dataMap, bitposition);
142 @SuppressWarnings("unchecked")
137 K keyCandidate = (K) content[keyIndex]; 143 K keyCandidate = (K) content[keyIndex];
138 if(keyCandidate.equals(key)) { 144 if (keyCandidate.equals(key)) {
139 if(value == defaultValue) { 145 if (value == defaultValue) {
140 // delete 146 // delete
141 MutableNode<K, V> mutable = this.toMutable(); 147 MutableNode<K, V> mutable = this.toMutable();
142 return mutable.removeEntry(selectedHashFragment,oldValue); 148 return mutable.removeEntry(selectedHashFragment, oldValue);
143 } else if(value == content[keyIndex+1]) { 149 } else if (value == content[keyIndex + 1]) {
144 // dont change 150 // dont change
145 oldValue.setOldValue(value); 151 oldValue.setOldValue(value);
146 return this; 152 return this;
@@ -150,7 +156,7 @@ public class ImmutableNode<K, V> extends Node<K, V> {
150 return mutable.updateValue(value, oldValue, selectedHashFragment); 156 return mutable.updateValue(value, oldValue, selectedHashFragment);
151 } 157 }
152 } else { 158 } else {
153 if(value == defaultValue) { 159 if (value == defaultValue) {
154 // dont change 160 // dont change
155 oldValue.setOldValue(defaultValue); 161 oldValue.setOldValue(defaultValue);
156 return this; 162 return this;
@@ -160,19 +166,19 @@ public class ImmutableNode<K, V> extends Node<K, V> {
160 return mutable.putValue(key, value, oldValue, hashProvider, defaultValue, hash, depth); 166 return mutable.putValue(key, value, oldValue, hashProvider, defaultValue, hash, depth);
161 } 167 }
162 } 168 }
163 } else if((nodeMap & bitposition)!=0) { 169 } else if ((nodeMap & bitposition) != 0) {
164 170 int keyIndex = content.length - 1 - index(nodeMap, bitposition);
165 int keyIndex = content.length-1-index(nodeMap, bitposition); 171 @SuppressWarnings("unchecked")
166 ImmutableNode<K,V> subNode = (ImmutableNode<K,V>) content[keyIndex]; 172 var subNode = (ImmutableNode<K, V>) content[keyIndex];
167 int newDepth = depth+1; 173 int newDepth = depth + 1;
168 int newHash = newHash(hashProvider, key, hash, newDepth); 174 int newHash = newHash(hashProvider, key, hash, newDepth);
169 Node<K,V> newsubNode = subNode.putValue(key, value, oldValue, hashProvider, defaultValue, newHash, newDepth); 175 var newsubNode = subNode.putValue(key, value, oldValue, hashProvider, defaultValue, newHash, newDepth);
170 176
171 if(subNode == newsubNode) { 177 if (subNode == newsubNode) {
172 // nothing changed 178 // nothing changed
173 return this; 179 return this;
174 } else { 180 } else {
175 MutableNode<K, V> mutable = toMutable(); 181 MutableNode<K, V> mutable = toMutable();
176 return mutable.updateWithSubNode(selectedHashFragment, newsubNode, value.equals(defaultValue)); 182 return mutable.updateWithSubNode(selectedHashFragment, newsubNode, value.equals(defaultValue));
177 } 183 }
178 } else { 184 } else {
@@ -181,59 +187,56 @@ public class ImmutableNode<K, V> extends Node<K, V> {
181 return mutable.putValue(key, value, oldValue, hashProvider, defaultValue, hash, depth); 187 return mutable.putValue(key, value, oldValue, hashProvider, defaultValue, hash, depth);
182 } 188 }
183 } 189 }
184 190
185
186 @SuppressWarnings("unchecked")
187 @Override 191 @Override
188 public long getSize() { 192 public long getSize() {
189 int result = Integer.bitCount(this.dataMap); 193 int result = Integer.bitCount(this.dataMap);
190 for(int subnodeIndex = 0; subnodeIndex < Integer.bitCount(this.nodeMap); subnodeIndex++) { 194 for (int subnodeIndex = 0; subnodeIndex < Integer.bitCount(this.nodeMap); subnodeIndex++) {
191 ImmutableNode<K,V> subnode = 195 @SuppressWarnings("unchecked")
192 (ImmutableNode<K, V>) this.content[this.content.length-1-subnodeIndex]; 196 var subnode = (ImmutableNode<K, V>) this.content[this.content.length - 1 - subnodeIndex];
193 result += subnode.getSize(); 197 result += subnode.getSize();
194 } 198 }
195 return result; 199 return result;
196 } 200 }
197 201
198 @Override 202 @Override
199 protected MutableNode<K,V> toMutable() { 203 protected MutableNode<K, V> toMutable() {
200 return new MutableNode<>(this); 204 return new MutableNode<>(this);
201 } 205 }
202 206
203 @Override 207 @Override
204 public ImmutableNode<K, V> toImmutable( 208 public ImmutableNode<K, V> toImmutable(Map<Node<K, V>, ImmutableNode<K, V>> cache) {
205 Map<Node<K, V>, ImmutableNode<K, V>> cache) {
206 return this; 209 return this;
207 } 210 }
208 211
209 @Override 212 @Override
210 protected MutableNode<K, V> isMutable() { 213 protected MutableNode<K, V> isMutable() {
211 return null; 214 return null;
212 } 215 }
213 216
214 @SuppressWarnings("unchecked") 217 @SuppressWarnings("unchecked")
215 @Override 218 @Override
216 boolean moveToNext(MapCursor<K, V> cursor) { 219 boolean moveToNext(MapCursor<K, V> cursor) {
217 // 1. try to move to data 220 // 1. try to move to data
218 int datas = Integer.bitCount(this.dataMap); 221 int datas = Integer.bitCount(this.dataMap);
219 if(cursor.dataIndex != MapCursor.INDEX_FINISH) { 222 if (cursor.dataIndex != MapCursor.INDEX_FINISH) {
220 int newDataIndex = cursor.dataIndex + 1; 223 int newDataIndex = cursor.dataIndex + 1;
221 if(newDataIndex < datas) { 224 if (newDataIndex < datas) {
222 cursor.dataIndex = newDataIndex; 225 cursor.dataIndex = newDataIndex;
223 cursor.key = (K) this.content[newDataIndex*2]; 226 cursor.key = (K) this.content[newDataIndex * 2];
224 cursor.value = (V) this.content[newDataIndex*2+1]; 227 cursor.value = (V) this.content[newDataIndex * 2 + 1];
225 return true; 228 return true;
226 } else { 229 } else {
227 cursor.dataIndex = MapCursor.INDEX_FINISH; 230 cursor.dataIndex = MapCursor.INDEX_FINISH;
228 } 231 }
229 } 232 }
230 233
231 // 2. look inside the subnodes 234 // 2. look inside the subnodes
232 int nodes = Integer.bitCount(this.nodeMap); 235 int nodes = Integer.bitCount(this.nodeMap);
233 int newNodeIndex = cursor.nodeIndexStack.peek() + 1; 236 int newNodeIndex = cursor.nodeIndexStack.peek() + 1;
234 if(newNodeIndex < nodes) { 237 if (newNodeIndex < nodes) {
235 // 2.1 found next subnode, move down to the subnode 238 // 2.1 found next subnode, move down to the subnode
236 Node<K, V> subnode = (Node<K, V>) this.content[this.content.length-1-newNodeIndex]; 239 Node<K, V> subnode = (Node<K, V>) this.content[this.content.length - 1 - newNodeIndex];
237 cursor.dataIndex = MapCursor.INDEX_START; 240 cursor.dataIndex = MapCursor.INDEX_START;
238 cursor.nodeIndexStack.pop(); 241 cursor.nodeIndexStack.pop();
239 cursor.nodeIndexStack.push(newNodeIndex); 242 cursor.nodeIndexStack.push(newNodeIndex);
@@ -244,7 +247,7 @@ public class ImmutableNode<K, V> extends Node<K, V> {
244 // 3. no subnode found, move up 247 // 3. no subnode found, move up
245 cursor.nodeStack.pop(); 248 cursor.nodeStack.pop();
246 cursor.nodeIndexStack.pop(); 249 cursor.nodeIndexStack.pop();
247 if(!cursor.nodeStack.isEmpty()) { 250 if (!cursor.nodeStack.isEmpty()) {
248 Node<K, V> supernode = cursor.nodeStack.peek(); 251 Node<K, V> supernode = cursor.nodeStack.peek();
249 return supernode.moveToNext(cursor); 252 return supernode.moveToNext(cursor);
250 } else { 253 } else {
@@ -254,69 +257,69 @@ public class ImmutableNode<K, V> extends Node<K, V> {
254 } 257 }
255 } 258 }
256 } 259 }
257 260
258 @Override 261 @Override
259 public void prettyPrint(StringBuilder builder, int depth, int code) { 262 public void prettyPrint(StringBuilder builder, int depth, int code) {
260 for(int i = 0; i<depth; i++) { 263 for (int i = 0; i < depth; i++) {
261 builder.append("\t"); 264 builder.append("\t");
262 } 265 }
263 if(code>=0) { 266 if (code >= 0) {
264 builder.append(code); 267 builder.append(code);
265 builder.append(":"); 268 builder.append(":");
266 } 269 }
267 builder.append("Immutable("); 270 builder.append("Immutable(");
268 boolean hadContent = false; 271 boolean hadContent = false;
269 int dataMask = 1; 272 int dataMask = 1;
270 for(int i = 0; i<FACTOR; i++) { 273 for (int i = 0; i < FACTOR; i++) {
271 if((dataMask & dataMap) != 0) { 274 if ((dataMask & dataMap) != 0) {
272 if(hadContent) { 275 if (hadContent) {
273 builder.append(","); 276 builder.append(",");
274 } 277 }
275 builder.append(i); 278 builder.append(i);
276 builder.append(":["); 279 builder.append(":[");
277 builder.append(content[2*index(dataMap, dataMask)].toString()); 280 builder.append(content[2 * index(dataMap, dataMask)].toString());
278 builder.append("]->["); 281 builder.append("]->[");
279 builder.append(content[2*index(dataMap, dataMask)+1].toString()); 282 builder.append(content[2 * index(dataMap, dataMask) + 1].toString());
280 builder.append("]"); 283 builder.append("]");
281 hadContent = true; 284 hadContent = true;
282 } 285 }
283 dataMask<<=1; 286 dataMask <<= 1;
284 } 287 }
285 builder.append(")"); 288 builder.append(")");
286 int nodeMask = 1; 289 int nodeMask = 1;
287 for(int i = 0; i<FACTOR; i++) { 290 for (int i = 0; i < FACTOR; i++) {
288 if((nodeMask & nodeMap)!=0) { 291 if ((nodeMask & nodeMap) != 0) {
289 @SuppressWarnings("unchecked") 292 @SuppressWarnings("unchecked")
290 Node<K,V> subNode = (Node<K, V>) content[content.length-1-index(nodeMap, nodeMask)]; 293 Node<K, V> subNode = (Node<K, V>) content[content.length - 1 - index(nodeMap, nodeMask)];
291 builder.append("\n"); 294 builder.append("\n");
292 subNode.prettyPrint(builder, depth+1, i); 295 subNode.prettyPrint(builder, depth + 1, i);
293 } 296 }
294 nodeMask<<=1; 297 nodeMask <<= 1;
295 } 298 }
296 } 299 }
297 300
298 @SuppressWarnings("unchecked")
299 @Override 301 @Override
300 public void checkIntegrity(ContinousHashProvider<? super K> hashProvider, V defaultValue, int depth) { 302 public void checkIntegrity(ContinousHashProvider<? super K> hashProvider, V defaultValue, int depth) {
301 if(depth>0) { 303 if (depth > 0) {
302 boolean orphaned = Integer.bitCount(dataMap) == 1 && nodeMap == 0; 304 boolean orphaned = Integer.bitCount(dataMap) == 1 && nodeMap == 0;
303 if(orphaned) { 305 if (orphaned) {
304 throw new IllegalStateException("Orphaned node! " + dataMap + ": " + content[0]); 306 throw new IllegalStateException("Orphaned node! " + dataMap + ": " + content[0]);
305 } 307 }
306 } 308 }
307 // check the place of data 309 // check the place of data
308 310
309 // check subnodes 311 // check subnodes
310 for(int i = 0; i<Integer.bitCount(nodeMap); i++) { 312 for (int i = 0; i < Integer.bitCount(nodeMap); i++) {
311 Node<K,V> subnode = (Node<K, V>) this.content[this.content.length-1-i]; 313 @SuppressWarnings("unchecked")
312 if(! (subnode instanceof ImmutableNode<?,?>)) { 314 var subnode = (Node<K, V>) this.content[this.content.length - 1 - i];
315 if (!(subnode instanceof ImmutableNode<?, ?>)) {
313 throw new IllegalStateException("Immutable node contains mutable subnodes!"); 316 throw new IllegalStateException("Immutable node contains mutable subnodes!");
314 } else { 317 } else {
315 subnode.checkIntegrity(hashProvider, defaultValue, depth+1); 318 subnode.checkIntegrity(hashProvider, defaultValue, depth + 1);
316 } 319 }
317 } 320 }
318 } 321 }
319 322
320 @Override 323 @Override
321 public int hashCode() { 324 public int hashCode() {
322 return this.precalculatedHash; 325 return this.precalculatedHash;
@@ -328,43 +331,39 @@ public class ImmutableNode<K, V> extends Node<K, V> {
328 return true; 331 return true;
329 if (obj == null) 332 if (obj == null)
330 return false; 333 return false;
331 if (obj instanceof ImmutableNode<?,?>) { 334 if (obj instanceof ImmutableNode<?, ?> other) {
332 ImmutableNode<?,?> other = (ImmutableNode<?,?>) obj; 335 return precalculatedHash == other.precalculatedHash && dataMap == other.dataMap && nodeMap == other.nodeMap
333 if (precalculatedHash != other.precalculatedHash || dataMap != other.dataMap || nodeMap != other.nodeMap || !Arrays.deepEquals(content, other.content)) 336 && Arrays.deepEquals(content, other.content);
334 return false; 337 } else if (obj instanceof MutableNode<?, ?> mutableObj) {
335 else return true; 338 return ImmutableNode.compareImmutableMutable(this, mutableObj);
336 } else if(obj instanceof MutableNode<?,?>) {
337 return ImmutableNode.compareImmutableMutable(this, (MutableNode<?, ?>) obj);
338 } else { 339 } else {
339 return false; 340 return false;
340 } 341 }
341 } 342 }
342 public static boolean compareImmutableMutable( 343
343 ImmutableNode<?, ?> immutable, 344 public static boolean compareImmutableMutable(ImmutableNode<?, ?> immutable, MutableNode<?, ?> mutable) {
344 MutableNode<?, ?> mutable)
345 {
346 int datas = 0; 345 int datas = 0;
347 int nodes = 0; 346 int nodes = 0;
348 final int immutableLength = immutable.content.length; 347 final int immutableLength = immutable.content.length;
349 for(int i = 0; i<FACTOR; i++) { 348 for (int i = 0; i < FACTOR; i++) {
350 Object key = mutable.content[i*2]; 349 Object key = mutable.content[i * 2];
351 // For each key candidate 350 // For each key candidate
352 if(key != null) { 351 if (key != null) {
353 // Check whether a new Key-Value pair can fit into the immutable container 352 // Check whether a new Key-Value pair can fit into the immutable container
354 if(datas*2+nodes+2 <= immutableLength) { 353 if (datas * 2 + nodes + 2 <= immutableLength) {
355 if( !immutable.content[datas*2].equals(key) || 354 if (!immutable.content[datas * 2].equals(key)
356 !immutable.content[datas*2+1].equals(mutable.content[i*2+1])) 355 || !immutable.content[datas * 2 + 1].equals(mutable.content[i * 2 + 1])) {
357 {
358 return false; 356 return false;
359 } 357 }
360 } else return false; 358 } else
359 return false;
361 datas++; 360 datas++;
362 } else { 361 } else {
363 Node<?,?> mutableSubnode = (Node<?, ?>) mutable.content[i*2+1]; 362 var mutableSubnode = (Node<?, ?>) mutable.content[i * 2 + 1];
364 if(mutableSubnode != null) { 363 if (mutableSubnode != null) {
365 if(datas*2+nodes+1 <= immutableLength) { 364 if (datas * 2 + nodes + 1 <= immutableLength) {
366 Object immutableSubnode = immutable.content[immutableLength-1-nodes]; 365 Object immutableSubnode = immutable.content[immutableLength - 1 - nodes];
367 if(!mutableSubnode.equals(immutableSubnode)) { 366 if (!mutableSubnode.equals(immutableSubnode)) {
368 return false; 367 return false;
369 } 368 }
370 nodes++; 369 nodes++;
diff --git a/store/src/main/java/org/eclipse/viatra/solver/data/map/internal/MapDiffCursor.java b/store/src/main/java/org/eclipse/viatra/solver/data/map/internal/MapDiffCursor.java
index e97e4aa1..35d20539 100644
--- a/store/src/main/java/org/eclipse/viatra/solver/data/map/internal/MapDiffCursor.java
+++ b/store/src/main/java/org/eclipse/viatra/solver/data/map/internal/MapDiffCursor.java
@@ -1,7 +1,6 @@
1package org.eclipse.viatra.solver.data.map.internal; 1package org.eclipse.viatra.solver.data.map.internal;
2 2
3import java.util.List; 3import java.util.List;
4import java.util.stream.Collectors;
5import java.util.stream.Stream; 4import java.util.stream.Stream;
6 5
7import org.eclipse.viatra.solver.data.map.ContinousHashProvider; 6import org.eclipse.viatra.solver.data.map.ContinousHashProvider;
@@ -11,110 +10,109 @@ import org.eclipse.viatra.solver.data.map.VersionedMap;
11 10
12/** 11/**
13 * A cursor representing the difference between two states of a map. 12 * A cursor representing the difference between two states of a map.
13 *
14 * @author Oszkar Semerath 14 * @author Oszkar Semerath
15 * 15 *
16 */ 16 */
17public class MapDiffCursor<K,V> implements DiffCursor<K, V>, Cursor<K,V>{ 17public class MapDiffCursor<K, V> implements DiffCursor<K, V>, Cursor<K, V> {
18 /** 18 /**
19 * Default value representing missing elements. 19 * Default value representing missing elements.
20 */ 20 */
21 private V defaultValue; 21 private V defaultValue;
22 private MapCursor<K,V> cursor1; 22 private MapCursor<K, V> cursor1;
23 private MapCursor<K,V> cursor2; 23 private MapCursor<K, V> cursor2;
24 private ContinousHashProvider<? super K> hashProvider; 24 private ContinousHashProvider<? super K> hashProvider;
25 25
26 // Values 26 // Values
27 private K key; 27 private K key;
28 private V fromValue; 28 private V fromValue;
29 private V toValue; 29 private V toValue;
30 30
31 // State 31 // State
32 /** 32 /**
33 * Positive number if cursor 1 is behind, negative number if cursor 2 is behind, and 0 if they are at the same position. 33 * Positive number if cursor 1 is behind, negative number if cursor 2 is behind,
34 * and 0 if they are at the same position.
34 */ 35 */
35 private int cursorRelation; 36 private int cursorRelation;
36 /** 37 private HashClash hashClash = HashClash.NONE;
37 * Denotes a state when two cursors are in the same position, but they contain different keys. 38
38 * Possible values: 39 public MapDiffCursor(ContinousHashProvider<? super K> hashProvider, V defaultValue, Cursor<K, V> cursor1,
39 * <ul> 40 Cursor<K, V> cursor2) {
40 * <li>0: not stuck</li>
41 * <li>1: hashClash, next it should return the key of cursor 1.</li>
42 * <li>2: hashClash, next it should return the key of cursor 2.</li>
43 * </ul>
44 */
45 private int hashClash=0;
46
47 public MapDiffCursor(ContinousHashProvider<? super K> hashProvider, V defaultValue, Cursor<K, V> cursor1, Cursor<K, V> cursor2) {
48 super(); 41 super();
49 this.hashProvider = hashProvider; 42 this.hashProvider = hashProvider;
50 this.defaultValue = defaultValue; 43 this.defaultValue = defaultValue;
51 this.cursor1 = (MapCursor<K, V>) cursor1; 44 this.cursor1 = (MapCursor<K, V>) cursor1;
52 this.cursor2 = (MapCursor<K, V>) cursor2; 45 this.cursor2 = (MapCursor<K, V>) cursor2;
53 } 46 }
47
54 @Override 48 @Override
55 public K getKey() { 49 public K getKey() {
56 return key; 50 return key;
57 } 51 }
52
58 @Override 53 @Override
59 public V getFromValue() { 54 public V getFromValue() {
60 return fromValue; 55 return fromValue;
61 } 56 }
57
62 @Override 58 @Override
63 public V getToValue() { 59 public V getToValue() {
64 return toValue; 60 return toValue;
65 } 61 }
62
66 @Override 63 @Override
67 public V getValue() { 64 public V getValue() {
68 return getToValue(); 65 return getToValue();
69 } 66 }
67
70 public boolean isTerminated() { 68 public boolean isTerminated() {
71 return cursor1.isTerminated() && cursor2.isTerminated(); 69 return cursor1.isTerminated() && cursor2.isTerminated();
72 } 70 }
71
73 @Override 72 @Override
74 public boolean isDirty() { 73 public boolean isDirty() {
75 return this.cursor1.isDirty() || this.cursor2.isDirty(); 74 return this.cursor1.isDirty() || this.cursor2.isDirty();
76 } 75 }
76
77 @Override 77 @Override
78 public List<VersionedMap<?, ?>> getDependingMaps() { 78 public List<VersionedMap<?, ?>> getDependingMaps() {
79 return Stream.concat( 79 return Stream.concat(cursor1.getDependingMaps().stream(), cursor2.getDependingMaps().stream()).toList();
80 cursor1.getDependingMaps().stream(),
81 cursor2.getDependingMaps().stream()
82 ).collect(Collectors.toList());
83 } 80 }
84 81
85 protected void updateState() { 82 protected void updateState() {
86 if(!isTerminated()) { 83 if (!isTerminated()) {
87 this.cursorRelation = MapCursor.compare(cursor1, cursor2); 84 this.cursorRelation = MapCursor.compare(cursor1, cursor2);
88 if(cursorRelation > 0 || cursor2.isTerminated()) { 85 if (cursorRelation > 0 || cursor2.isTerminated()) {
89 this.key = cursor1.getKey(); 86 this.key = cursor1.getKey();
90 this.fromValue = cursor1.getValue(); 87 this.fromValue = cursor1.getValue();
91 this.toValue = defaultValue; 88 this.toValue = defaultValue;
92 } else if(cursorRelation < 0 || cursor1.isTerminated()){ 89 } else if (cursorRelation < 0 || cursor1.isTerminated()) {
93 this.key = cursor2.getKey(); 90 this.key = cursor2.getKey();
94 this.fromValue = defaultValue; 91 this.fromValue = defaultValue;
95 this.toValue = cursor1.getValue(); 92 this.toValue = cursor1.getValue();
96 } else { 93 } else {
97 // cursor1 = cursor2 94 // cursor1 = cursor2
98 if(cursor1.getKey().equals(cursor2.getKey())) { 95 if (cursor1.getKey().equals(cursor2.getKey())) {
99 this.key = cursor1.getKey(); 96 this.key = cursor1.getKey();
100 this.fromValue = cursor1.getValue(); 97 this.fromValue = cursor1.getValue();
101 this.toValue = defaultValue; 98 this.toValue = defaultValue;
102 } else { 99 } else {
103 resolveHashClash1(); 100 resolveHashClashWithFirstEntry();
104 } 101 }
105 } 102 }
106 } 103 }
107 } 104 }
108 protected void resolveHashClash1() { 105
106 protected void resolveHashClashWithFirstEntry() {
109 int compareResult = this.hashProvider.compare(cursor1.key, cursor2.key); 107 int compareResult = this.hashProvider.compare(cursor1.key, cursor2.key);
110 if(compareResult<0) { 108 if (compareResult < 0) {
111 this.hashClash = 2; 109 this.hashClash = HashClash.STUCK_CURSOR_2;
112 this.cursorRelation = 0; 110 this.cursorRelation = 0;
113 this.key = cursor1.key; 111 this.key = cursor1.key;
114 this.fromValue = cursor1.value; 112 this.fromValue = cursor1.value;
115 this.toValue = defaultValue; 113 this.toValue = defaultValue;
116 } else if(compareResult>0) { 114 } else if (compareResult > 0) {
117 this.hashClash = 1; 115 this.hashClash = HashClash.STUCK_CURSOR_1;
118 this.cursorRelation = 0; 116 this.cursorRelation = 0;
119 this.key = cursor2.key; 117 this.key = cursor2.key;
120 this.fromValue = defaultValue; 118 this.fromValue = defaultValue;
@@ -123,40 +121,47 @@ public class MapDiffCursor<K,V> implements DiffCursor<K, V>, Cursor<K,V>{
123 throw new IllegalArgumentException("Inconsistent compare result for diffcursor"); 121 throw new IllegalArgumentException("Inconsistent compare result for diffcursor");
124 } 122 }
125 } 123 }
124
126 protected boolean isInHashClash() { 125 protected boolean isInHashClash() {
127 return this.hashClash != 0; 126 return this.hashClash != HashClash.NONE;
128 } 127 }
129 protected void resolveHashClash2() { 128
130 if(hashClash == 1) { 129 protected void resolveHashClashWithSecondEntry() {
131 this.hashClash = 0; 130 switch (this.hashClash) {
131 case STUCK_CURSOR_1:
132 this.hashClash = HashClash.NONE;
132 this.cursorRelation = 0; 133 this.cursorRelation = 0;
133 this.key = cursor1.key; 134 this.key = cursor1.key;
134 this.fromValue = cursor1.value; 135 this.fromValue = cursor1.value;
135 this.toValue = defaultValue; 136 this.toValue = defaultValue;
136 } else if(hashClash == 2) { 137 break;
137 this.hashClash = 0; 138 case STUCK_CURSOR_2:
139 this.hashClash = HashClash.NONE;
138 this.cursorRelation = 0; 140 this.cursorRelation = 0;
139 this.key = cursor2.key; 141 this.key = cursor2.key;
140 this.fromValue = defaultValue; 142 this.fromValue = defaultValue;
141 this.toValue = cursor2.value; 143 this.toValue = cursor2.value;
142 } else throw new IllegalArgumentException("Inconsistent compare result for diffcursor"); 144 break;
145 default:
146 throw new IllegalArgumentException("Inconsistent compare result for diffcursor");
147 }
143 } 148 }
144 149
145
146 protected boolean sameValues() { 150 protected boolean sameValues() {
147 if(this.fromValue == null) { 151 if (this.fromValue == null) {
148 return this.toValue == null; 152 return this.toValue == null;
149 } else { 153 } else {
150 return this.fromValue.equals(this.toValue); 154 return this.fromValue.equals(this.toValue);
151 } 155 }
152 } 156 }
157
153 protected boolean moveOne() { 158 protected boolean moveOne() {
154 if(isTerminated()) { 159 if (isTerminated()) {
155 return false; 160 return false;
156 } 161 }
157 if(this.cursorRelation > 0 || cursor2.isTerminated()) { 162 if (this.cursorRelation > 0 || cursor2.isTerminated()) {
158 return cursor1.move(); 163 return cursor1.move();
159 } else if(this.cursorRelation < 0 || cursor1.isTerminated()) { 164 } else if (this.cursorRelation < 0 || cursor1.isTerminated()) {
160 return cursor2.move(); 165 return cursor2.move();
161 } else { 166 } else {
162 boolean moved1 = cursor1.move(); 167 boolean moved1 = cursor1.move();
@@ -164,8 +169,9 @@ public class MapDiffCursor<K,V> implements DiffCursor<K, V>, Cursor<K,V>{
164 return moved1 && moved2; 169 return moved1 && moved2;
165 } 170 }
166 } 171 }
172
167 private boolean skipNode() { 173 private boolean skipNode() {
168 if(isTerminated()) { 174 if (isTerminated()) {
169 throw new IllegalStateException("DiffCursor tries to skip when terminated!"); 175 throw new IllegalStateException("DiffCursor tries to skip when terminated!");
170 } 176 }
171 boolean update1 = cursor1.skipCurrentNode(); 177 boolean update1 = cursor1.skipCurrentNode();
@@ -173,42 +179,43 @@ public class MapDiffCursor<K,V> implements DiffCursor<K, V>, Cursor<K,V>{
173 updateState(); 179 updateState();
174 return update1 && update2; 180 return update1 && update2;
175 } 181 }
176 182
177 protected boolean moveToConsistentState() { 183 protected boolean moveToConsistentState() {
178 if(!isTerminated()) { 184 if (!isTerminated()) {
179 boolean changed; 185 boolean changed;
180 boolean lastResult = true; 186 boolean lastResult = true;
181 do { 187 do {
182 changed = false; 188 changed = false;
183 if(MapCursor.sameSubnode(cursor1, cursor2)) { 189 if (MapCursor.sameSubnode(cursor1, cursor2)) {
184 lastResult = skipNode(); 190 lastResult = skipNode();
185 changed = true; 191 changed = true;
186 } 192 }
187 if(sameValues()) { 193 if (sameValues()) {
188 lastResult = moveOne(); 194 lastResult = moveOne();
189 changed = true; 195 changed = true;
190 } 196 }
191 updateState(); 197 updateState();
192 } while(changed && !isTerminated()); 198 } while (changed && !isTerminated());
193 return lastResult; 199 return lastResult;
194 } else { 200 } else {
195 return false; 201 return false;
196 } 202 }
197 } 203 }
198 204
199 public boolean move() { 205 public boolean move() {
200 if(!isTerminated()) { 206 if (!isTerminated()) {
201 if(isInHashClash()) { 207 if (isInHashClash()) {
202 this.resolveHashClash2(); 208 this.resolveHashClashWithSecondEntry();
203 return true; 209 return true;
204 } else { 210 } else {
205 if(moveOne()) { 211 if (moveOne()) {
206 return moveToConsistentState(); 212 return moveToConsistentState();
207 } else { 213 } else {
208 return false; 214 return false;
209 } 215 }
210 } 216 }
211 217
212 } else return false; 218 } else
219 return false;
213 } 220 }
214} 221}
diff --git a/store/src/main/java/org/eclipse/viatra/solver/data/map/internal/MutableNode.java b/store/src/main/java/org/eclipse/viatra/solver/data/map/internal/MutableNode.java
index 9e63b941..b5fee673 100644
--- a/store/src/main/java/org/eclipse/viatra/solver/data/map/internal/MutableNode.java
+++ b/store/src/main/java/org/eclipse/viatra/solver/data/map/internal/MutableNode.java
@@ -52,19 +52,22 @@ public class MutableNode<K, V> extends Node<K, V> {
52 this.cachedHash = node.hashCode(); 52 this.cachedHash = node.hashCode();
53 } 53 }
54 54
55 @SuppressWarnings("unchecked")
56 @Override 55 @Override
57 public V getValue(K key, ContinousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth) { 56 public V getValue(K key, ContinousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth) {
58 int selectedHashFragment = hashFragment(hash, shiftDepth(depth)); 57 int selectedHashFragment = hashFragment(hash, shiftDepth(depth));
58 @SuppressWarnings("unchecked")
59 K keyCandidate = (K) this.content[2 * selectedHashFragment]; 59 K keyCandidate = (K) this.content[2 * selectedHashFragment];
60 if (keyCandidate != null) { 60 if (keyCandidate != null) {
61 if (keyCandidate.equals(key)) { 61 if (keyCandidate.equals(key)) {
62 return (V) this.content[2 * selectedHashFragment + 1]; 62 @SuppressWarnings("unchecked")
63 V value = (V) this.content[2 * selectedHashFragment + 1];
64 return value;
63 } else { 65 } else {
64 return defaultValue; 66 return defaultValue;
65 } 67 }
66 } else { 68 } else {
67 Node<K, V> nodeCandidate = (Node<K, V>) content[2 * selectedHashFragment + 1]; 69 @SuppressWarnings("unchecked")
70 var nodeCandidate = (Node<K, V>) content[2 * selectedHashFragment + 1];
68 if (nodeCandidate != null) { 71 if (nodeCandidate != null) {
69 int newDepth = depth + 1; 72 int newDepth = depth + 1;
70 int newHash = newHash(hashProvider, key, hash, newDepth); 73 int newHash = newHash(hashProvider, key, hash, newDepth);
@@ -75,11 +78,11 @@ public class MutableNode<K, V> extends Node<K, V> {
75 } 78 }
76 } 79 }
77 80
78 @SuppressWarnings("unchecked")
79 @Override 81 @Override
80 public Node<K, V> putValue(K key, V value, OldValueBox<V> oldValue, ContinousHashProvider<? super K> hashProvider, V defaultValue, int hash, 82 public Node<K, V> putValue(K key, V value, OldValueBox<V> oldValue, ContinousHashProvider<? super K> hashProvider,
81 int depth) { 83 V defaultValue, int hash, int depth) {
82 int selectedHashFragment = hashFragment(hash, shiftDepth(depth)); 84 int selectedHashFragment = hashFragment(hash, shiftDepth(depth));
85 @SuppressWarnings("unchecked")
83 K keyCandidate = (K) content[2 * selectedHashFragment]; 86 K keyCandidate = (K) content[2 * selectedHashFragment];
84 if (keyCandidate != null) { 87 if (keyCandidate != null) {
85 // If has key 88 // If has key
@@ -105,10 +108,11 @@ public class MutableNode<K, V> extends Node<K, V> {
105 } 108 }
106 } else { 109 } else {
107 // If it does not have key, check for value 110 // If it does not have key, check for value
108 Node<K, V> nodeCandidate = (Node<K, V>) content[2 * selectedHashFragment + 1]; 111 @SuppressWarnings("unchecked")
112 var nodeCandidate = (Node<K, V>) content[2 * selectedHashFragment + 1];
109 if (nodeCandidate != null) { 113 if (nodeCandidate != null) {
110 // If it has value, it is a subnode -> upate that 114 // If it has value, it is a subnode -> upate that
111 Node<K, V> newNode = nodeCandidate.putValue(key, value, oldValue, hashProvider, defaultValue, 115 var newNode = nodeCandidate.putValue(key, value, oldValue, hashProvider, defaultValue,
112 newHash(hashProvider, key, hash, depth + 1), depth + 1); 116 newHash(hashProvider, key, hash, depth + 1), depth + 1);
113 return updateWithSubNode(selectedHashFragment, newNode, value.equals(defaultValue)); 117 return updateWithSubNode(selectedHashFragment, newNode, value.equals(defaultValue));
114 } else { 118 } else {
@@ -125,10 +129,11 @@ public class MutableNode<K, V> extends Node<K, V> {
125 } 129 }
126 } 130 }
127 131
128 @SuppressWarnings("unchecked") 132 private Node<K, V> addEntry(K key, V value, OldValueBox<V> oldValueBox, int selectedHashFragment) {
129 private Node<K, V> addEntry(K key, V value, OldValueBox<V> oldValue, int selectedHashFragment) {
130 content[2 * selectedHashFragment] = key; 133 content[2 * selectedHashFragment] = key;
131 oldValue.setOldValue((V) content[2 * selectedHashFragment + 1]); 134 @SuppressWarnings("unchecked")
135 V oldValue = (V) content[2 * selectedHashFragment + 1];
136 oldValueBox.setOldValue(oldValue);
132 content[2 * selectedHashFragment + 1] = value; 137 content[2 * selectedHashFragment + 1] = value;
133 updateHash(); 138 updateHash();
134 return this; 139 return this;
@@ -231,6 +236,8 @@ public class MutableNode<K, V> extends Node<K, V> {
231 return this; 236 return this;
232 } 237 }
233 238
239 // Pass everything as parameters for performance.
240 @SuppressWarnings("squid:S107")
234 private MutableNode<K, V> newNodeWithTwoEntries(ContinousHashProvider<? super K> hashProvider, K key1, V value1, 241 private MutableNode<K, V> newNodeWithTwoEntries(ContinousHashProvider<? super K> hashProvider, K key1, V value1,
235 int oldHash1, K key2, V value2, int oldHash2, int newdepth) { 242 int oldHash1, K key2, V value2, int oldHash2, int newdepth) {
236 int newHash1 = newHash(hashProvider, key1, oldHash1, newdepth); 243 int newHash1 = newHash(hashProvider, key1, oldHash1, newdepth);
@@ -377,7 +384,6 @@ public class MutableNode<K, V> extends Node<K, V> {
377 } 384 }
378 } 385 }
379 386
380 @SuppressWarnings({ "unchecked" })
381 @Override 387 @Override
382 public void checkIntegrity(ContinousHashProvider<? super K> hashProvider, V defaultValue, int depth) { 388 public void checkIntegrity(ContinousHashProvider<? super K> hashProvider, V defaultValue, int depth) {
383 // check for orphan nodes 389 // check for orphan nodes
@@ -390,7 +396,9 @@ public class MutableNode<K, V> extends Node<K, V> {
390 // check the place of data 396 // check the place of data
391 for (int i = 0; i < FACTOR; i++) { 397 for (int i = 0; i < FACTOR; i++) {
392 if (this.content[2 * i] != null) { 398 if (this.content[2 * i] != null) {
399 @SuppressWarnings("unchecked")
393 K key = (K) this.content[2 * i]; 400 K key = (K) this.content[2 * i];
401 @SuppressWarnings("unchecked")
394 V value = (V) this.content[2 * i + 1]; 402 V value = (V) this.content[2 * i + 1];
395 403
396 if (value == defaultValue) { 404 if (value == defaultValue) {
@@ -408,7 +416,8 @@ public class MutableNode<K, V> extends Node<K, V> {
408 // check subnodes 416 // check subnodes
409 for (int i = 0; i < FACTOR; i++) { 417 for (int i = 0; i < FACTOR; i++) {
410 if (this.content[2 * i + 1] != null && this.content[2 * i] == null) { 418 if (this.content[2 * i + 1] != null && this.content[2 * i] == null) {
411 Node<K, V> subNode = (Node<K, V>) this.content[2 * i + 1]; 419 @SuppressWarnings("unchecked")
420 var subNode = (Node<K, V>) this.content[2 * i + 1];
412 subNode.checkIntegrity(hashProvider, defaultValue, depth + 1); 421 subNode.checkIntegrity(hashProvider, defaultValue, depth + 1);
413 } 422 }
414 } 423 }
@@ -436,12 +445,10 @@ public class MutableNode<K, V> extends Node<K, V> {
436 return true; 445 return true;
437 if (obj == null) 446 if (obj == null)
438 return false; 447 return false;
439 if (obj instanceof MutableNode<?, ?>) { 448 if (obj instanceof MutableNode<?, ?> mutableObj) {
440 MutableNode<?, ?> other = (MutableNode<?, ?>) obj; 449 return Arrays.deepEquals(this.content, mutableObj.content);
441 return Arrays.deepEquals(this.content, other.content); 450 } else if (obj instanceof ImmutableNode<?, ?> immutableObj) {
442 } else if (obj instanceof ImmutableNode<?, ?>) { 451 return ImmutableNode.compareImmutableMutable(immutableObj, this);
443 ImmutableNode<?, ?> other = (ImmutableNode<?, ?>) obj;
444 return ImmutableNode.compareImmutableMutable(other, this);
445 } else { 452 } else {
446 return false; 453 return false;
447 } 454 }
diff --git a/store/src/main/java/org/eclipse/viatra/solver/data/model/ModelStoreImpl.java b/store/src/main/java/org/eclipse/viatra/solver/data/model/ModelStoreImpl.java
index f5e3b141..a97fb27a 100644
--- a/store/src/main/java/org/eclipse/viatra/solver/data/model/ModelStoreImpl.java
+++ b/store/src/main/java/org/eclipse/viatra/solver/data/model/ModelStoreImpl.java
@@ -1,7 +1,6 @@
1package org.eclipse.viatra.solver.data.model; 1package org.eclipse.viatra.solver.data.model;
2 2
3import java.util.HashMap; 3import java.util.HashMap;
4import java.util.HashSet;
5import java.util.LinkedList; 4import java.util.LinkedList;
6import java.util.List; 5import java.util.List;
7import java.util.Map; 6import java.util.Map;
@@ -34,8 +33,7 @@ public class ModelStoreImpl implements ModelStore {
34 Map<SimilarRelationEquivalenceClass, List<Relation<?>>> symbolRepresentationsPerHashPerArity = new HashMap<>(); 33 Map<SimilarRelationEquivalenceClass, List<Relation<?>>> symbolRepresentationsPerHashPerArity = new HashMap<>();
35 34
36 for (DataRepresentation<?, ?> dataRepresentation : dataRepresentations) { 35 for (DataRepresentation<?, ?> dataRepresentation : dataRepresentations) {
37 if (dataRepresentation instanceof Relation<?>) { 36 if (dataRepresentation instanceof Relation<?> symbolRepresentation) {
38 Relation<?> symbolRepresentation = (Relation<?>) dataRepresentation;
39 addOrCreate(symbolRepresentationsPerHashPerArity, 37 addOrCreate(symbolRepresentationsPerHashPerArity,
40 new SimilarRelationEquivalenceClass(symbolRepresentation), symbolRepresentation); 38 new SimilarRelationEquivalenceClass(symbolRepresentation), symbolRepresentation);
41 } else if (dataRepresentation instanceof AuxilaryData<?, ?>) { 39 } else if (dataRepresentation instanceof AuxilaryData<?, ?>) {
@@ -58,10 +56,10 @@ public class ModelStoreImpl implements ModelStore {
58 List<Relation<?>> symbolGroup) { 56 List<Relation<?>> symbolGroup) {
59 final ContinousHashProvider<Tuple> hashProvider = symbolGroup.get(0).getHashProvider(); 57 final ContinousHashProvider<Tuple> hashProvider = symbolGroup.get(0).getHashProvider();
60 final Object defaultValue = symbolGroup.get(0).getDefaultValue(); 58 final Object defaultValue = symbolGroup.get(0).getDefaultValue();
61 59
62 List<VersionedMapStore<Tuple, Object>> maps = VersionedMapStoreImpl 60 List<VersionedMapStore<Tuple, Object>> maps = VersionedMapStoreImpl
63 .createSharedVersionedMapStores(symbolGroup.size(), hashProvider, defaultValue); 61 .createSharedVersionedMapStores(symbolGroup.size(), hashProvider, defaultValue);
64 62
65 for (int i = 0; i < symbolGroup.size(); i++) { 63 for (int i = 0; i < symbolGroup.size(); i++) {
66 result.put(symbolGroup.get(i), maps.get(i)); 64 result.put(symbolGroup.get(i), maps.get(i));
67 } 65 }
@@ -100,24 +98,20 @@ public class ModelStoreImpl implements ModelStore {
100 } 98 }
101 return new ModelImpl(this, maps); 99 return new ModelImpl(this, maps);
102 } 100 }
103 101
104 @Override 102 @Override
105 @SuppressWarnings("squid:S1751")
106 public synchronized Set<Long> getStates() { 103 public synchronized Set<Long> getStates() {
107 // if not empty, return first 104 var iterator = stores.values().iterator();
108 for(VersionedMapStore<?, ?> store : stores.values()) { 105 if (iterator.hasNext()) {
109 return new HashSet<>(store.getStates()); 106 return Set.copyOf(iterator.next().getStates());
110 } 107 }
111 // if empty 108 return Set.of(0l);
112 Set<Long> result = new HashSet<>();
113 result.add(0l);
114 return result;
115 } 109 }
116 110
117 @Override 111 @Override
118 public synchronized ModelDiffCursor getDiffCursor(long from, long to) { 112 public synchronized ModelDiffCursor getDiffCursor(long from, long to) {
119 Map<DataRepresentation<?, ?>,DiffCursor<?,?>> diffcursors = new HashMap<>(); 113 Map<DataRepresentation<?, ?>, DiffCursor<?, ?>> diffcursors = new HashMap<>();
120 for(Entry<DataRepresentation<?, ?>, VersionedMapStore<?, ?>> entry : stores.entrySet()) { 114 for (Entry<DataRepresentation<?, ?>, VersionedMapStore<?, ?>> entry : stores.entrySet()) {
121 DataRepresentation<?, ?> representation = entry.getKey(); 115 DataRepresentation<?, ?> representation = entry.getKey();
122 DiffCursor<?, ?> diffCursor = entry.getValue().getDiffCursor(from, to); 116 DiffCursor<?, ?> diffCursor = entry.getValue().getDiffCursor(from, to);
123 diffcursors.put(representation, diffCursor); 117 diffcursors.put(representation, diffCursor);
diff --git a/store/src/main/java/org/eclipse/viatra/solver/data/model/representation/TruthValue.java b/store/src/main/java/org/eclipse/viatra/solver/data/model/representation/TruthValue.java
index aeccde9e..049c7eac 100644
--- a/store/src/main/java/org/eclipse/viatra/solver/data/model/representation/TruthValue.java
+++ b/store/src/main/java/org/eclipse/viatra/solver/data/model/representation/TruthValue.java
@@ -1,42 +1,49 @@
1package org.eclipse.viatra.solver.data.model.representation; 1package org.eclipse.viatra.solver.data.model.representation;
2 2
3public class TruthValue { 3public enum TruthValue {
4 public static final TruthValue True = new TruthValue("true"); 4 TRUE("true"),
5 public static final TruthValue False = new TruthValue("false"); 5
6 public static final TruthValue Unknown = new TruthValue("unknown"); 6 FALSE("false"),
7 public static final TruthValue Error = new TruthValue("error"); 7
8 8 UNKNOWN("unknown"),
9
10 ERROR("error");
11
9 private final String name; 12 private final String name;
10 protected TruthValue(String name) { 13
14 private TruthValue(String name) {
11 this.name = name; 15 this.name = name;
12 } 16 }
13 17
14 public String getName() { 18 public String getName() {
15 return name; 19 return name;
16 } 20 }
17 21
18 public static TruthValue toTruthValue(boolean value) { 22 public static TruthValue toTruthValue(boolean value) {
19 if(value) return True; 23 return value ? TRUE : FALSE;
20 else return False;
21 } 24 }
25
22 public boolean isConsistent() { 26 public boolean isConsistent() {
23 return this != Error; 27 return this != ERROR;
24 } 28 }
29
25 public boolean isComplete() { 30 public boolean isComplete() {
26 return this != Unknown; 31 return this != UNKNOWN;
27 } 32 }
33
28 public boolean must() { 34 public boolean must() {
29 return this == True || this == Error; 35 return this == TRUE || this == ERROR;
30 } 36 }
37
31 public boolean may() { 38 public boolean may() {
32 return this == True || this == Unknown; 39 return this == TRUE || this == UNKNOWN;
33 } 40 }
34 41
35 public TruthValue not() { 42 public TruthValue not() {
36 if(this == True) { 43 if (this == TRUE) {
37 return False; 44 return FALSE;
38 } else if(this == False) { 45 } else if (this == FALSE) {
39 return True; 46 return TRUE;
40 } else { 47 } else {
41 return this; 48 return this;
42 } 49 }
diff --git a/store/src/main/java/org/eclipse/viatra/solver/data/query/building/PredicateAtom.java b/store/src/main/java/org/eclipse/viatra/solver/data/query/building/PredicateAtom.java
index 3e5ef88e..439298d0 100644
--- a/store/src/main/java/org/eclipse/viatra/solver/data/query/building/PredicateAtom.java
+++ b/store/src/main/java/org/eclipse/viatra/solver/data/query/building/PredicateAtom.java
@@ -4,52 +4,61 @@ import java.util.List;
4import java.util.Map; 4import java.util.Map;
5import java.util.Set; 5import java.util.Set;
6 6
7public class PredicateAtom implements DNFAtom{ 7public class PredicateAtom implements DNFAtom {
8 private DNFPredicate referred; 8 private DNFPredicate referred;
9 private List<Variable> substitution; 9 private List<Variable> substitution;
10 private boolean positive; 10 private boolean positive;
11 private boolean transitive; 11 private boolean transitive;
12 12
13 public PredicateAtom(boolean positive, boolean transitive, DNFPredicate referred, List<Variable> substitution) { 13 public PredicateAtom(boolean positive, boolean transitive, DNFPredicate referred, List<Variable> substitution) {
14 this.positive = positive; 14 this.positive = positive;
15 this.referred = referred; 15 this.referred = referred;
16 this.substitution = substitution; 16 this.substitution = substitution;
17 this.transitive = transitive; 17 this.transitive = transitive;
18 } 18 }
19
19 public DNFPredicate getReferred() { 20 public DNFPredicate getReferred() {
20 return referred; 21 return referred;
21 } 22 }
23
22 public void setReferred(DNFPredicate referred) { 24 public void setReferred(DNFPredicate referred) {
23 this.referred = referred; 25 this.referred = referred;
24 } 26 }
27
25 public List<Variable> getSubstitution() { 28 public List<Variable> getSubstitution() {
26 return substitution; 29 return substitution;
27 } 30 }
31
28 public void setSubstitution(List<Variable> substitution) { 32 public void setSubstitution(List<Variable> substitution) {
29 this.substitution = substitution; 33 this.substitution = substitution;
30 } 34 }
35
31 public boolean isPositive() { 36 public boolean isPositive() {
32 return positive; 37 return positive;
33 } 38 }
39
34 public void setPositive(boolean positive) { 40 public void setPositive(boolean positive) {
35 this.positive = positive; 41 this.positive = positive;
36 } 42 }
43
37 public boolean isTransitive() { 44 public boolean isTransitive() {
38 return transitive; 45 return transitive;
39 } 46 }
47
40 public void setTransitive(boolean transitive) { 48 public void setTransitive(boolean transitive) {
41 this.transitive = transitive; 49 this.transitive = transitive;
42 } 50 }
51
43 @Override 52 @Override
44 public void unifyVariables(Map<String, Variable> variables) { 53 public void unifyVariables(Map<String, Variable> variables) {
45 for(int i = 0; i<this.substitution.size(); i++) { 54 for (int i = 0; i < this.substitution.size(); i++) {
46 final Object term = this.substitution.get(i); 55 final Object term = this.substitution.get(i);
47 if(term instanceof Variable) { 56 if (term instanceof Variable variableReference) {
48 Variable variableReference = (Variable) term;
49 this.substitution.set(i, DNFAtom.unifyVariables(variables, variableReference)); 57 this.substitution.set(i, DNFAtom.unifyVariables(variables, variableReference));
50 } 58 }
51 } 59 }
52 } 60 }
61
53 @Override 62 @Override
54 public void collectAllVariables(Set<Variable> variables) { 63 public void collectAllVariables(Set<Variable> variables) {
55 DNFAtom.addToCollection(variables, substitution); 64 DNFAtom.addToCollection(variables, substitution);
diff --git a/store/src/main/java/org/eclipse/viatra/solver/data/query/building/RelationAtom.java b/store/src/main/java/org/eclipse/viatra/solver/data/query/building/RelationAtom.java
index f7152bba..adf2f8c7 100644
--- a/store/src/main/java/org/eclipse/viatra/solver/data/query/building/RelationAtom.java
+++ b/store/src/main/java/org/eclipse/viatra/solver/data/query/building/RelationAtom.java
@@ -7,37 +7,41 @@ import java.util.Set;
7import org.eclipse.viatra.solver.data.query.view.FilteredRelationView; 7import org.eclipse.viatra.solver.data.query.view.FilteredRelationView;
8import org.eclipse.viatra.solver.data.query.view.RelationView; 8import org.eclipse.viatra.solver.data.query.view.RelationView;
9 9
10public class RelationAtom implements DNFAtom{ 10public class RelationAtom implements DNFAtom {
11 RelationView<?> view; 11 RelationView<?> view;
12 List<Variable> substitution; 12 List<Variable> substitution;
13 13
14 public RelationAtom(RelationView<?> view, List<Variable> substitution) { 14 public RelationAtom(RelationView<?> view, List<Variable> substitution) {
15 this.view = view; 15 this.view = view;
16 this.substitution = substitution; 16 this.substitution = substitution;
17 } 17 }
18
18 public RelationView<?> getView() { 19 public RelationView<?> getView() {
19 return view; 20 return view;
20 } 21 }
22
21 public void setView(FilteredRelationView<?> view) { 23 public void setView(FilteredRelationView<?> view) {
22 this.view = view; 24 this.view = view;
23 } 25 }
26
24 public List<Variable> getSubstitution() { 27 public List<Variable> getSubstitution() {
25 return substitution; 28 return substitution;
26 } 29 }
30
27 public void setSubstitution(List<Variable> substitution) { 31 public void setSubstitution(List<Variable> substitution) {
28 this.substitution = substitution; 32 this.substitution = substitution;
29 } 33 }
30 34
31 @Override 35 @Override
32 public void unifyVariables(Map<String, Variable> variables) { 36 public void unifyVariables(Map<String, Variable> variables) {
33 for(int i = 0; i<this.substitution.size(); i++) { 37 for (int i = 0; i < this.substitution.size(); i++) {
34 final Object term = this.substitution.get(i); 38 final Object term = this.substitution.get(i);
35 if(term instanceof Variable) { 39 if (term instanceof Variable variableReference) {
36 Variable variableReference = (Variable) term;
37 this.substitution.set(i, DNFAtom.unifyVariables(variables, variableReference)); 40 this.substitution.set(i, DNFAtom.unifyVariables(variables, variableReference));
38 } 41 }
39 } 42 }
40 } 43 }
44
41 @Override 45 @Override
42 public void collectAllVariables(Set<Variable> variables) { 46 public void collectAllVariables(Set<Variable> variables) {
43 DNFAtom.addToCollection(variables, substitution); 47 DNFAtom.addToCollection(variables, substitution);
diff --git a/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalRuntimeContext.java b/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalRuntimeContext.java
index 7d1682b2..fa6a59ab 100644
--- a/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalRuntimeContext.java
+++ b/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalRuntimeContext.java
@@ -37,7 +37,6 @@ public class RelationalRuntimeContext implements IQueryRuntimeContext {
37 return metaContext; 37 return metaContext;
38 } 38 }
39 39
40 //
41 /** 40 /**
42 * TODO: check {@link NavigationHelperImpl#coalesceTraversals(Callable)} 41 * TODO: check {@link NavigationHelperImpl#coalesceTraversals(Callable)}
43 */ 42 */
@@ -57,8 +56,7 @@ public class RelationalRuntimeContext implements IQueryRuntimeContext {
57 56
58 @Override 57 @Override
59 public boolean isIndexed(IInputKey key, IndexingService service) { 58 public boolean isIndexed(IInputKey key, IndexingService service) {
60 if(key instanceof RelationView<?>) { 59 if(key instanceof RelationView<?> relationalKey) {
61 RelationView<?> relationalKey = (RelationView<?>) key;
62 return this.relationUpdateListener.containsRelationalView(relationalKey); 60 return this.relationUpdateListener.containsRelationalView(relationalKey);
63 } else { 61 } else {
64 return false; 62 return false;