aboutsummaryrefslogtreecommitdiffstats
path: root/store/src/main/java/org/eclipse/viatra/solver/data/map/internal/MapDiffCursor.java
diff options
context:
space:
mode:
Diffstat (limited to 'store/src/main/java/org/eclipse/viatra/solver/data/map/internal/MapDiffCursor.java')
-rw-r--r--store/src/main/java/org/eclipse/viatra/solver/data/map/internal/MapDiffCursor.java221
1 files changed, 0 insertions, 221 deletions
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
deleted file mode 100644
index 35d20539..00000000
--- a/store/src/main/java/org/eclipse/viatra/solver/data/map/internal/MapDiffCursor.java
+++ /dev/null
@@ -1,221 +0,0 @@
1package org.eclipse.viatra.solver.data.map.internal;
2
3import java.util.List;
4import java.util.stream.Stream;
5
6import org.eclipse.viatra.solver.data.map.ContinousHashProvider;
7import org.eclipse.viatra.solver.data.map.Cursor;
8import org.eclipse.viatra.solver.data.map.DiffCursor;
9import org.eclipse.viatra.solver.data.map.VersionedMap;
10
11/**
12 * A cursor representing the difference between two states of a map.
13 *
14 * @author Oszkar Semerath
15 *
16 */
17public class MapDiffCursor<K, V> implements DiffCursor<K, V>, Cursor<K, V> {
18 /**
19 * Default value representing missing elements.
20 */
21 private V defaultValue;
22 private MapCursor<K, V> cursor1;
23 private MapCursor<K, V> cursor2;
24 private ContinousHashProvider<? super K> hashProvider;
25
26 // Values
27 private K key;
28 private V fromValue;
29 private V toValue;
30
31 // State
32 /**
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.
35 */
36 private int cursorRelation;
37 private HashClash hashClash = HashClash.NONE;
38
39 public MapDiffCursor(ContinousHashProvider<? super K> hashProvider, V defaultValue, Cursor<K, V> cursor1,
40 Cursor<K, V> cursor2) {
41 super();
42 this.hashProvider = hashProvider;
43 this.defaultValue = defaultValue;
44 this.cursor1 = (MapCursor<K, V>) cursor1;
45 this.cursor2 = (MapCursor<K, V>) cursor2;
46 }
47
48 @Override
49 public K getKey() {
50 return key;
51 }
52
53 @Override
54 public V getFromValue() {
55 return fromValue;
56 }
57
58 @Override
59 public V getToValue() {
60 return toValue;
61 }
62
63 @Override
64 public V getValue() {
65 return getToValue();
66 }
67
68 public boolean isTerminated() {
69 return cursor1.isTerminated() && cursor2.isTerminated();
70 }
71
72 @Override
73 public boolean isDirty() {
74 return this.cursor1.isDirty() || this.cursor2.isDirty();
75 }
76
77 @Override
78 public List<VersionedMap<?, ?>> getDependingMaps() {
79 return Stream.concat(cursor1.getDependingMaps().stream(), cursor2.getDependingMaps().stream()).toList();
80 }
81
82 protected void updateState() {
83 if (!isTerminated()) {
84 this.cursorRelation = MapCursor.compare(cursor1, cursor2);
85 if (cursorRelation > 0 || cursor2.isTerminated()) {
86 this.key = cursor1.getKey();
87 this.fromValue = cursor1.getValue();
88 this.toValue = defaultValue;
89 } else if (cursorRelation < 0 || cursor1.isTerminated()) {
90 this.key = cursor2.getKey();
91 this.fromValue = defaultValue;
92 this.toValue = cursor1.getValue();
93 } else {
94 // cursor1 = cursor2
95 if (cursor1.getKey().equals(cursor2.getKey())) {
96 this.key = cursor1.getKey();
97 this.fromValue = cursor1.getValue();
98 this.toValue = defaultValue;
99 } else {
100 resolveHashClashWithFirstEntry();
101 }
102 }
103 }
104 }
105
106 protected void resolveHashClashWithFirstEntry() {
107 int compareResult = this.hashProvider.compare(cursor1.key, cursor2.key);
108 if (compareResult < 0) {
109 this.hashClash = HashClash.STUCK_CURSOR_2;
110 this.cursorRelation = 0;
111 this.key = cursor1.key;
112 this.fromValue = cursor1.value;
113 this.toValue = defaultValue;
114 } else if (compareResult > 0) {
115 this.hashClash = HashClash.STUCK_CURSOR_1;
116 this.cursorRelation = 0;
117 this.key = cursor2.key;
118 this.fromValue = defaultValue;
119 this.toValue = cursor2.value;
120 } else {
121 throw new IllegalArgumentException("Inconsistent compare result for diffcursor");
122 }
123 }
124
125 protected boolean isInHashClash() {
126 return this.hashClash != HashClash.NONE;
127 }
128
129 protected void resolveHashClashWithSecondEntry() {
130 switch (this.hashClash) {
131 case STUCK_CURSOR_1:
132 this.hashClash = HashClash.NONE;
133 this.cursorRelation = 0;
134 this.key = cursor1.key;
135 this.fromValue = cursor1.value;
136 this.toValue = defaultValue;
137 break;
138 case STUCK_CURSOR_2:
139 this.hashClash = HashClash.NONE;
140 this.cursorRelation = 0;
141 this.key = cursor2.key;
142 this.fromValue = defaultValue;
143 this.toValue = cursor2.value;
144 break;
145 default:
146 throw new IllegalArgumentException("Inconsistent compare result for diffcursor");
147 }
148 }
149
150 protected boolean sameValues() {
151 if (this.fromValue == null) {
152 return this.toValue == null;
153 } else {
154 return this.fromValue.equals(this.toValue);
155 }
156 }
157
158 protected boolean moveOne() {
159 if (isTerminated()) {
160 return false;
161 }
162 if (this.cursorRelation > 0 || cursor2.isTerminated()) {
163 return cursor1.move();
164 } else if (this.cursorRelation < 0 || cursor1.isTerminated()) {
165 return cursor2.move();
166 } else {
167 boolean moved1 = cursor1.move();
168 boolean moved2 = cursor2.move();
169 return moved1 && moved2;
170 }
171 }
172
173 private boolean skipNode() {
174 if (isTerminated()) {
175 throw new IllegalStateException("DiffCursor tries to skip when terminated!");
176 }
177 boolean update1 = cursor1.skipCurrentNode();
178 boolean update2 = cursor2.skipCurrentNode();
179 updateState();
180 return update1 && update2;
181 }
182
183 protected boolean moveToConsistentState() {
184 if (!isTerminated()) {
185 boolean changed;
186 boolean lastResult = true;
187 do {
188 changed = false;
189 if (MapCursor.sameSubnode(cursor1, cursor2)) {
190 lastResult = skipNode();
191 changed = true;
192 }
193 if (sameValues()) {
194 lastResult = moveOne();
195 changed = true;
196 }
197 updateState();
198 } while (changed && !isTerminated());
199 return lastResult;
200 } else {
201 return false;
202 }
203 }
204
205 public boolean move() {
206 if (!isTerminated()) {
207 if (isInHashClash()) {
208 this.resolveHashClashWithSecondEntry();
209 return true;
210 } else {
211 if (moveOne()) {
212 return moveToConsistentState();
213 } else {
214 return false;
215 }
216 }
217
218 } else
219 return false;
220 }
221}