aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/util/IMultiLookup.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/util/IMultiLookup.java')
-rw-r--r--subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/util/IMultiLookup.java216
1 files changed, 216 insertions, 0 deletions
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/util/IMultiLookup.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/util/IMultiLookup.java
new file mode 100644
index 00000000..1ce1d2c9
--- /dev/null
+++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/util/IMultiLookup.java
@@ -0,0 +1,216 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2018, Gabor Bergmann, IncQueryLabs 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 *******************************************************************************/
9package tools.refinery.viatra.runtime.matchers.util;
10
11import java.util.stream.Stream;
12
13import tools.refinery.viatra.runtime.matchers.util.CollectionsFactory.MemoryType;
14
15/**
16 * A multi-map that associates sets / multisets / delta sets of values to each key.
17 *
18 * <p> Implementors must provide semantic (not identity-based) hashCode() and equals() using the static helpers {@link #hashCode(IMultiLookup)} and {@link #equals(IMultiLookup, Object)} here.
19 *
20 * @author Gabor Bergmann
21 * @since 2.0
22 * @noimplement This interface is not intended to be implemented by clients.
23 */
24public interface IMultiLookup<Key, Value> {
25
26 /**
27 * Returns true if this collection is empty, false otherwise.
28 * @since 2.2
29 */
30 boolean isEmpty();
31
32
33 /**
34 * Returns true if there are any values associated with the given key.
35 * @param key a key for which associated values are sought
36 * @since 2.3
37 */
38 boolean lookupExists(Key key);
39
40 /**
41 * Returns a (read-only) bucket of values associated with the given key.
42 * Clients must not modify the returned bucket.
43 * @param key a key for which associated values are sought
44 * @return null if key not found, a bucket of values otherwise
45 */
46 IMemoryView<Value> lookup(Key key);
47
48 /**
49 * Returns a (read-only) bucket of values associated with the given key.
50 * Clients must not modify the returned bucket.
51 * @param key a key for which associated values are sought
52 * @return a bucket of values, never null
53 */
54 default IMemoryView<Value> lookupOrEmpty(Key key) {
55 IMemoryView<Value> bucket = lookup(key);
56 return bucket == null ? EmptyMemory.instance() : bucket;
57 }
58
59 /**
60 * Returns a (read-only) bucket of values associated with the given key, while simultaneously removing them.
61 * Clients must not modify the returned bucket.
62 * @param key a key for which associated values are sought
63 * @return a bucket of values, never null
64 * @since 2.3
65 */
66 IMemoryView<Value> lookupAndRemoveAll(Key key);
67
68 /**
69 * Returns a (read-only) bucket of values associated with the given key, which can be of any type.
70 * Clients must not modify the returned bucket.
71 * @param key a key for which associated values are sought (may or may not be of Key type)
72 * @return null if key not found, a bucket of values otherwise
73 */
74 IMemoryView<Value> lookupUnsafe(Object key);
75
76 /**
77 * Returns a (read-only) bucket of values associated with the given key.
78 * Clients must not modify the returned bucket.
79 * @param key a key for which associated values are sought (may or may not be of Key type)
80 * @return a bucket of values, never null
81 */
82 default IMemoryView<Value> lookupUnsafeOrEmpty(Object key) {
83 IMemoryView<Value> bucket = lookupUnsafe(key);
84 return bucket == null ? EmptyMemory.instance() : bucket;
85 }
86
87
88
89 /**
90 * @return the set of distinct keys that have values associated.
91 */
92 Iterable<Key> distinctKeys();
93
94 /**
95 * @return the set of distinct keys that have values associated.
96 * @since 2.3
97 */
98 Stream<Key> distinctKeysStream();
99
100 /**
101 * @return the number of distinct keys that have values associated.
102 */
103 int countKeys();
104
105 /**
106 * Iterates once over each distinct value.
107 */
108 Iterable<Value> distinctValues();
109
110 /**
111 * Iterates once over each distinct value.
112 * @since 2.3
113 */
114 Stream<Value> distinctValuesStream();
115
116
117
118 /**
119 * How significant was the change? *
120 * @author Gabor Bergmann
121 */
122 public enum ChangeGranularity {
123 /**
124 * First key-value pair with given key inserted, or last pair with given key deleted.
125 * (In case of delta maps, also if last negative key-value pair with given key neutralized.)
126 */
127 KEY,
128 /**
129 * First occurrence of given key-value pair inserted, or last occurrence of the pair deleted, while key still has values associated.
130 * (In case of delta maps, also if last negative occurrence of key-value pair neutralized.)
131 */
132 VALUE,
133 /**
134 * Duplicate key-value pair inserted or deleted.
135 */
136 DUPLICATE
137 }
138
139 /**
140 * Adds key-value pair to the lookup structure, or fails if not possible.
141 * <p> If the addition would cause duplicates but the bucket type does not allow it ({@link MemoryType#SETS}),
142 * the operation throws an {@link IllegalStateException}.
143 * @return the granularity of the change
144 * @throws IllegalStateException if addition would cause duplication that is not permitted
145 */
146 public ChangeGranularity addPair(Key key, Value value);
147 /**
148 * Adds key-value pair to the lookup structure.
149 * <p> If the addition would cause duplicates but the bucket type does not allow it ({@link MemoryType#SETS}),
150 * the operation is silently ignored and {@link ChangeGranularity#DUPLICATE} is returned.
151 * @return the granularity of the change, or {@link ChangeGranularity#DUPLICATE} if addition would result in a duplicate and therefore ignored
152 * @since 2.3
153 */
154 public ChangeGranularity addPairOrNop(Key key, Value value);
155 /**
156 * Removes key-value pair from the lookup structure, or fails if not possible.
157 * <p> When attempting to remove a key-value pair with zero multiplicity from a non-delta bucket type
158 * ({@link MemoryType#SETS} or {@link MemoryType#MULTISETS}}), an {@link IllegalStateException} is thrown.
159 * @return the granularity of the change
160 * @throws IllegalStateException if removing non-existing element that is not permitted
161 */
162 public ChangeGranularity removePair(Key key, Value value);
163 /**
164 * Removes key-value pair from the lookup structure.
165 * <p> When attempting to remove a key-value pair with zero multiplicity from a non-delta bucket type
166 * ({@link MemoryType#SETS} or {@link MemoryType#MULTISETS}}),
167 * the operation is silently ignored and {@link ChangeGranularity#DUPLICATE} is returned.
168 * @return the granularity of the change
169 * @throws IllegalStateException if removing non-existing element that is not permitted
170 * @since 2.3
171 */
172 public ChangeGranularity removePairOrNop(Key key, Value value);
173
174 /**
175 * Updates multiplicity of key-value pair by a positive amount.
176 *
177 * <p> PRE: count > 0
178 *
179 * @return the granularity of the change
180 * @throws IllegalStateException if addition would cause duplication that is not permitted
181 */
182 public ChangeGranularity addPairPositiveMultiplicity(Key key, Value value, int count);
183
184 /**
185 * Empties out the lookup structure.
186 */
187 public void clear();
188
189 /**
190 * Provides semantic equality comparison.
191 */
192 public static <Key, Value> boolean equals(IMultiLookup<Key, Value> self, Object obj) {
193 if (obj instanceof IMultiLookup<?, ?>) {
194 IMultiLookup<?, ?> other = (IMultiLookup<?, ?>) obj;
195 if (other.countKeys() != self.countKeys()) return false;
196 for (Object key : other.distinctKeys()) {
197 if (! other.lookupUnsafe(key).equals(self.lookupUnsafe(key)))
198 return false;
199 }
200 return true;
201 }
202 return false;
203 }
204
205 /**
206 * Provides semantic hashCode() comparison.
207 */
208 public static <Key, Value> int hashCode(IMultiLookup<Key, Value> memory) {
209 int hashCode = 0;
210 for (Key key : memory.distinctKeys()) {
211 hashCode += key.hashCode() ^ memory.lookup(key).hashCode();
212 }
213 return hashCode;
214 }
215
216}