aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/util/IMemoryView.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/util/IMemoryView.java')
-rw-r--r--subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/util/IMemoryView.java205
1 files changed, 205 insertions, 0 deletions
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/util/IMemoryView.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/util/IMemoryView.java
new file mode 100644
index 00000000..add575c6
--- /dev/null
+++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/util/IMemoryView.java
@@ -0,0 +1,205 @@
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.Iterator;
12import java.util.Map;
13import java.util.Map.Entry;
14import java.util.Set;
15import java.util.function.BiConsumer;
16import java.util.stream.Stream;
17import java.util.stream.StreamSupport;
18
19/**
20 * A read-only view on a memory containing a positive or negative number of equal() copies for some values.
21 * During iterations, each distinct value is iterated only once.
22 *
23 * <p> See {@link IMemory}.
24 *
25 * <p> Implementors must provide semantic (not identity-based) hashCode() and equals() using the static helpers {@link #hashCode(IMemoryView)} and {@link #equals(IMemoryView, Object)} here.
26 *
27 * @author Gabor Bergmann
28 *
29 * @since 2.0
30 */
31public interface IMemoryView<T> extends Iterable<T> {
32
33 /**
34 * Returns the number of occurrences of the given value.
35 *
36 * @return the number of occurrences
37 */
38 int getCount(T value);
39
40 /**
41 * Returns the number of occurrences of the given value (which may be of any type).
42 *
43 * @return the number of occurrences
44 */
45 int getCountUnsafe(Object value);
46
47 /**
48 * @return true if the given value is contained with a nonzero multiplicity
49 */
50 boolean containsNonZero(T value);
51
52 /**
53 * @return true if the given value (which may be of any type) is contained with a nonzero multiplicity
54 */
55 boolean containsNonZeroUnsafe(Object value);
56
57 /**
58 * @return the number of distinct values
59 */
60 int size();
61
62 /**
63 *
64 * @return iff contains at least one value with non-zero occurrences
65 */
66 boolean isEmpty();
67
68 /**
69 * The set of distinct values
70 */
71 Set<T> distinctValues();
72
73
74 /**
75 * Where supported, returns the stored element that is equal to the given value, or null if none.
76 * Useful for canonicalization in case of non-identity equals().
77 *
78 * <p> For collections that do not support canonicalization, simply returns the argument if contained, null if none.
79 *
80 * @return a value equal to the argument if such a value is stored, or null if none
81 */
82 default T theContainedVersionOf(T value) {
83 if (containsNonZero(value)) return value; else return null;
84 }
85
86 /**
87 * Where supported, returns the stored element that is equal to the given value (of any type),
88 * or null if none.
89 * Useful for canonicalization in case of non-identity equals().
90 *
91 * <p> For collections that do not support canonicalization, simply returns the argument if contained, null if none.
92 *
93 * @return a value equal to the argument if such a value is stored, or null if none
94 */
95 @SuppressWarnings("unchecked")
96 default T theContainedVersionOfUnsafe(Object value) {
97 if (containsNonZeroUnsafe(value)) return (T) value; else return null;
98 }
99
100
101 /**
102 * @return an unmodifiable view of contained values with their multiplicities
103 */
104 default Iterable<Map.Entry<T, Integer>> entriesWithMultiplicities() {
105 return () -> {
106 Iterator<T> wrapped = distinctValues().iterator();
107 return new Iterator<Map.Entry<T, Integer>> () {
108 @Override
109 public boolean hasNext() {
110 return wrapped.hasNext();
111 }
112
113 @Override
114 public Map.Entry<T, Integer> next() {
115 T key = wrapped.next();
116 int count = getCount(key);
117 return new Map.Entry<T, Integer>(){
118 @Override
119 public T getKey() {
120 return key;
121 }
122
123 @Override
124 public Integer getValue() {
125 return count;
126 }
127
128 @Override
129 public Integer setValue(Integer value) {
130 throw new UnsupportedOperationException();
131 }
132
133 @Override
134 public String toString() {
135 return String.format("%d of %s", count, key);
136 }
137
138 };
139 }
140
141 };
142 };
143 }
144
145 /**
146 * Process contained values with their multiplicities
147 */
148 default void forEachEntryWithMultiplicities(BiConsumer<T, Integer> entryConsumer) {
149 for (T value : distinctValues()) {
150 entryConsumer.accept(value, getCount(value));
151 }
152 }
153
154
155 /**
156 * For compatibility with legacy code relying on element-to-integer maps.
157 * @return an unmodifiable view of contained values with their multiplicities
158 */
159 public default Map<T, Integer> asMap() {
160 return new MemoryViewBackedMapView<>(this);
161 }
162
163 /**
164 * For compatibility with legacy code relying on element-to-integer maps.
165 * @return an unmodifiable view of contained values with their multiplicities
166 */
167 public static <T> IMemoryView<T> fromMap(Map<T, Integer> wrapped) {
168 return new MapBackedMemoryView<>(wrapped);
169 }
170
171 /**
172 * @return a stream of values, iterable once
173 * @since 2.1
174 */
175 public default Stream<T> asStream() {
176 return StreamSupport.stream(spliterator(), false);
177 }
178
179 /**
180 * Provides semantic equality comparison.
181 */
182 public static <T> boolean equals(IMemoryView<T> self, Object obj) {
183 if (obj instanceof IMemoryView<?>) {
184 IMemoryView<?> other = (IMemoryView<?>) obj;
185 if (other.size() != self.size()) return false;
186 for (Entry<?, Integer> entry : other.entriesWithMultiplicities()) {
187 if ( !entry.getValue().equals(self.getCountUnsafe(entry.getKey())))
188 return false;
189 }
190 return true;
191 }
192 return false;
193 }
194
195 /**
196 * Provides semantic hashCode() comparison.
197 */
198 public static <T> int hashCode(IMemoryView<T> memory) {
199 int hashCode = 0;
200 for (T value : memory.distinctValues()) {
201 hashCode += value.hashCode() ^ Integer.hashCode(memory.getCount(value));
202 }
203 return hashCode;
204 }
205} \ No newline at end of file