aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/impl/BaseMatcher.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/impl/BaseMatcher.java')
-rw-r--r--subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/impl/BaseMatcher.java350
1 files changed, 350 insertions, 0 deletions
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/impl/BaseMatcher.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/impl/BaseMatcher.java
new file mode 100644
index 00000000..ad79aafd
--- /dev/null
+++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/impl/BaseMatcher.java
@@ -0,0 +1,350 @@
1/*******************************************************************************
2 * Copyright (c) 2004-2010 Gabor Bergmann and Daniel Varro
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
10package tools.refinery.viatra.runtime.api.impl;
11
12import java.util.Collection;
13import java.util.List;
14import java.util.Optional;
15import java.util.Set;
16import java.util.function.Consumer;
17import java.util.stream.Collectors;
18import java.util.stream.Stream;
19
20import tools.refinery.viatra.runtime.api.IPatternMatch;
21import tools.refinery.viatra.runtime.api.IQuerySpecification;
22import tools.refinery.viatra.runtime.api.ViatraQueryEngine;
23import tools.refinery.viatra.runtime.api.ViatraQueryMatcher;
24import tools.refinery.viatra.runtime.internal.apiimpl.QueryResultWrapper;
25import tools.refinery.viatra.runtime.matchers.backend.IMatcherCapability;
26import tools.refinery.viatra.runtime.matchers.backend.IQueryResultProvider;
27import tools.refinery.viatra.runtime.matchers.tuple.Tuple;
28import tools.refinery.viatra.runtime.matchers.util.Preconditions;
29
30/**
31 * Base implementation of ViatraQueryMatcher.
32 *
33 * @author Bergmann Gábor
34 *
35 * @param <Match>
36 */
37public abstract class BaseMatcher<Match extends IPatternMatch> extends QueryResultWrapper implements ViatraQueryMatcher<Match> {
38
39 // FIELDS AND CONSTRUCTOR
40
41 protected ViatraQueryEngine engine;
42 protected IQuerySpecification<? extends BaseMatcher<Match>> querySpecification;
43 private IMatcherCapability capabilities;
44
45 /**
46 * @since 1.4
47 */
48 public BaseMatcher(IQuerySpecification<? extends BaseMatcher<Match>> querySpecification) {
49 this.querySpecification = querySpecification;
50 this.querySpecification.getInternalQueryRepresentation().ensureInitialized();
51 }
52
53 /**
54 * @since 1.4
55 */
56 @Override
57 protected
58 void setBackend(ViatraQueryEngine engine, IQueryResultProvider resultProvider, IMatcherCapability capabilities){
59 this.backend = resultProvider;
60 this.engine = engine;
61 this.capabilities = capabilities;
62 }
63
64 // ARRAY-BASED INTERFACE
65
66 /** Converts the array representation of a pattern match to an immutable Match object. */
67 protected abstract Match arrayToMatch(Object[] parameters);
68 /** Converts the array representation of a pattern match to a mutable Match object. */
69 protected abstract Match arrayToMatchMutable(Object[] parameters);
70
71 /** Converts the Match object of a pattern match to the array representation. */
72 protected Object[] matchToArray(Match partialMatch) {
73 return partialMatch.toArray();
74 }
75 // TODO make me public for performance reasons
76 protected abstract Match tupleToMatch(Tuple t);
77
78 private Object[] fEmptyArray;
79
80 protected Object[] emptyArray() {
81 if (fEmptyArray == null)
82 fEmptyArray = new Object[getSpecification().getParameterNames().size()];
83 return fEmptyArray;
84 }
85
86 // REFLECTION
87
88 @Override
89 public Integer getPositionOfParameter(String parameterName) {
90 return getSpecification().getPositionOfParameter(parameterName);
91 }
92
93 @Override
94 public List<String> getParameterNames() {
95 return getSpecification().getParameterNames();
96 }
97
98 // BASE IMPLEMENTATION
99
100 @Override
101 public Collection<Match> getAllMatches() {
102 return rawStreamAllMatches(emptyArray()).collect(Collectors.toSet());
103 }
104
105 @Override
106 public Stream<Match> streamAllMatches() {
107 return rawStreamAllMatches(emptyArray());
108 }
109
110 /**
111 * Returns a stream of all matches of the pattern that conform to the given fixed values of some parameters.
112 *
113 * @param parameters
114 * array where each non-null element binds the corresponding pattern parameter to a fixed value.
115 * @pre size of input array must be equal to the number of parameters.
116 * @return matches represented as a Match object.
117 * @since 2.0
118 */
119 protected Stream<Match> rawStreamAllMatches(Object[] parameters) {
120 // clones the tuples into a match object to protect the Tuples from modifications outside of the ReteMatcher
121 return backend.getAllMatches(parameters).map(this::tupleToMatch);
122 }
123
124 @Override
125 public Collection<Match> getAllMatches(Match partialMatch) {
126 return rawStreamAllMatches(partialMatch.toArray()).collect(Collectors.toSet());
127 }
128
129 @Override
130 public Stream<Match> streamAllMatches(Match partialMatch) {
131 return rawStreamAllMatches(partialMatch.toArray());
132 }
133
134 // with input binding as pattern-specific parameters: not declared in interface
135
136 @Override
137 public Optional<Match> getOneArbitraryMatch() {
138 return rawGetOneArbitraryMatch(emptyArray());
139 }
140
141 /**
142 * Returns an arbitrarily chosen match of the pattern that conforms to the given fixed values of some parameters.
143 * Neither determinism nor randomness of selection is guaranteed.
144 *
145 * @param parameters
146 * array where each non-null element binds the corresponding pattern parameter to a fixed value.
147 * @pre size of input array must be equal to the number of parameters.
148 * @return a match represented as a Match object, or null if no match is found.
149 * @since 2.0
150 */
151 protected Optional<Match> rawGetOneArbitraryMatch(Object[] parameters) {
152 return backend.getOneArbitraryMatch(parameters).map(this::tupleToMatch);
153 }
154
155 @Override
156 public Optional<Match> getOneArbitraryMatch(Match partialMatch) {
157 return rawGetOneArbitraryMatch(partialMatch.toArray());
158 }
159
160 // with input binding as pattern-specific parameters: not declared in interface
161
162 /**
163 * Indicates whether the given combination of specified pattern parameters constitute a valid pattern match, under
164 * any possible substitution of the unspecified parameters.
165 *
166 * @param parameters
167 * array where each non-null element binds the corresponding pattern parameter to a fixed value.
168 * @return true if the input is a valid (partial) match of the pattern.
169 */
170 protected boolean rawHasMatch(Object[] parameters) {
171 return backend.hasMatch(parameters);
172 }
173
174 @Override
175 public boolean hasMatch() {
176 return rawHasMatch(emptyArray());
177 }
178
179 @Override
180 public boolean hasMatch(Match partialMatch) {
181 return rawHasMatch(partialMatch.toArray());
182 }
183
184 // with input binding as pattern-specific parameters: not declared in interface
185
186 @Override
187 public int countMatches() {
188 return rawCountMatches(emptyArray());
189 }
190
191 /**
192 * Returns the number of all matches of the pattern that conform to the given fixed values of some parameters.
193 *
194 * @param parameters
195 * array where each non-null element binds the corresponding pattern parameter to a fixed value.
196 * @pre size of input array must be equal to the number of parameters.
197 * @return the number of pattern matches found.
198 */
199 protected int rawCountMatches(Object[] parameters) {
200 return backend.countMatches(parameters);
201 }
202
203 @Override
204 public int countMatches(Match partialMatch) {
205 return rawCountMatches(partialMatch.toArray());
206 }
207
208 // with input binding as pattern-specific parameters: not declared in interface
209
210 /**
211 * Executes the given processor on each match of the pattern that conforms to the given fixed values of some
212 * parameters.
213 *
214 * @param parameters
215 * array where each non-null element binds the corresponding pattern parameter to a fixed value.
216 * @pre size of input array must be equal to the number of parameters.
217 * @param action
218 * the action that will process each pattern match.
219 * @since 2.0
220 */
221 protected void rawForEachMatch(Object[] parameters, Consumer<? super Match> processor) {
222 backend.getAllMatches(parameters).map(this::tupleToMatch).forEach(processor);
223 }
224
225 @Override
226 public void forEachMatch(Consumer<? super Match> processor) {
227 rawForEachMatch(emptyArray(), processor);
228 }
229
230 @Override
231 public void forEachMatch(Match match, Consumer<? super Match> processor) {
232 rawForEachMatch(match.toArray(), processor);
233 }
234
235 // with input binding as pattern-specific parameters: not declared in interface
236
237 @Override
238 public boolean forOneArbitraryMatch(Consumer<? super Match> processor) {
239 return rawForOneArbitraryMatch(emptyArray(), processor);
240 }
241
242 @Override
243 public boolean forOneArbitraryMatch(Match partialMatch, Consumer<? super Match> processor) {
244 return rawForOneArbitraryMatch(partialMatch.toArray(), processor);
245 }
246
247 /**
248 * Executes the given processor on an arbitrarily chosen match of the pattern that conforms to the given fixed
249 * values of some parameters. Neither determinism nor randomness of selection is guaranteed.
250 *
251 * @param parameters
252 * array where each non-null element binds the corresponding pattern parameter to a fixed value.
253 * @pre size of input array must be equal to the number of parameters.
254 * @param processor
255 * the action that will process the selected match.
256 * @return true if the pattern has at least one match with the given parameter values, false if the processor was
257 * not invoked
258 * @since 2.0
259 */
260 protected boolean rawForOneArbitraryMatch(Object[] parameters, Consumer<? super Match> processor) {
261 return backend.getOneArbitraryMatch(parameters).map(this::tupleToMatch).map(m -> {
262 processor.accept(m);
263 return true;
264 }).orElse(false);
265 }
266
267 // with input binding as pattern-specific parameters: not declared in interface
268
269
270 @Override
271 public Match newEmptyMatch() {
272 return arrayToMatchMutable(new Object[getParameterNames().size()]);
273 }
274
275 @Override
276 public Match newMatch(Object... parameters) {
277 return arrayToMatch(parameters);
278 }
279
280 @Override
281 public Set<Object> getAllValues(final String parameterName) {
282 return rawStreamAllValues(getPositionOfParameter(parameterName), emptyArray()).collect(Collectors.toSet());
283 }
284
285 @Override
286 public Set<Object> getAllValues(final String parameterName, Match partialMatch) {
287 return rawStreamAllValues(getPositionOfParameter(parameterName), partialMatch.toArray()).collect(Collectors.toSet());
288 }
289
290 /**
291 * Retrieve a stream of values that occur in matches for the given parameterName, that conforms to the given fixed
292 * values of some parameters.
293 *
294 * @param position
295 * position of the parameter for which values are returned
296 * @param parameters
297 * a parameter array corresponding to a partial match of the pattern where each non-null field binds the
298 * corresponding pattern parameter to a fixed value.
299 * @return the stream of all values in the given position
300 * @throws IllegalArgumentException
301 * if length of parameters array does not equal to number of parameters
302 * @throws IndexOutOfBoundsException
303 * if position is not appropriate for the current parameter size
304 * @since 2.0
305 */
306 protected Stream<Object> rawStreamAllValues(final int position, Object[] parameters) {
307 Preconditions.checkElementIndex(position, getParameterNames().size());
308 Preconditions.checkArgument(parameters.length == getParameterNames().size());
309 return rawStreamAllMatches(parameters).map(match -> match.get(position));
310 }
311
312 /**
313 * Uses an existing set to accumulate all values of the parameter with the given name. Since it is a protected
314 * method, no error checking or input validation is performed!
315 *
316 * @param position
317 * position of the parameter for which values are returned
318 * @param parameters
319 * a parameter array corresponding to a partial match of the pattern where each non-null field binds the
320 * corresponding pattern parameter to a fixed value.
321 * @param accumulator
322 * the existing set to fill with the values
323 */
324 @SuppressWarnings("unchecked")
325 protected <T> void rawAccumulateAllValues(final int position, Object[] parameters, final Set<T> accumulator) {
326 rawForEachMatch(parameters, match -> accumulator.add((T) match.get(position)));
327 }
328
329 @Override
330 public ViatraQueryEngine getEngine() {
331 return engine;
332 }
333
334 @Override
335 public IQuerySpecification<? extends BaseMatcher<Match>> getSpecification() {
336 return querySpecification;
337 }
338
339 @Override
340 public String getPatternName() {
341 return querySpecification.getFullyQualifiedName();
342 }
343
344 /**
345 * @since 1.4
346 */
347 public IMatcherCapability getCapabilities() {
348 return capabilities;
349 }
350}