aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/viatra-runtime-matchers/src/main/java/tools/refinery/viatra/runtime/matchers/backend/QueryEvaluationHint.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/viatra-runtime-matchers/src/main/java/tools/refinery/viatra/runtime/matchers/backend/QueryEvaluationHint.java')
-rw-r--r--subprojects/viatra-runtime-matchers/src/main/java/tools/refinery/viatra/runtime/matchers/backend/QueryEvaluationHint.java241
1 files changed, 241 insertions, 0 deletions
diff --git a/subprojects/viatra-runtime-matchers/src/main/java/tools/refinery/viatra/runtime/matchers/backend/QueryEvaluationHint.java b/subprojects/viatra-runtime-matchers/src/main/java/tools/refinery/viatra/runtime/matchers/backend/QueryEvaluationHint.java
new file mode 100644
index 00000000..eab92128
--- /dev/null
+++ b/subprojects/viatra-runtime-matchers/src/main/java/tools/refinery/viatra/runtime/matchers/backend/QueryEvaluationHint.java
@@ -0,0 +1,241 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Bergmann Gabor, Istvan Rath 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 *******************************************************************************/
9package tools.refinery.viatra.runtime.matchers.backend;
10
11import java.util.AbstractMap;
12import java.util.Collections;
13import java.util.HashMap;
14import java.util.Map;
15import java.util.Objects;
16import java.util.stream.Collectors;
17
18import tools.refinery.viatra.runtime.matchers.util.Preconditions;
19
20/**
21 * Provides VIATRA Query with additional hints on how a query should be evaluated. The same hint can be provided to multiple queries.
22 *
23 * <p> This class is immutable. Overriding options will create a new instance.
24 *
25 * <p>
26 * Here be dragons: for advanced users only.
27 *
28 * @author Bergmann Gabor
29 *
30 */
31public class QueryEvaluationHint {
32
33 /**
34 * @since 2.0
35 *
36 */
37 public enum BackendRequirement {
38 /**
39 * The current hint does not specify any backend requirement
40 */
41 UNSPECIFIED,
42 /**
43 * The current hint specifies that the default search backend of the engine should be used
44 */
45 DEFAULT_SEARCH,
46 /**
47 * The current hint specifies that the default caching backend of the engine should be used
48 */
49 DEFAULT_CACHING,
50 /**
51 * The current hint specifies that a specific backend is to be used
52 */
53 SPECIFIC
54 }
55
56 final IQueryBackendFactory queryBackendFactory;
57 final Map<QueryHintOption<?>, Object> backendHintSettings;
58 final BackendRequirement requirement;
59
60 /**
61 * Specifies the suggested query backend requirements, and value settings for additional backend-specific options.
62 *
63 * <p>
64 * The backend requirement type must not be {@link BackendRequirement#SPECIFIC} - for that case, use the constructor
65 * {@link #QueryEvaluationHint(Map, IQueryBackendFactory)}.
66 *
67 * @param backendHintSettings
68 * if non-null, each entry in the map overrides backend-specific options regarding query evaluation
69 * (null-valued map entries permitted to erase hints); passing null means default options associated with
70 * the query
71 * @param backendRequirementType
72 * defines the kind of backend requirement
73 * @since 2.0
74 */
75 public QueryEvaluationHint(Map<QueryHintOption<?>, Object> backendHintSettings, BackendRequirement backendRequirementType) {
76 super();
77 Preconditions.checkArgument(backendRequirementType != null, "Specific requirement needs to be set");
78 Preconditions.checkArgument(backendRequirementType != BackendRequirement.SPECIFIC, "Specific backend requirement needs providing a corresponding backend type");
79 this.queryBackendFactory = null;
80 this.requirement = backendRequirementType;
81 this.backendHintSettings = (backendHintSettings == null)
82 ? Collections.<QueryHintOption<?>, Object> emptyMap()
83 : new HashMap<>(backendHintSettings);
84 }
85
86 /**
87 * Specifies the suggested query backend, and value settings for additional backend-specific options. The first
88 * parameter can be null; if the second parameter is null, it is expected that the other constructor is called
89 * instead with a {@link BackendRequirement#UNSPECIFIED} parameter.
90 *
91 * @param backendHintSettings
92 * if non-null, each entry in the map overrides backend-specific options regarding query evaluation
93 * (null-valued map entries permitted to erase hints); passing null means default options associated with
94 * the query
95 * @param queryBackendFactory
96 * overrides the query evaluator algorithm; passing null retains the default algorithm associated with
97 * the query
98 * @since 1.5
99 */
100 public QueryEvaluationHint(
101 Map<QueryHintOption<?>, Object> backendHintSettings,
102 IQueryBackendFactory queryBackendFactory) {
103 super();
104 this.queryBackendFactory = queryBackendFactory;
105 this.requirement = (queryBackendFactory == null) ? BackendRequirement.UNSPECIFIED : BackendRequirement.SPECIFIC;
106 this.backendHintSettings = (backendHintSettings == null)
107 ? Collections.<QueryHintOption<?>, Object> emptyMap()
108 : new HashMap<>(backendHintSettings);
109 }
110
111 /**
112 * Returns the backend requirement described by this hint. If a specific backend is required, that can be queried by {@link #getQueryBackendFactory()}.
113 * @since 2.0
114 */
115 public BackendRequirement getQueryBackendRequirementType() {
116 return requirement;
117 }
118
119 /**
120 * A suggestion for choosing the query evaluator algorithm.
121 *
122 * <p>
123 * Returns null iff {@link #getQueryBackendRequirementType()} does not return {@link BackendRequirement#SPECIFIC};
124 * in such cases a corresponding default backend is selected inside the engine
125 */
126 public IQueryBackendFactory getQueryBackendFactory() {
127 return queryBackendFactory;
128 }
129
130 /**
131 * Each entry in the immutable map overrides backend-specific options regarding query evaluation.
132 *
133 * <p>The map is non-null, even if empty.
134 * Null-valued map entries are also permitted to erase hints via {@link #overrideBy(QueryEvaluationHint)}.
135 *
136 * @since 1.5
137 */
138 public Map<QueryHintOption<?>, Object> getBackendHintSettings() {
139 return backendHintSettings;
140 }
141
142
143 /**
144 * Override values in this hint and return a consolidated instance.
145 *
146 * @since 1.4
147 */
148 public QueryEvaluationHint overrideBy(QueryEvaluationHint overridingHint){
149 if (overridingHint == null)
150 return this;
151
152 BackendRequirement overriddenRequirement = this.getQueryBackendRequirementType();
153 if (overridingHint.getQueryBackendRequirementType() != BackendRequirement.UNSPECIFIED) {
154 overriddenRequirement = overridingHint.getQueryBackendRequirementType();
155 }
156 Map<QueryHintOption<?>, Object> hints = new HashMap<>(this.getBackendHintSettings());
157 if (overridingHint.getBackendHintSettings() != null) {
158 hints.putAll(overridingHint.getBackendHintSettings());
159 }
160 if (overriddenRequirement == BackendRequirement.SPECIFIC) {
161 IQueryBackendFactory factory = this.getQueryBackendFactory();
162 if (overridingHint.getQueryBackendFactory() != null) {
163 factory = overridingHint.getQueryBackendFactory();
164 }
165 return new QueryEvaluationHint(hints, factory);
166 } else {
167 return new QueryEvaluationHint(hints, overriddenRequirement);
168 }
169 }
170
171 /**
172 * Returns whether the given hint option is overridden.
173 * @since 1.5
174 */
175 public boolean isOptionOverridden(QueryHintOption<?> option) {
176 return getBackendHintSettings().containsKey(option);
177 }
178
179 /**
180 * Returns the value of the given hint option from the given hint collection, or null if not defined.
181 * @since 1.5
182 */
183 @SuppressWarnings("unchecked")
184 public <HintValue> HintValue getValueOrNull(QueryHintOption<HintValue> option) {
185 return (HintValue) getBackendHintSettings().get(option);
186 }
187
188 /**
189 * Returns the value of the given hint option from the given hint collection, or the default value if not defined.
190 * Intended to be called by backends to find out the definitive value that should be considered.
191 * @since 1.5
192 */
193 public <HintValue> HintValue getValueOrDefault(QueryHintOption<HintValue> option) {
194 return option.getValueOrDefault(this);
195 }
196
197 @Override
198 public int hashCode() {
199 return Objects.hash(backendHintSettings, queryBackendFactory, requirement);
200 }
201
202 @Override
203 public boolean equals(Object obj) {
204 if (this == obj)
205 return true;
206 if (obj == null)
207 return false;
208 if (getClass() != obj.getClass())
209 return false;
210 QueryEvaluationHint other = (QueryEvaluationHint) obj;
211 return Objects.equals(backendHintSettings, other.backendHintSettings)
212 &&
213 Objects.equals(queryBackendFactory, other.queryBackendFactory)
214 &&
215 Objects.equals(requirement, other.requirement)
216 ;
217 }
218
219 @Override
220 public String toString() {
221 StringBuilder sb = new StringBuilder();
222
223 if (getQueryBackendFactory() != null)
224 sb.append("backend: ").append(getQueryBackendFactory().getBackendClass().getSimpleName());
225 if (! backendHintSettings.isEmpty()) {
226 sb.append("hints: ");
227 if(backendHintSettings instanceof AbstractMap){
228 sb.append(backendHintSettings.toString());
229 } else {
230 // we have to iterate on the contents
231
232 String joinedHintMap = backendHintSettings.entrySet().stream()
233 .map(setting -> setting.getKey() + "=" + setting.getValue()).collect(Collectors.joining(", "));
234 sb.append('{').append(joinedHintMap).append('}');
235 }
236 }
237
238 final String result = sb.toString();
239 return result.isEmpty() ? "defaults" : result;
240 }
241}