diff options
Diffstat (limited to 'subprojects/viatra-runtime-matchers/src/main/java/tools/refinery/viatra/runtime/matchers/memories/timely/AbstractTimelyMaskedMemory.java')
-rw-r--r-- | subprojects/viatra-runtime-matchers/src/main/java/tools/refinery/viatra/runtime/matchers/memories/timely/AbstractTimelyMaskedMemory.java | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/subprojects/viatra-runtime-matchers/src/main/java/tools/refinery/viatra/runtime/matchers/memories/timely/AbstractTimelyMaskedMemory.java b/subprojects/viatra-runtime-matchers/src/main/java/tools/refinery/viatra/runtime/matchers/memories/timely/AbstractTimelyMaskedMemory.java new file mode 100644 index 00000000..45ce3a4e --- /dev/null +++ b/subprojects/viatra-runtime-matchers/src/main/java/tools/refinery/viatra/runtime/matchers/memories/timely/AbstractTimelyMaskedMemory.java | |||
@@ -0,0 +1,228 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2018, Gabor Bergmann, IncQuery Labs Ltd. | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.memories.timely; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.Iterator; | ||
13 | import java.util.Map; | ||
14 | import java.util.Map.Entry; | ||
15 | import java.util.Objects; | ||
16 | import java.util.Set; | ||
17 | import java.util.TreeMap; | ||
18 | |||
19 | import tools.refinery.viatra.runtime.matchers.memories.MaskedTupleMemory; | ||
20 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
21 | import tools.refinery.viatra.runtime.matchers.tuple.TupleMask; | ||
22 | import tools.refinery.viatra.runtime.matchers.util.CollectionsFactory; | ||
23 | import tools.refinery.viatra.runtime.matchers.util.Direction; | ||
24 | import tools.refinery.viatra.runtime.matchers.util.Signed; | ||
25 | import tools.refinery.viatra.runtime.matchers.util.TimelyMemory; | ||
26 | import tools.refinery.viatra.runtime.matchers.util.timeline.Diff; | ||
27 | import tools.refinery.viatra.runtime.matchers.util.timeline.Timeline; | ||
28 | |||
29 | /** | ||
30 | * Common parts of timely default and timely unary implementations. | ||
31 | * | ||
32 | * @noextend This class is not intended to be subclassed by clients. | ||
33 | * @author Tamas Szabo | ||
34 | * @since 2.3 | ||
35 | */ | ||
36 | abstract class AbstractTimelyMaskedMemory<Timestamp extends Comparable<Timestamp>, KeyType> | ||
37 | extends MaskedTupleMemory<Timestamp> { | ||
38 | |||
39 | protected final TreeMap<Timestamp, Set<KeyType>> foldingStates; | ||
40 | protected final Map<KeyType, TimelyMemory<Timestamp>> memoryMap; | ||
41 | protected final boolean isLazy; | ||
42 | |||
43 | public AbstractTimelyMaskedMemory(final TupleMask mask, final Object owner, final boolean isLazy) { | ||
44 | super(mask, owner); | ||
45 | this.isLazy = isLazy; | ||
46 | this.memoryMap = CollectionsFactory.createMap(); | ||
47 | this.foldingStates = this.isLazy ? CollectionsFactory.createTreeMap() : null; | ||
48 | } | ||
49 | |||
50 | @Override | ||
51 | public void initializeWith(final MaskedTupleMemory<Timestamp> other, final Timestamp defaultValue) { | ||
52 | final Iterable<Tuple> signatures = other.getSignatures(); | ||
53 | for (final Tuple signature : signatures) { | ||
54 | if (other.isTimely()) { | ||
55 | final Map<Tuple, Timeline<Timestamp>> tupleMap = other.getWithTimeline(signature); | ||
56 | for (final Entry<Tuple, Timeline<Timestamp>> entry : tupleMap.entrySet()) { | ||
57 | for (final Signed<Timestamp> signed : entry.getValue().asChangeSequence()) { | ||
58 | if (signed.getDirection() == Direction.DELETE) { | ||
59 | this.removeWithTimestamp(entry.getKey(), signed.getPayload()); | ||
60 | } else { | ||
61 | this.addWithTimestamp(entry.getKey(), signed.getPayload()); | ||
62 | } | ||
63 | } | ||
64 | } | ||
65 | } else { | ||
66 | final Collection<Tuple> tuples = other.get(signature); | ||
67 | for (final Tuple tuple : tuples) { | ||
68 | this.addWithTimestamp(tuple, defaultValue); | ||
69 | } | ||
70 | } | ||
71 | } | ||
72 | } | ||
73 | |||
74 | public boolean isPresentAtInfinityInteral(KeyType key) { | ||
75 | final TimelyMemory<Timestamp> values = this.memoryMap.get(key); | ||
76 | if (values == null) { | ||
77 | return false; | ||
78 | } else { | ||
79 | return values.getCountAtInfinity() != 0; | ||
80 | } | ||
81 | } | ||
82 | |||
83 | @Override | ||
84 | public void clear() { | ||
85 | this.memoryMap.clear(); | ||
86 | } | ||
87 | |||
88 | @Override | ||
89 | public int getKeysetSize() { | ||
90 | return this.memoryMap.keySet().size(); | ||
91 | } | ||
92 | |||
93 | @Override | ||
94 | public int getTotalSize() { | ||
95 | int i = 0; | ||
96 | for (final Entry<KeyType, TimelyMemory<Timestamp>> entry : this.memoryMap.entrySet()) { | ||
97 | i += entry.getValue().size(); | ||
98 | } | ||
99 | return i; | ||
100 | } | ||
101 | |||
102 | @Override | ||
103 | public Iterator<Tuple> iterator() { | ||
104 | return this.memoryMap.values().stream().flatMap(e -> e.keySet().stream()).iterator(); | ||
105 | } | ||
106 | |||
107 | protected Collection<Tuple> getInternal(final KeyType key) { | ||
108 | final TimelyMemory<Timestamp> memory = this.memoryMap.get(key); | ||
109 | if (memory == null) { | ||
110 | return null; | ||
111 | } else { | ||
112 | return memory.getTuplesAtInfinity(); | ||
113 | } | ||
114 | } | ||
115 | |||
116 | public Map<Tuple, Timeline<Timestamp>> getWithTimestampInternal(final KeyType key) { | ||
117 | final TimelyMemory<Timestamp> memory = this.memoryMap.get(key); | ||
118 | if (memory == null) { | ||
119 | return null; | ||
120 | } else { | ||
121 | return memory.asMap(); | ||
122 | } | ||
123 | } | ||
124 | |||
125 | protected Diff<Timestamp> removeInternal(final KeyType key, final Tuple tuple, final Timestamp timestamp) { | ||
126 | Timestamp oldResumableTimestamp = null; | ||
127 | Timestamp newResumableTimestamp = null; | ||
128 | |||
129 | final TimelyMemory<Timestamp> keyMemory = this.memoryMap.get(key); | ||
130 | if (keyMemory == null) { | ||
131 | throw raiseDuplicateDeletion(tuple); | ||
132 | } | ||
133 | |||
134 | if (this.isLazy) { | ||
135 | oldResumableTimestamp = keyMemory.getResumableTimestamp(); | ||
136 | } | ||
137 | |||
138 | Diff<Timestamp> diff = null; | ||
139 | try { | ||
140 | diff = keyMemory.remove(tuple, timestamp); | ||
141 | } catch (final IllegalStateException e) { | ||
142 | throw raiseDuplicateDeletion(tuple); | ||
143 | } | ||
144 | if (keyMemory.isEmpty()) { | ||
145 | this.memoryMap.remove(key); | ||
146 | } | ||
147 | |||
148 | if (this.isLazy) { | ||
149 | newResumableTimestamp = keyMemory.getResumableTimestamp(); | ||
150 | if (!Objects.equals(oldResumableTimestamp, newResumableTimestamp)) { | ||
151 | unregisterFoldingState(oldResumableTimestamp, key); | ||
152 | registerFoldingState(newResumableTimestamp, key); | ||
153 | } | ||
154 | } | ||
155 | |||
156 | return diff; | ||
157 | } | ||
158 | |||
159 | protected Diff<Timestamp> addInternal(final KeyType key, final Tuple tuple, final Timestamp timestamp) { | ||
160 | Timestamp oldResumableTimestamp = null; | ||
161 | Timestamp newResumableTimestamp = null; | ||
162 | |||
163 | final TimelyMemory<Timestamp> keyMemory = this.memoryMap.computeIfAbsent(key, | ||
164 | k -> new TimelyMemory<Timestamp>(this.isLazy)); | ||
165 | |||
166 | if (this.isLazy) { | ||
167 | oldResumableTimestamp = keyMemory.getResumableTimestamp(); | ||
168 | } | ||
169 | |||
170 | final Diff<Timestamp> diff = keyMemory.put(tuple, timestamp); | ||
171 | |||
172 | if (this.isLazy) { | ||
173 | newResumableTimestamp = keyMemory.getResumableTimestamp(); | ||
174 | if (!Objects.equals(oldResumableTimestamp, newResumableTimestamp)) { | ||
175 | unregisterFoldingState(oldResumableTimestamp, key); | ||
176 | registerFoldingState(newResumableTimestamp, key); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | return diff; | ||
181 | } | ||
182 | |||
183 | @Override | ||
184 | public Diff<Timestamp> removeWithTimestamp(final Tuple tuple, final Timestamp timestamp) { | ||
185 | return removeWithTimestamp(tuple, null, timestamp); | ||
186 | } | ||
187 | |||
188 | @Override | ||
189 | public Diff<Timestamp> addWithTimestamp(final Tuple tuple, final Timestamp timestamp) { | ||
190 | return addWithTimestamp(tuple, null, timestamp); | ||
191 | } | ||
192 | |||
193 | @Override | ||
194 | public boolean isTimely() { | ||
195 | return true; | ||
196 | } | ||
197 | |||
198 | protected void registerFoldingState(final Timestamp timestamp, final KeyType key) { | ||
199 | if (timestamp != null) { | ||
200 | this.foldingStates.compute(timestamp, (k, v) -> { | ||
201 | if (v == null) { | ||
202 | v = CollectionsFactory.createSet(); | ||
203 | } | ||
204 | v.add(key); | ||
205 | return v; | ||
206 | }); | ||
207 | } | ||
208 | } | ||
209 | |||
210 | protected void unregisterFoldingState(final Timestamp timestamp, final KeyType key) { | ||
211 | if (timestamp != null) { | ||
212 | this.foldingStates.compute(timestamp, (k, v) -> { | ||
213 | v.remove(key); | ||
214 | return v.isEmpty() ? null : v; | ||
215 | }); | ||
216 | } | ||
217 | } | ||
218 | |||
219 | @Override | ||
220 | public Timestamp getResumableTimestamp() { | ||
221 | if (this.foldingStates == null || this.foldingStates.isEmpty()) { | ||
222 | return null; | ||
223 | } else { | ||
224 | return this.foldingStates.firstKey(); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | } | ||