diff options
Diffstat (limited to 'subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/ViatraQueryEngineOptions.java')
-rw-r--r-- | subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/ViatraQueryEngineOptions.java | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/ViatraQueryEngineOptions.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/ViatraQueryEngineOptions.java new file mode 100644 index 00000000..15bf1f91 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/ViatraQueryEngineOptions.java | |||
@@ -0,0 +1,293 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Balázs Grill, Zoltan Ujhelyi, IncQuery Labs 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.api; | ||
10 | |||
11 | |||
12 | import java.util.Objects; | ||
13 | import java.util.ServiceLoader; | ||
14 | |||
15 | import tools.refinery.viatra.runtime.matchers.backend.IQueryBackendFactory; | ||
16 | import tools.refinery.viatra.runtime.matchers.backend.IQueryBackendFactoryProvider; | ||
17 | import tools.refinery.viatra.runtime.matchers.backend.QueryEvaluationHint; | ||
18 | import tools.refinery.viatra.runtime.matchers.util.Preconditions; | ||
19 | |||
20 | /** | ||
21 | * This class is intended to provide options to a created {@link ViatraQueryEngine} instance. The {@link #DEFAULT} | ||
22 | * instance represents the configuration that is selected when no explicit options are provided by the user. To create | ||
23 | * new configurations, use the static builder methods {@link #defineOptions()} (starts with empty options) or | ||
24 | * {@link #copyOptions(ViatraQueryEngineOptions)} (starts with all options from an existing configuration). | ||
25 | * | ||
26 | * @author Balázs Grill, Zoltan Ujhelyi | ||
27 | * @since 1.4 | ||
28 | * | ||
29 | */ | ||
30 | public final class ViatraQueryEngineOptions { | ||
31 | |||
32 | private static boolean areSystemDefaultsCalculated = false; | ||
33 | private static IQueryBackendFactory systemDefaultBackendFactory; | ||
34 | private static IQueryBackendFactory systemDefaultCachingBackendFactory; | ||
35 | private static IQueryBackendFactory systemDefaultSearchBackendFactory; | ||
36 | |||
37 | /** | ||
38 | * @since 2.0 | ||
39 | */ | ||
40 | public static void setSystemDefaultBackends(IQueryBackendFactory systemDefaultBackendFactory, | ||
41 | IQueryBackendFactory systemDefaultCachingBackendFactory, | ||
42 | IQueryBackendFactory systemDefaultSearchBackendFactory) { | ||
43 | areSystemDefaultsCalculated = true; | ||
44 | ViatraQueryEngineOptions.systemDefaultBackendFactory = systemDefaultBackendFactory; | ||
45 | ViatraQueryEngineOptions.systemDefaultCachingBackendFactory = systemDefaultCachingBackendFactory; | ||
46 | ViatraQueryEngineOptions.systemDefaultSearchBackendFactory = systemDefaultSearchBackendFactory; | ||
47 | } | ||
48 | |||
49 | /** | ||
50 | * If {@link #setSystemDefaultBackends(IQueryBackendFactory, IQueryBackendFactory, IQueryBackendFactory)} is not | ||
51 | * called, this method is responsible of finding the corresponding backends on the classpath using Java Service | ||
52 | * loaders. | ||
53 | */ | ||
54 | private static void calculateSystemDefaultBackends() { | ||
55 | for (IQueryBackendFactoryProvider provider : ServiceLoader.load(IQueryBackendFactoryProvider.class)) { | ||
56 | if (provider.isSystemDefaultEngine()) { | ||
57 | systemDefaultBackendFactory = provider.getFactory(); | ||
58 | } | ||
59 | if (provider.isSystemDefaultCachingBackend()) { | ||
60 | systemDefaultCachingBackendFactory = provider.getFactory(); | ||
61 | } | ||
62 | if (provider.isSystemDefaultSearchBackend()) { | ||
63 | systemDefaultSearchBackendFactory = provider.getFactory(); | ||
64 | } | ||
65 | } | ||
66 | areSystemDefaultsCalculated = true; | ||
67 | } | ||
68 | |||
69 | private static IQueryBackendFactory getSystemDefaultBackend() { | ||
70 | if (!areSystemDefaultsCalculated) { | ||
71 | calculateSystemDefaultBackends(); | ||
72 | } | ||
73 | return Objects.requireNonNull(systemDefaultBackendFactory, "System default backend not found"); | ||
74 | } | ||
75 | |||
76 | private static IQueryBackendFactory getSystemDefaultCachingBackend() { | ||
77 | if (!areSystemDefaultsCalculated) { | ||
78 | calculateSystemDefaultBackends(); | ||
79 | } | ||
80 | return Objects.requireNonNull(systemDefaultCachingBackendFactory, "System default caching backend not found"); | ||
81 | } | ||
82 | |||
83 | private static IQueryBackendFactory getSystemDefaultSearchBackend() { | ||
84 | if (!areSystemDefaultsCalculated) { | ||
85 | calculateSystemDefaultBackends(); | ||
86 | } | ||
87 | return Objects.requireNonNull(systemDefaultSearchBackendFactory, "System default search backend not found"); | ||
88 | } | ||
89 | |||
90 | private final QueryEvaluationHint engineDefaultHints; | ||
91 | |||
92 | private final IQueryBackendFactory defaultCachingBackendFactory; | ||
93 | private final IQueryBackendFactory defaultSearchBackendFactory; | ||
94 | |||
95 | /** The default engine options; if options are not defined, this version will be used. */ | ||
96 | private static ViatraQueryEngineOptions DEFAULT; | ||
97 | |||
98 | /** | ||
99 | * @since 2.0 | ||
100 | */ | ||
101 | public static final ViatraQueryEngineOptions getDefault() { | ||
102 | if (DEFAULT == null) { | ||
103 | DEFAULT = new Builder().build(); | ||
104 | } | ||
105 | return DEFAULT; | ||
106 | } | ||
107 | |||
108 | public static final class Builder { | ||
109 | private QueryEvaluationHint engineDefaultHints; | ||
110 | |||
111 | private IQueryBackendFactory defaultBackendFactory; | ||
112 | private IQueryBackendFactory defaultCachingBackendFactory; | ||
113 | private IQueryBackendFactory defaultSearchBackendFactory; | ||
114 | |||
115 | public Builder() { | ||
116 | |||
117 | } | ||
118 | |||
119 | public Builder(ViatraQueryEngineOptions from) { | ||
120 | this.engineDefaultHints = from.engineDefaultHints; | ||
121 | this.defaultBackendFactory = engineDefaultHints.getQueryBackendFactory(); | ||
122 | this.defaultCachingBackendFactory = from.defaultCachingBackendFactory; | ||
123 | this.defaultSearchBackendFactory = from.defaultSearchBackendFactory; | ||
124 | } | ||
125 | |||
126 | /** | ||
127 | * Note that the backend factory in the hint is overridden by a factory added with | ||
128 | * {@link #withDefaultBackend(IQueryBackendFactory)}. | ||
129 | */ | ||
130 | public Builder withDefaultHint(QueryEvaluationHint engineDefaultHints) { | ||
131 | this.engineDefaultHints = engineDefaultHints; | ||
132 | return this; | ||
133 | } | ||
134 | |||
135 | /** | ||
136 | * Note that this backend factory overrides the factory defined by the hint added by | ||
137 | * {@link #withDefaultHint(QueryEvaluationHint)}. | ||
138 | */ | ||
139 | public Builder withDefaultBackend(IQueryBackendFactory defaultBackendFactory) { | ||
140 | this.defaultBackendFactory = defaultBackendFactory; | ||
141 | return this; | ||
142 | } | ||
143 | |||
144 | /** | ||
145 | * @since 2.0 | ||
146 | */ | ||
147 | public Builder withDefaultSearchBackend(IQueryBackendFactory defaultSearchBackendFactory) { | ||
148 | Preconditions.checkArgument(!defaultSearchBackendFactory.isCaching(), "%s is not a search backend", defaultSearchBackendFactory.getClass()); | ||
149 | this.defaultSearchBackendFactory = defaultSearchBackendFactory; | ||
150 | return this; | ||
151 | } | ||
152 | |||
153 | public Builder withDefaultCachingBackend(IQueryBackendFactory defaultCachingBackendFactory) { | ||
154 | Preconditions.checkArgument(defaultCachingBackendFactory.isCaching(), "%s is not a caching backend", defaultCachingBackendFactory.getClass()); | ||
155 | this.defaultCachingBackendFactory = defaultCachingBackendFactory; | ||
156 | return this; | ||
157 | } | ||
158 | |||
159 | public ViatraQueryEngineOptions build() { | ||
160 | IQueryBackendFactory defaultFactory = getDefaultBackend(); | ||
161 | QueryEvaluationHint hint = getEngineDefaultHints(defaultFactory); | ||
162 | return new ViatraQueryEngineOptions(hint, getDefaultCachingBackend(), getDefaultSearchBackend()); | ||
163 | } | ||
164 | |||
165 | private IQueryBackendFactory getDefaultBackend() { | ||
166 | if (defaultBackendFactory != null){ | ||
167 | return defaultBackendFactory; | ||
168 | } else if (engineDefaultHints != null) { | ||
169 | return engineDefaultHints.getQueryBackendFactory(); | ||
170 | } else { | ||
171 | return getSystemDefaultBackend(); | ||
172 | } | ||
173 | } | ||
174 | |||
175 | private IQueryBackendFactory getDefaultCachingBackend() { | ||
176 | if (defaultCachingBackendFactory != null) { | ||
177 | return defaultCachingBackendFactory; | ||
178 | } else if (defaultBackendFactory != null && defaultBackendFactory.isCaching()) { | ||
179 | return defaultBackendFactory; | ||
180 | } else { | ||
181 | return getSystemDefaultCachingBackend(); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | private IQueryBackendFactory getDefaultSearchBackend() { | ||
186 | if (defaultSearchBackendFactory != null) { | ||
187 | return defaultSearchBackendFactory; | ||
188 | } else if (defaultBackendFactory != null && !defaultBackendFactory.isCaching()) { | ||
189 | return defaultBackendFactory; | ||
190 | } else { | ||
191 | return getSystemDefaultSearchBackend(); | ||
192 | } | ||
193 | } | ||
194 | |||
195 | private QueryEvaluationHint getEngineDefaultHints(IQueryBackendFactory defaultFactory) { | ||
196 | if (engineDefaultHints != null){ | ||
197 | return engineDefaultHints.overrideBy(new QueryEvaluationHint(null, defaultFactory)); | ||
198 | } else { | ||
199 | return new QueryEvaluationHint(null, defaultFactory); | ||
200 | } | ||
201 | } | ||
202 | } | ||
203 | |||
204 | /** | ||
205 | * Initializes an option builder with no previously set options. | ||
206 | */ | ||
207 | public static Builder defineOptions() { | ||
208 | return new Builder(); | ||
209 | } | ||
210 | |||
211 | /** | ||
212 | * Initializes an option builder with settings from an existing configuration. | ||
213 | */ | ||
214 | public static Builder copyOptions(ViatraQueryEngineOptions options) { | ||
215 | return new Builder(options); | ||
216 | } | ||
217 | |||
218 | private ViatraQueryEngineOptions(QueryEvaluationHint engineDefaultHints, | ||
219 | IQueryBackendFactory defaultCachingBackendFactory, IQueryBackendFactory defaultSearchBackendFactory) { | ||
220 | this.engineDefaultHints = engineDefaultHints; | ||
221 | this.defaultCachingBackendFactory = defaultCachingBackendFactory; | ||
222 | this.defaultSearchBackendFactory = defaultSearchBackendFactory; | ||
223 | } | ||
224 | |||
225 | public QueryEvaluationHint getEngineDefaultHints() { | ||
226 | return engineDefaultHints; | ||
227 | } | ||
228 | |||
229 | /** | ||
230 | * Returns the configured default backend | ||
231 | * | ||
232 | * @return the defaultBackendFactory | ||
233 | */ | ||
234 | public IQueryBackendFactory getDefaultBackendFactory() { | ||
235 | switch (engineDefaultHints.getQueryBackendRequirementType()) { | ||
236 | case DEFAULT_CACHING: | ||
237 | return ViatraQueryEngineOptions.getSystemDefaultCachingBackend(); | ||
238 | case DEFAULT_SEARCH: | ||
239 | return ViatraQueryEngineOptions.getSystemDefaultCachingBackend(); | ||
240 | case SPECIFIC: | ||
241 | return engineDefaultHints.getQueryBackendFactory(); | ||
242 | case UNSPECIFIED: | ||
243 | default: | ||
244 | return ViatraQueryEngineOptions.getSystemDefaultBackend(); | ||
245 | } | ||
246 | } | ||
247 | |||
248 | /** | ||
249 | * Returns the configured default caching backend. If the default backend caches matches, it is usually expected, but | ||
250 | * not mandatory for the two default backends to be the same. | ||
251 | */ | ||
252 | public IQueryBackendFactory getDefaultCachingBackendFactory() { | ||
253 | return defaultCachingBackendFactory; | ||
254 | } | ||
255 | |||
256 | /** | ||
257 | * Returns the configured default search-based backend. If the default backend is search-based, it is usually expected, but | ||
258 | * not mandatory for the two default backends to be the same. | ||
259 | * @since 2.0 | ||
260 | */ | ||
261 | public IQueryBackendFactory getDefaultSearchBackendFactory() { | ||
262 | return defaultSearchBackendFactory; | ||
263 | } | ||
264 | |||
265 | @Override | ||
266 | public String toString() { | ||
267 | // TODO defaultCachingBackendFactory is ignored | ||
268 | if(Objects.equals(engineDefaultHints, DEFAULT.engineDefaultHints)) | ||
269 | return "defaults"; | ||
270 | else | ||
271 | return engineDefaultHints.toString(); | ||
272 | } | ||
273 | |||
274 | /** | ||
275 | * @since 2.0 | ||
276 | */ | ||
277 | public IQueryBackendFactory getQueryBackendFactory(QueryEvaluationHint hint) { | ||
278 | if (hint == null) { | ||
279 | return getDefaultBackendFactory(); | ||
280 | } | ||
281 | |||
282 | switch (hint.getQueryBackendRequirementType()) { | ||
283 | case DEFAULT_CACHING: | ||
284 | return getDefaultCachingBackendFactory(); | ||
285 | case DEFAULT_SEARCH: | ||
286 | return getDefaultSearchBackendFactory(); | ||
287 | case SPECIFIC: | ||
288 | return hint.getQueryBackendFactory(); | ||
289 | default: | ||
290 | return getDefaultBackendFactory(); | ||
291 | } | ||
292 | } | ||
293 | } | ||