diff options
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.java | 350 |
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 | |||
10 | package tools.refinery.viatra.runtime.api.impl; | ||
11 | |||
12 | import java.util.Collection; | ||
13 | import java.util.List; | ||
14 | import java.util.Optional; | ||
15 | import java.util.Set; | ||
16 | import java.util.function.Consumer; | ||
17 | import java.util.stream.Collectors; | ||
18 | import java.util.stream.Stream; | ||
19 | |||
20 | import tools.refinery.viatra.runtime.api.IPatternMatch; | ||
21 | import tools.refinery.viatra.runtime.api.IQuerySpecification; | ||
22 | import tools.refinery.viatra.runtime.api.ViatraQueryEngine; | ||
23 | import tools.refinery.viatra.runtime.api.ViatraQueryMatcher; | ||
24 | import tools.refinery.viatra.runtime.internal.apiimpl.QueryResultWrapper; | ||
25 | import tools.refinery.viatra.runtime.matchers.backend.IMatcherCapability; | ||
26 | import tools.refinery.viatra.runtime.matchers.backend.IQueryResultProvider; | ||
27 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
28 | import 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 | */ | ||
37 | public 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 | } | ||