diff options
author | 2021-07-29 19:01:25 +0200 | |
---|---|---|
committer | 2021-07-29 19:01:25 +0200 | |
commit | 7f6a2528bf83f93e3d35eff228f7180e0181f4eb (patch) | |
tree | 068dc3454cc9f968162e5ae03cc8733f9011de72 /model-data/src/main/java/org/eclipse/viatra/solver/data/map/internal/MapCursor.java | |
parent | Refactoring based on Sonar reports (diff) | |
download | refinery-7f6a2528bf83f93e3d35eff228f7180e0181f4eb.tar.gz refinery-7f6a2528bf83f93e3d35eff228f7180e0181f4eb.tar.zst refinery-7f6a2528bf83f93e3d35eff228f7180e0181f4eb.zip |
Add new data structure for backend
Co-authored-by: Oszkár Semeráth <semerath@mit.bme.hu>
Diffstat (limited to 'model-data/src/main/java/org/eclipse/viatra/solver/data/map/internal/MapCursor.java')
-rw-r--r-- | model-data/src/main/java/org/eclipse/viatra/solver/data/map/internal/MapCursor.java | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/model-data/src/main/java/org/eclipse/viatra/solver/data/map/internal/MapCursor.java b/model-data/src/main/java/org/eclipse/viatra/solver/data/map/internal/MapCursor.java new file mode 100644 index 00000000..6c177611 --- /dev/null +++ b/model-data/src/main/java/org/eclipse/viatra/solver/data/map/internal/MapCursor.java | |||
@@ -0,0 +1,131 @@ | |||
1 | package org.eclipse.viatra.solver.data.map.internal; | ||
2 | |||
3 | import java.util.ArrayDeque; | ||
4 | import java.util.ConcurrentModificationException; | ||
5 | import java.util.Iterator; | ||
6 | import java.util.List; | ||
7 | |||
8 | import org.eclipse.viatra.solver.data.map.Cursor; | ||
9 | import org.eclipse.viatra.solver.data.map.VersionedMap; | ||
10 | |||
11 | public class MapCursor<KEY,VALUE> implements Cursor<KEY,VALUE> { | ||
12 | // Constants | ||
13 | static int IndexStart = -1; | ||
14 | static int IndexFinish = -2; | ||
15 | |||
16 | // Tree stack | ||
17 | ArrayDeque<Node<KEY,VALUE>> nodeStack; | ||
18 | ArrayDeque<Integer> nodeIndexStack; | ||
19 | int dataIndex; | ||
20 | |||
21 | // Values | ||
22 | KEY key; | ||
23 | VALUE value; | ||
24 | |||
25 | // Hash code for checking concurrent modifications | ||
26 | final VersionedMap<KEY,VALUE> map; | ||
27 | final int creationHash; | ||
28 | |||
29 | public MapCursor(Node<KEY, VALUE> root, VersionedMap<KEY,VALUE> map) { | ||
30 | // Initializing tree stack | ||
31 | super(); | ||
32 | this.nodeStack = new ArrayDeque<>(); | ||
33 | this.nodeIndexStack = new ArrayDeque<>(); | ||
34 | if(root != null) { | ||
35 | this.nodeStack.add(root); | ||
36 | this.nodeIndexStack.push(IndexStart); | ||
37 | } | ||
38 | |||
39 | this.dataIndex = IndexStart; | ||
40 | |||
41 | // Initializing cache | ||
42 | this.key = null; | ||
43 | this.value = null; | ||
44 | |||
45 | // Initializing state | ||
46 | this.map=map; | ||
47 | this.creationHash = map.hashCode(); | ||
48 | } | ||
49 | |||
50 | public KEY getKey() { | ||
51 | return key; | ||
52 | } | ||
53 | |||
54 | public VALUE getValue() { | ||
55 | return value; | ||
56 | } | ||
57 | |||
58 | public boolean isTerminated() { | ||
59 | return this.nodeStack.isEmpty(); | ||
60 | } | ||
61 | |||
62 | public boolean move() { | ||
63 | if(isDirty()) { | ||
64 | throw new ConcurrentModificationException(); | ||
65 | } | ||
66 | if(!isTerminated()) { | ||
67 | boolean result = this.nodeStack.peek().moveToNext(this); | ||
68 | if(this.nodeIndexStack.size() != this.nodeStack.size()) { | ||
69 | throw new IllegalArgumentException("Node stack is corrupted by illegal moves!"); | ||
70 | } | ||
71 | return result; | ||
72 | } | ||
73 | return false; | ||
74 | } | ||
75 | public boolean skipCurrentNode() { | ||
76 | nodeStack.pop(); | ||
77 | nodeIndexStack.pop(); | ||
78 | dataIndex = IndexFinish; | ||
79 | return move(); | ||
80 | } | ||
81 | @Override | ||
82 | public boolean isDirty() { | ||
83 | return this.map.hashCode() != this.creationHash; | ||
84 | } | ||
85 | @Override | ||
86 | public List<VersionedMap<KEY, VALUE>> getDependingMaps() { | ||
87 | return List.of(this.map); | ||
88 | } | ||
89 | |||
90 | public static <KEY,VALUE> boolean sameSubnode(MapCursor<KEY,VALUE> cursor1, MapCursor<KEY,VALUE> cursor2) { | ||
91 | Node<KEY, VALUE> nodeOfCursor1 = cursor1.nodeStack.peek(); | ||
92 | Node<KEY, VALUE> nodeOfCursor2 = cursor2.nodeStack.peek(); | ||
93 | if(nodeOfCursor1 != null && nodeOfCursor2 != null) { | ||
94 | return nodeOfCursor1.equals(nodeOfCursor2); | ||
95 | } else { | ||
96 | return false; | ||
97 | } | ||
98 | } | ||
99 | |||
100 | /** | ||
101 | * | ||
102 | * @param <KEY> | ||
103 | * @param <VALUE> | ||
104 | * @param cursor1 | ||
105 | * @param cursor2 | ||
106 | * @returnv Positive number if cursor 1 is behind, negative number if cursor 2 is behind, and 0 if they are at the same position. | ||
107 | */ | ||
108 | public static <KEY,VALUE> int compare(MapCursor<KEY,VALUE> cursor1, MapCursor<KEY,VALUE> cursor2) { | ||
109 | // two cursors are equally deep | ||
110 | Iterator<Integer> stack1 = cursor1.nodeIndexStack.descendingIterator(); | ||
111 | Iterator<Integer> stack2 = cursor2.nodeIndexStack.descendingIterator(); | ||
112 | if(stack1.hasNext()) { | ||
113 | if(!stack2.hasNext()) { | ||
114 | // stack 2 has no more element, thus stack 1 is deeper | ||
115 | return 1; | ||
116 | } | ||
117 | int val1 = stack1.next(); | ||
118 | int val2 = stack2.next(); | ||
119 | if(val1 < val2) { | ||
120 | return -1; | ||
121 | } else if(val2 < val1) { | ||
122 | return 1; | ||
123 | } | ||
124 | } | ||
125 | if(stack2.hasNext()) { | ||
126 | // stack 2 has more element, thus stack 2 is deeper | ||
127 | return 1; | ||
128 | } | ||
129 | return Integer.compare(cursor1.dataIndex, cursor2.dataIndex); | ||
130 | } | ||
131 | } | ||