diff options
author | 2023-08-19 03:00:23 +0200 | |
---|---|---|
committer | 2023-08-19 03:00:23 +0200 | |
commit | fc7e3dc61a2ac8de32914af331c1144e4fa843e6 (patch) | |
tree | f17f58c9a14700e76c4b54b242c0bca061199e1f /subprojects/viatra-runtime/src/main | |
parent | chore: import VIATRA source (diff) | |
download | refinery-fc7e3dc61a2ac8de32914af331c1144e4fa843e6.tar.gz refinery-fc7e3dc61a2ac8de32914af331c1144e4fa843e6.tar.zst refinery-fc7e3dc61a2ac8de32914af331c1144e4fa843e6.zip |
refactor: remove unused VIATRA code
We don't need Eclipse platform support, table-based scopes, and EMF support.
Diffstat (limited to 'subprojects/viatra-runtime/src/main')
64 files changed, 145 insertions, 5822 deletions
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/IExtensions.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/IExtensions.java deleted file mode 100644 index d5e0d51f..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/IExtensions.java +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2004-2010 Gabor Bergmann, 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 | *******************************************************************************/ | ||
9 | |||
10 | package tools.refinery.viatra.runtime; | ||
11 | |||
12 | /** | ||
13 | * Interface for storing string constants related to VIATRA Query's extension points. | ||
14 | * | ||
15 | * @author Istvan Rath | ||
16 | * | ||
17 | */ | ||
18 | public interface IExtensions { | ||
19 | |||
20 | public static final String QUERY_SPECIFICATION_EXTENSION_POINT_ID = ViatraQueryRuntimePlugin.PLUGIN_ID + ".queryspecification"; | ||
21 | |||
22 | public static final String INJECTOREXTENSIONID = ViatraQueryRuntimePlugin.PLUGIN_ID + ".injectorprovider"; | ||
23 | |||
24 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/ViatraQueryRuntimePlugin.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/ViatraQueryRuntimePlugin.java deleted file mode 100644 index 5fbcdad0..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/ViatraQueryRuntimePlugin.java +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
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 | package tools.refinery.viatra.runtime; | ||
10 | |||
11 | import org.eclipse.core.runtime.Plugin; | ||
12 | import tools.refinery.viatra.runtime.internal.ExtensionBasedSurrogateQueryLoader; | ||
13 | import tools.refinery.viatra.runtime.internal.ExtensionBasedSystemDefaultBackendLoader; | ||
14 | import tools.refinery.viatra.runtime.registry.ExtensionBasedQuerySpecificationLoader; | ||
15 | import org.osgi.framework.BundleContext; | ||
16 | |||
17 | /** | ||
18 | * The activator class controls the plug-in life cycle | ||
19 | */ | ||
20 | public class ViatraQueryRuntimePlugin extends Plugin { | ||
21 | |||
22 | public static final String PLUGIN_ID = "tools.refinery.viatra.runtime"; | ||
23 | |||
24 | @Override | ||
25 | public void start(BundleContext context) throws Exception { | ||
26 | super.start(context); | ||
27 | ExtensionBasedSurrogateQueryLoader.instance().loadKnownSurrogateQueriesIntoRegistry(); | ||
28 | ExtensionBasedQuerySpecificationLoader.getInstance().loadRegisteredQuerySpecificationsIntoRegistry(); | ||
29 | ExtensionBasedSystemDefaultBackendLoader.instance().loadKnownBackends(); | ||
30 | } | ||
31 | |||
32 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/AdvancedViatraQueryEngine.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/AdvancedViatraQueryEngine.java index 21e7dfa3..32a3430d 100644 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/AdvancedViatraQueryEngine.java +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/AdvancedViatraQueryEngine.java | |||
@@ -3,32 +3,27 @@ | |||
3 | * This program and the accompanying materials are made available under the | 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 | 4 | * terms of the Eclipse Public License v. 2.0 which is available at |
5 | * http://www.eclipse.org/legal/epl-v20.html. | 5 | * http://www.eclipse.org/legal/epl-v20.html. |
6 | * | 6 | * |
7 | * SPDX-License-Identifier: EPL-2.0 | 7 | * SPDX-License-Identifier: EPL-2.0 |
8 | *******************************************************************************/ | 8 | *******************************************************************************/ |
9 | package tools.refinery.viatra.runtime.api; | 9 | package tools.refinery.viatra.runtime.api; |
10 | 10 | ||
11 | import java.lang.reflect.InvocationTargetException; | ||
12 | import java.util.concurrent.Callable; | ||
13 | |||
14 | import tools.refinery.viatra.runtime.api.scope.QueryScope; | 11 | import tools.refinery.viatra.runtime.api.scope.QueryScope; |
15 | import tools.refinery.viatra.runtime.emf.EMFScope; | ||
16 | import tools.refinery.viatra.runtime.internal.apiimpl.ViatraQueryEngineImpl; | 12 | import tools.refinery.viatra.runtime.internal.apiimpl.ViatraQueryEngineImpl; |
17 | import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException; | 13 | import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException; |
18 | import tools.refinery.viatra.runtime.matchers.backend.IMatcherCapability; | 14 | import tools.refinery.viatra.runtime.matchers.backend.*; |
19 | import tools.refinery.viatra.runtime.matchers.backend.IQueryBackend; | 15 | |
20 | import tools.refinery.viatra.runtime.matchers.backend.IQueryBackendFactory; | 16 | import java.lang.reflect.InvocationTargetException; |
21 | import tools.refinery.viatra.runtime.matchers.backend.IQueryResultProvider; | 17 | import java.util.concurrent.Callable; |
22 | import tools.refinery.viatra.runtime.matchers.backend.QueryEvaluationHint; | ||
23 | 18 | ||
24 | /** | 19 | /** |
25 | * Advanced interface to a VIATRA incremental evaluation engine. | 20 | * Advanced interface to a VIATRA incremental evaluation engine. |
26 | * | 21 | * |
27 | * <p> | 22 | * <p> |
28 | * You can create a new, private, unmanaged {@link AdvancedViatraQueryEngine} instance using | 23 | * You can create a new, private, unmanaged {@link AdvancedViatraQueryEngine} instance using |
29 | * {@link #createUnmanagedEngine(QueryScope)}. Additionally, you can access the advanced interface on any | 24 | * {@link #createUnmanagedEngine(QueryScope)}. Additionally, you can access the advanced interface on any |
30 | * {@link ViatraQueryEngine} by {@link AdvancedViatraQueryEngine#from(ViatraQueryEngine)}. | 25 | * {@link ViatraQueryEngine} by {@link AdvancedViatraQueryEngine#from(ViatraQueryEngine)}. |
31 | * | 26 | * |
32 | * <p> | 27 | * <p> |
33 | * While the default interface {@link ViatraQueryEngine}, is suitable for most users, this advanced interface provides more | 28 | * While the default interface {@link ViatraQueryEngine}, is suitable for most users, this advanced interface provides more |
34 | * control over the engine. The most important added functionality is the following: | 29 | * control over the engine. The most important added functionality is the following: |
@@ -45,29 +40,29 @@ import tools.refinery.viatra.runtime.matchers.backend.QueryEvaluationHint; | |||
45 | * register a callback using {@link #addLifecycleListener(ViatraQueryEngineLifecycleListener)} to learn when another client | 40 | * register a callback using {@link #addLifecycleListener(ViatraQueryEngineLifecycleListener)} to learn when another client |
46 | * has called the destructive methods {@link #dispose()} or {@link #wipe()}. | 41 | * has called the destructive methods {@link #dispose()} or {@link #wipe()}. |
47 | * </ul> | 42 | * </ul> |
48 | * | 43 | * |
49 | * @author Bergmann Gabor | 44 | * @author Bergmann Gabor |
50 | * @noextend This class is not intended to be subclassed by clients. | 45 | * @noextend This class is not intended to be subclassed by clients. |
51 | */ | 46 | */ |
52 | public abstract class AdvancedViatraQueryEngine extends ViatraQueryEngine { | 47 | public abstract class AdvancedViatraQueryEngine extends ViatraQueryEngine { |
53 | 48 | ||
54 | /** | 49 | /** |
55 | * Creates a new unmanaged VIATRA Query engine to evaluate queries over a given scope specified by an {@link QueryScope}. | 50 | * Creates a new unmanaged VIATRA Query engine to evaluate queries over a given scope specified by an {@link QueryScope}. |
56 | * | 51 | * |
57 | * <p> Repeated invocations will return different instances, so other clients are unable to independently access | 52 | * <p> Repeated invocations will return different instances, so other clients are unable to independently access |
58 | * and influence the returned engine. Note that unmanaged engines do not benefit from some performance improvements | 53 | * and influence the returned engine. Note that unmanaged engines do not benefit from some performance improvements |
59 | * that stem from sharing incrementally maintained indices and caches between multiple clients using the same managed | 54 | * that stem from sharing incrementally maintained indices and caches between multiple clients using the same managed |
60 | * engine instance. | 55 | * engine instance. |
61 | * | 56 | * |
62 | * <p> | 57 | * <p> |
63 | * Client is responsible for the lifecycle of the returned engine, hence the usage of the advanced interface | 58 | * Client is responsible for the lifecycle of the returned engine, hence the usage of the advanced interface |
64 | * {@link AdvancedViatraQueryEngine}. | 59 | * {@link AdvancedViatraQueryEngine}. |
65 | * | 60 | * |
66 | * <p> | 61 | * <p> |
67 | * The match set of any patterns will be incrementally refreshed upon updates from this scope. | 62 | * The match set of any patterns will be incrementally refreshed upon updates from this scope. |
68 | * | 63 | * |
69 | * @param scope | 64 | * @param scope |
70 | * the scope of query evaluation; the definition of the set of model elements that this engine is operates on. | 65 | * the scope of query evaluation; the definition of the set of model elements that this engine is operates on. |
71 | * Provide e.g. a {@link EMFScope} for evaluating queries on an EMF model. | 66 | * Provide e.g. a {@link EMFScope} for evaluating queries on an EMF model. |
72 | * @return the advanced interface to a newly created unmanaged engine | 67 | * @return the advanced interface to a newly created unmanaged engine |
73 | * @since 0.9 | 68 | * @since 0.9 |
@@ -75,24 +70,24 @@ public abstract class AdvancedViatraQueryEngine extends ViatraQueryEngine { | |||
75 | public static AdvancedViatraQueryEngine createUnmanagedEngine(QueryScope scope) { | 70 | public static AdvancedViatraQueryEngine createUnmanagedEngine(QueryScope scope) { |
76 | return new ViatraQueryEngineImpl(null, scope); | 71 | return new ViatraQueryEngineImpl(null, scope); |
77 | } | 72 | } |
78 | 73 | ||
79 | /** | 74 | /** |
80 | * Creates a new unmanaged VIATRA Query engine to evaluate queries over a given scope specified by an {@link QueryScope}. | 75 | * Creates a new unmanaged VIATRA Query engine to evaluate queries over a given scope specified by an {@link QueryScope}. |
81 | * | 76 | * |
82 | * <p> Repeated invocations will return different instances, so other clients are unable to independently access | 77 | * <p> Repeated invocations will return different instances, so other clients are unable to independently access |
83 | * and influence the returned engine. Note that unmanaged engines do not benefit from some performance improvements | 78 | * and influence the returned engine. Note that unmanaged engines do not benefit from some performance improvements |
84 | * that stem from sharing incrementally maintained indices and caches between multiple clients using the same managed | 79 | * that stem from sharing incrementally maintained indices and caches between multiple clients using the same managed |
85 | * engine instance. | 80 | * engine instance. |
86 | * | 81 | * |
87 | * <p> | 82 | * <p> |
88 | * Client is responsible for the lifecycle of the returned engine, hence the usage of the advanced interface | 83 | * Client is responsible for the lifecycle of the returned engine, hence the usage of the advanced interface |
89 | * {@link AdvancedViatraQueryEngine}. | 84 | * {@link AdvancedViatraQueryEngine}. |
90 | * | 85 | * |
91 | * <p> | 86 | * <p> |
92 | * The match set of any patterns will be incrementally refreshed upon updates from this scope. | 87 | * The match set of any patterns will be incrementally refreshed upon updates from this scope. |
93 | * | 88 | * |
94 | * @param scope | 89 | * @param scope |
95 | * the scope of query evaluation; the definition of the set of model elements that this engine is operates on. | 90 | * the scope of query evaluation; the definition of the set of model elements that this engine is operates on. |
96 | * Provide e.g. a {@link EMFScope} for evaluating queries on an EMF model. | 91 | * Provide e.g. a {@link EMFScope} for evaluating queries on an EMF model. |
97 | * @return the advanced interface to a newly created unmanaged engine | 92 | * @return the advanced interface to a newly created unmanaged engine |
98 | * @since 1.4 | 93 | * @since 1.4 |
@@ -103,11 +98,11 @@ public abstract class AdvancedViatraQueryEngine extends ViatraQueryEngine { | |||
103 | 98 | ||
104 | /** | 99 | /** |
105 | * Provides access to a given existing engine through the advanced interface. | 100 | * Provides access to a given existing engine through the advanced interface. |
106 | * | 101 | * |
107 | * <p> | 102 | * <p> |
108 | * Caveat: if the referenced engine is managed (i.e. created via {@link ViatraQueryEngine#on(QueryScope)}), the advanced | 103 | * Caveat: if the referenced engine is managed (i.e. created via {@link ViatraQueryEngine#on(QueryScope)}), the advanced |
109 | * methods {@link #dispose()} and {@link #wipe()} will not be allowed. | 104 | * methods {@link #dispose()} and {@link #wipe()} will not be allowed. |
110 | * | 105 | * |
111 | * @param engine | 106 | * @param engine |
112 | * the engine to access using the advanced interface | 107 | * the engine to access using the advanced interface |
113 | * @return a reference to the same engine conforming to the advanced interface | 108 | * @return a reference to the same engine conforming to the advanced interface |
@@ -118,7 +113,7 @@ public abstract class AdvancedViatraQueryEngine extends ViatraQueryEngine { | |||
118 | 113 | ||
119 | /** | 114 | /** |
120 | * Add an engine lifecycle listener to this engine instance. | 115 | * Add an engine lifecycle listener to this engine instance. |
121 | * | 116 | * |
122 | * @param listener | 117 | * @param listener |
123 | * the {@link ViatraQueryEngineLifecycleListener} that should listen to lifecycle events from this engine | 118 | * the {@link ViatraQueryEngineLifecycleListener} that should listen to lifecycle events from this engine |
124 | */ | 119 | */ |
@@ -126,7 +121,7 @@ public abstract class AdvancedViatraQueryEngine extends ViatraQueryEngine { | |||
126 | 121 | ||
127 | /** | 122 | /** |
128 | * Remove an existing lifecycle listener from this engine instance. | 123 | * Remove an existing lifecycle listener from this engine instance. |
129 | * | 124 | * |
130 | * @param listener | 125 | * @param listener |
131 | * the {@link ViatraQueryEngineLifecycleListener} that should not listen to lifecycle events from this | 126 | * the {@link ViatraQueryEngineLifecycleListener} that should not listen to lifecycle events from this |
132 | * engine anymore | 127 | * engine anymore |
@@ -136,7 +131,7 @@ public abstract class AdvancedViatraQueryEngine extends ViatraQueryEngine { | |||
136 | /** | 131 | /** |
137 | * Add an model update event listener to this engine instance (that fires its callbacks according to its | 132 | * Add an model update event listener to this engine instance (that fires its callbacks according to its |
138 | * notification level). | 133 | * notification level). |
139 | * | 134 | * |
140 | * @param listener | 135 | * @param listener |
141 | * the {@link ViatraQueryModelUpdateListener} that should listen to model update events from this engine. | 136 | * the {@link ViatraQueryModelUpdateListener} that should listen to model update events from this engine. |
142 | */ | 137 | */ |
@@ -144,7 +139,7 @@ public abstract class AdvancedViatraQueryEngine extends ViatraQueryEngine { | |||
144 | 139 | ||
145 | /** | 140 | /** |
146 | * Remove an existing model update event listener to this engine instance. | 141 | * Remove an existing model update event listener to this engine instance. |
147 | * | 142 | * |
148 | * @param listener | 143 | * @param listener |
149 | * the {@link ViatraQueryModelUpdateListener} that should not listen to model update events from this engine | 144 | * the {@link ViatraQueryModelUpdateListener} that should not listen to model update events from this engine |
150 | * anymore | 145 | * anymore |
@@ -153,20 +148,20 @@ public abstract class AdvancedViatraQueryEngine extends ViatraQueryEngine { | |||
153 | 148 | ||
154 | /** | 149 | /** |
155 | * Registers low-level callbacks for match appearance and disappearance on this pattern matcher. | 150 | * Registers low-level callbacks for match appearance and disappearance on this pattern matcher. |
156 | * | 151 | * |
157 | * <p> | 152 | * <p> |
158 | * <b>Caution: </b> This is a low-level callback that is invoked when the pattern matcher is not necessarily in a | 153 | * <b>Caution: </b> This is a low-level callback that is invoked when the pattern matcher is not necessarily in a |
159 | * consistent state yet. Importantly, no model modification permitted during the callback. Most users should use the | 154 | * consistent state yet. Importantly, no model modification permitted during the callback. Most users should use the |
160 | * databinding support ({@link org.eclipse.viatra.addon.databinding.runtime.api.ViatraObservables ViatraObservables}) or the event-driven API | 155 | * databinding support ({@link org.eclipse.viatra.addon.databinding.runtime.api.ViatraObservables ViatraObservables}) or the event-driven API |
161 | * ({@link org.eclipse.viatra.transformation.evm.api.EventDrivenVM EventDrivenVM}) instead. | 156 | * ({@link org.eclipse.viatra.transformation.evm.api.EventDrivenVM EventDrivenVM}) instead. |
162 | * | 157 | * |
163 | * <p> | 158 | * <p> |
164 | * Performance note: expected to be much more efficient than polling at {@link #addCallbackAfterUpdates(Runnable)}, | 159 | * Performance note: expected to be much more efficient than polling at {@link #addCallbackAfterUpdates(Runnable)}, |
165 | * but prone to "signal hazards", e.g. spurious match appearances that will disappear immediately afterwards. | 160 | * but prone to "signal hazards", e.g. spurious match appearances that will disappear immediately afterwards. |
166 | * | 161 | * |
167 | * <p> | 162 | * <p> |
168 | * The callback can be unregistered via {@link #removeCallbackOnMatchUpdate(IMatchUpdateListener)}. | 163 | * The callback can be unregistered via {@link #removeCallbackOnMatchUpdate(IMatchUpdateListener)}. |
169 | * | 164 | * |
170 | * @param fireNow | 165 | * @param fireNow |
171 | * if true, appearCallback will be immediately invoked on all current matches as a one-time effect. See | 166 | * if true, appearCallback will be immediately invoked on all current matches as a one-time effect. See |
172 | * also {@link ViatraQueryMatcher#forEachMatch(IMatchProcessor)}. | 167 | * also {@link ViatraQueryMatcher#forEachMatch(IMatchProcessor)}. |
@@ -180,7 +175,7 @@ public abstract class AdvancedViatraQueryEngine extends ViatraQueryEngine { | |||
180 | 175 | ||
181 | /** | 176 | /** |
182 | * Remove an existing match update event listener to this engine instance. | 177 | * Remove an existing match update event listener to this engine instance. |
183 | * | 178 | * |
184 | * @param matcher | 179 | * @param matcher |
185 | * the {@link ViatraQueryMatcher} for which this listener should not be active anymore | 180 | * the {@link ViatraQueryMatcher} for which this listener should not be active anymore |
186 | * @param listener | 181 | * @param listener |
@@ -189,15 +184,15 @@ public abstract class AdvancedViatraQueryEngine extends ViatraQueryEngine { | |||
189 | public abstract <Match extends IPatternMatch> void removeMatchUpdateListener(ViatraQueryMatcher<Match> matcher, | 184 | public abstract <Match extends IPatternMatch> void removeMatchUpdateListener(ViatraQueryMatcher<Match> matcher, |
190 | IMatchUpdateListener<? super Match> listener); | 185 | IMatchUpdateListener<? super Match> listener); |
191 | 186 | ||
192 | 187 | ||
193 | /** | 188 | /** |
194 | * Access a pattern matcher based on a {@link IQuerySpecification}, overriding some of the default query evaluation hints. | 189 | * Access a pattern matcher based on a {@link IQuerySpecification}, overriding some of the default query evaluation hints. |
195 | * Multiple calls may return the same matcher depending on the actual evaluation hints. | 190 | * Multiple calls may return the same matcher depending on the actual evaluation hints. |
196 | * | 191 | * |
197 | * <p> It is guaranteed that this method will always return a matcher instance which is functionally compatible | 192 | * <p> It is guaranteed that this method will always return a matcher instance which is functionally compatible |
198 | * with the requested functionality (see {@link IMatcherCapability}). | 193 | * with the requested functionality (see {@link IMatcherCapability}). |
199 | * Otherwise, the query evaluator is free to ignore any hints. | 194 | * Otherwise, the query evaluator is free to ignore any hints. |
200 | * | 195 | * |
201 | * <p> For stateful query backends (Rete), hints may be effective only the first time a matcher is created. | 196 | * <p> For stateful query backends (Rete), hints may be effective only the first time a matcher is created. |
202 | * @param querySpecification a {@link IQuerySpecification} that describes a VIATRA query | 197 | * @param querySpecification a {@link IQuerySpecification} that describes a VIATRA query |
203 | * @return a pattern matcher corresponding to the specification | 198 | * @return a pattern matcher corresponding to the specification |
@@ -206,20 +201,20 @@ public abstract class AdvancedViatraQueryEngine extends ViatraQueryEngine { | |||
206 | * @since 0.9 | 201 | * @since 0.9 |
207 | */ | 202 | */ |
208 | public abstract <Matcher extends ViatraQueryMatcher<? extends IPatternMatch>> Matcher getMatcher( | 203 | public abstract <Matcher extends ViatraQueryMatcher<? extends IPatternMatch>> Matcher getMatcher( |
209 | IQuerySpecification<Matcher> querySpecification, | 204 | IQuerySpecification<Matcher> querySpecification, |
210 | QueryEvaluationHint optionalEvaluationHints); | 205 | QueryEvaluationHint optionalEvaluationHints); |
211 | 206 | ||
212 | /** | 207 | /** |
213 | * Initializes matchers for a group of patterns as one step (optionally overriding some of the default query evaluation hints). | 208 | * Initializes matchers for a group of patterns as one step (optionally overriding some of the default query evaluation hints). |
214 | * If some of the pattern matchers are already | 209 | * If some of the pattern matchers are already |
215 | * constructed in the engine, no task is performed for them. | 210 | * constructed in the engine, no task is performed for them. |
216 | * | 211 | * |
217 | * <p> | 212 | * <p> |
218 | * This preparation step has the advantage that it prepares pattern matchers for an arbitrary number of patterns in a | 213 | * This preparation step has the advantage that it prepares pattern matchers for an arbitrary number of patterns in a |
219 | * single-pass traversal of the model. | 214 | * single-pass traversal of the model. |
220 | * This is typically more efficient than traversing the model each time an individual pattern matcher is initialized on demand. | 215 | * This is typically more efficient than traversing the model each time an individual pattern matcher is initialized on demand. |
221 | * The performance benefit only manifests itself if the engine is not in wildcard mode. | 216 | * The performance benefit only manifests itself if the engine is not in wildcard mode. |
222 | * | 217 | * |
223 | * @param queryGroup a {@link IQueryGroup} identifying a set of VIATRA queries | 218 | * @param queryGroup a {@link IQueryGroup} identifying a set of VIATRA queries |
224 | * @param optionalEvaluationHints additional / overriding options on query evaluation; passing null means default options associated with each query | 219 | * @param optionalEvaluationHints additional / overriding options on query evaluation; passing null means default options associated with each query |
225 | * @throws ViatraQueryRuntimeException | 220 | * @throws ViatraQueryRuntimeException |
@@ -227,23 +222,23 @@ public abstract class AdvancedViatraQueryEngine extends ViatraQueryEngine { | |||
227 | * @since 0.9 | 222 | * @since 0.9 |
228 | */ | 223 | */ |
229 | public abstract void prepareGroup(IQueryGroup queryGroup, QueryEvaluationHint optionalEvaluationHints); | 224 | public abstract void prepareGroup(IQueryGroup queryGroup, QueryEvaluationHint optionalEvaluationHints); |
230 | 225 | ||
231 | /** | 226 | /** |
232 | * Indicates whether the engine is managed, i.e. the default engine assigned to the given scope root by | 227 | * Indicates whether the engine is managed, i.e. the default engine assigned to the given scope root by |
233 | * {@link ViatraQueryEngine#on(QueryScope)}. | 228 | * {@link ViatraQueryEngine#on(QueryScope)}. |
234 | * | 229 | * |
235 | * <p> | 230 | * <p> |
236 | * If the engine is managed, there may be other clients using it, as all calls to | 231 | * If the engine is managed, there may be other clients using it, as all calls to |
237 | * {@link ViatraQueryEngine#on(QueryScope)} return the same managed engine instance for a given scope root. Therefore the | 232 | * {@link ViatraQueryEngine#on(QueryScope)} return the same managed engine instance for a given scope root. Therefore the |
238 | * destructive methods {@link #wipe()} and {@link #dispose()} are not allowed. | 233 | * destructive methods {@link #wipe()} and {@link #dispose()} are not allowed. |
239 | * | 234 | * |
240 | * <p> | 235 | * <p> |
241 | * On the other hand, if the engine is unmanaged (i.e. a private instance created using | 236 | * On the other hand, if the engine is unmanaged (i.e. a private instance created using |
242 | * {@link #createUnmanagedEngine(QueryScope)}), then {@link #wipe()} and {@link #dispose()} can be called. If you | 237 | * {@link #createUnmanagedEngine(QueryScope)}), then {@link #wipe()} and {@link #dispose()} can be called. If you |
243 | * explicitly share a private, unmanaged engine between multiple sites, register a callback using | 238 | * explicitly share a private, unmanaged engine between multiple sites, register a callback using |
244 | * {@link #addLifecycleListener(ViatraQueryEngineLifecycleListener)} to learn when another client has called these | 239 | * {@link #addLifecycleListener(ViatraQueryEngineLifecycleListener)} to learn when another client has called these |
245 | * destructive methods. | 240 | * destructive methods. |
246 | * | 241 | * |
247 | * @return true if the engine is managed, and therefore potentially shared with other clients querying the same EMF | 242 | * @return true if the engine is managed, and therefore potentially shared with other clients querying the same EMF |
248 | * model | 243 | * model |
249 | */ | 244 | */ |
@@ -252,11 +247,11 @@ public abstract class AdvancedViatraQueryEngine extends ViatraQueryEngine { | |||
252 | /** | 247 | /** |
253 | * Indicates whether the engine is in a tainted, inconsistent state due to some internal errors. If true, results | 248 | * Indicates whether the engine is in a tainted, inconsistent state due to some internal errors. If true, results |
254 | * are no longer reliable; engine should be disposed. | 249 | * are no longer reliable; engine should be disposed. |
255 | * | 250 | * |
256 | * <p> | 251 | * <p> |
257 | * The engine is in a tainted state if any of its internal processes report back a fatal error. The | 252 | * The engine is in a tainted state if any of its internal processes report back a fatal error. The |
258 | * {@link ViatraQueryEngineLifecycleListener} interface provides a callback method for entering the tainted state. | 253 | * {@link ViatraQueryEngineLifecycleListener} interface provides a callback method for entering the tainted state. |
259 | * | 254 | * |
260 | * @return the tainted state | 255 | * @return the tainted state |
261 | */ | 256 | */ |
262 | public abstract boolean isTainted(); | 257 | public abstract boolean isTainted(); |
@@ -265,7 +260,7 @@ public abstract class AdvancedViatraQueryEngine extends ViatraQueryEngine { | |||
265 | * Discards any pattern matcher caches and forgets known patterns. The base index built directly on the underlying | 260 | * Discards any pattern matcher caches and forgets known patterns. The base index built directly on the underlying |
266 | * EMF model, however, is kept in memory to allow reuse when new pattern matchers are built. Use this method if you | 261 | * EMF model, however, is kept in memory to allow reuse when new pattern matchers are built. Use this method if you |
267 | * have e.g. new versions of the same patterns, to be matched on the same model. | 262 | * have e.g. new versions of the same patterns, to be matched on the same model. |
268 | * | 263 | * |
269 | * <p> | 264 | * <p> |
270 | * Matcher objects will continue to return stale results. If no references are retained to the matchers, they can | 265 | * Matcher objects will continue to return stale results. If no references are retained to the matchers, they can |
271 | * eventually be GC'ed. | 266 | * eventually be GC'ed. |
@@ -275,7 +270,7 @@ public abstract class AdvancedViatraQueryEngine extends ViatraQueryEngine { | |||
275 | * If you explicitly share a private, unmanaged engine between multiple sites, register a callback using | 270 | * If you explicitly share a private, unmanaged engine between multiple sites, register a callback using |
276 | * {@link #addLifecycleListener(ViatraQueryEngineLifecycleListener)} to learn when another client has called this | 271 | * {@link #addLifecycleListener(ViatraQueryEngineLifecycleListener)} to learn when another client has called this |
277 | * destructive method. | 272 | * destructive method. |
278 | * | 273 | * |
279 | * @throws UnsupportedOperationException | 274 | * @throws UnsupportedOperationException |
280 | * if engine is managed | 275 | * if engine is managed |
281 | */ | 276 | */ |
@@ -295,12 +290,12 @@ public abstract class AdvancedViatraQueryEngine extends ViatraQueryEngine { | |||
295 | * If you explicitly share a private, unmanaged engine between multiple sites, register a callback using | 290 | * If you explicitly share a private, unmanaged engine between multiple sites, register a callback using |
296 | * {@link #addLifecycleListener(ViatraQueryEngineLifecycleListener)} to learn when another client has called this | 291 | * {@link #addLifecycleListener(ViatraQueryEngineLifecycleListener)} to learn when another client has called this |
297 | * destructive method. | 292 | * destructive method. |
298 | * | 293 | * |
299 | * @throws UnsupportedOperationException | 294 | * @throws UnsupportedOperationException |
300 | * if engine is managed | 295 | * if engine is managed |
301 | */ | 296 | */ |
302 | public abstract void dispose(); | 297 | public abstract void dispose(); |
303 | 298 | ||
304 | /** | 299 | /** |
305 | * Provides access to the selected query backend component of the VIATRA Query engine. | 300 | * Provides access to the selected query backend component of the VIATRA Query engine. |
306 | * @noreference for internal use only | 301 | * @noreference for internal use only |
@@ -316,45 +311,45 @@ public abstract class AdvancedViatraQueryEngine extends ViatraQueryEngine { | |||
316 | * @since 1.4 | 311 | * @since 1.4 |
317 | */ | 312 | */ |
318 | public abstract <Matcher extends ViatraQueryMatcher<? extends IPatternMatch>> Matcher getExistingMatcher(IQuerySpecification<Matcher> querySpecification, QueryEvaluationHint optionalOverrideHints); | 313 | public abstract <Matcher extends ViatraQueryMatcher<? extends IPatternMatch>> Matcher getExistingMatcher(IQuerySpecification<Matcher> querySpecification, QueryEvaluationHint optionalOverrideHints); |
319 | 314 | ||
320 | /** | 315 | /** |
321 | * Returns the immutable {@link ViatraQueryEngineOptions} of the engine. | 316 | * Returns the immutable {@link ViatraQueryEngineOptions} of the engine. |
322 | * | 317 | * |
323 | * @return the engine options | 318 | * @return the engine options |
324 | * @since 1.4 | 319 | * @since 1.4 |
325 | */ | 320 | */ |
326 | public abstract ViatraQueryEngineOptions getEngineOptions(); | 321 | public abstract ViatraQueryEngineOptions getEngineOptions(); |
327 | 322 | ||
328 | /** | 323 | /** |
329 | * Return the underlying result provider for the given matcher. | 324 | * Return the underlying result provider for the given matcher. |
330 | * | 325 | * |
331 | * @beta This method may change in future versions | 326 | * @beta This method may change in future versions |
332 | * @since 1.4 | 327 | * @since 1.4 |
333 | * @noreference This method is considered internal API | 328 | * @noreference This method is considered internal API |
334 | */ | 329 | */ |
335 | public abstract IQueryResultProvider getResultProviderOfMatcher(ViatraQueryMatcher<? extends IPatternMatch> matcher); | 330 | public abstract IQueryResultProvider getResultProviderOfMatcher(ViatraQueryMatcher<? extends IPatternMatch> matcher); |
336 | 331 | ||
337 | /** | 332 | /** |
338 | * The given callable will be executed, and all update propagation in stateful query backends | 333 | * The given callable will be executed, and all update propagation in stateful query backends |
339 | * will be delayed until the execution is done. Within the callback, these backends will provide stale results. | 334 | * will be delayed until the execution is done. Within the callback, these backends will provide stale results. |
340 | * | 335 | * |
341 | * <p> It is optional for a {@link IQueryBackend} to support the delaying of update propagation; stateless backends will display up-to-date results. | 336 | * <p> It is optional for a {@link IQueryBackend} to support the delaying of update propagation; stateless backends will display up-to-date results. |
342 | * In this case, the given callable shall be executed, and the update propagation shall happen just like in non-delayed execution. | 337 | * In this case, the given callable shall be executed, and the update propagation shall happen just like in non-delayed execution. |
343 | * | 338 | * |
344 | * <p> Example: in the Rete network, no messages will be propagated until the given callable is executed. | 339 | * <p> Example: in the Rete network, no messages will be propagated until the given callable is executed. |
345 | * After the execution of the callable, all accumulated messages will be delivered. | 340 | * After the execution of the callable, all accumulated messages will be delivered. |
346 | * | 341 | * |
347 | * <p> The purpose of this method is that stateful query backends may save work when multiple model modifications are performed within the callback that partially cancel each other out. | 342 | * <p> The purpose of this method is that stateful query backends may save work when multiple model modifications are performed within the callback that partially cancel each other out. |
348 | * | 343 | * |
349 | * @param callable the callable to be executed | 344 | * @param callable the callable to be executed |
350 | * @return the result of the callable | 345 | * @return the result of the callable |
351 | * @since 1.6 | 346 | * @since 1.6 |
352 | */ | 347 | */ |
353 | public abstract <V> V delayUpdatePropagation(Callable<V> callable) throws InvocationTargetException; | 348 | public abstract <V> V delayUpdatePropagation(Callable<V> callable) throws InvocationTargetException; |
354 | 349 | ||
355 | /** | 350 | /** |
356 | * Returns true if the update propagation in this engine is currently delayed, false otherwise. | 351 | * Returns true if the update propagation in this engine is currently delayed, false otherwise. |
357 | * | 352 | * |
358 | * @see {@link #delayUpdatePropagation(Callable)} | 353 | * @see {@link #delayUpdatePropagation(Callable)} |
359 | * @since 1.6 | 354 | * @since 1.6 |
360 | */ | 355 | */ |
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/IModelConnectorTypeEnum.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/IModelConnectorTypeEnum.java deleted file mode 100644 index e672a6e2..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/IModelConnectorTypeEnum.java +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2012, Andras Okros, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.api; | ||
10 | |||
11 | /** | ||
12 | * This enum represents the possible notifier types which a model input should provide for the ui. | ||
13 | */ | ||
14 | public enum IModelConnectorTypeEnum { | ||
15 | |||
16 | RESOURCESET, RESOURCE; | ||
17 | |||
18 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/IQuerySpecification.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/IQuerySpecification.java index 9b84b031..326d2202 100644 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/IQuerySpecification.java +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/IQuerySpecification.java | |||
@@ -3,14 +3,13 @@ | |||
3 | * This program and the accompanying materials are made available under the | 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 | 4 | * terms of the Eclipse Public License v. 2.0 which is available at |
5 | * http://www.eclipse.org/legal/epl-v20.html. | 5 | * http://www.eclipse.org/legal/epl-v20.html. |
6 | * | 6 | * |
7 | * SPDX-License-Identifier: EPL-2.0 | 7 | * SPDX-License-Identifier: EPL-2.0 |
8 | *******************************************************************************/ | 8 | *******************************************************************************/ |
9 | 9 | ||
10 | package tools.refinery.viatra.runtime.api; | 10 | package tools.refinery.viatra.runtime.api; |
11 | 11 | ||
12 | import tools.refinery.viatra.runtime.api.scope.QueryScope; | 12 | import tools.refinery.viatra.runtime.api.scope.QueryScope; |
13 | import tools.refinery.viatra.runtime.emf.EMFScope; | ||
14 | import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException; | 13 | import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException; |
15 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | 14 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; |
16 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQueryHeader; | 15 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQueryHeader; |
@@ -18,8 +17,8 @@ import tools.refinery.viatra.runtime.matchers.psystem.queries.PQueryHeader; | |||
18 | /** | 17 | /** |
19 | * API interface for a VIATRA query specification. Each query is associated with a pattern. Methods instantiate a matcher | 18 | * API interface for a VIATRA query specification. Each query is associated with a pattern. Methods instantiate a matcher |
20 | * of the pattern with various parameters. | 19 | * of the pattern with various parameters. |
21 | * | 20 | * |
22 | * <p> As of 0.9.0, some internal details (mostly relevant for query evaluator backends) have been moved to {@link #getInternalQueryRepresentation()}. | 21 | * <p> As of 0.9.0, some internal details (mostly relevant for query evaluator backends) have been moved to {@link #getInternalQueryRepresentation()}. |
23 | * | 22 | * |
24 | * @author Bergmann Gábor | 23 | * @author Bergmann Gábor |
25 | * | 24 | * |
@@ -39,49 +38,49 @@ public interface IQuerySpecification<Matcher extends ViatraQueryMatcher<? extend | |||
39 | */ | 38 | */ |
40 | public Matcher getMatcher(ViatraQueryEngine engine); | 39 | public Matcher getMatcher(ViatraQueryEngine engine); |
41 | 40 | ||
42 | 41 | ||
43 | /** | 42 | /** |
44 | * Returns an empty, mutable Match compatible with matchers of this query. | 43 | * Returns an empty, mutable Match compatible with matchers of this query. |
45 | * Fields of the mutable match can be filled to create a partial match, usable as matcher input. | 44 | * Fields of the mutable match can be filled to create a partial match, usable as matcher input. |
46 | * This can be used to call the matcher with a partial match | 45 | * This can be used to call the matcher with a partial match |
47 | * even if the specific class of the matcher or the match is unknown. | 46 | * even if the specific class of the matcher or the match is unknown. |
48 | * | 47 | * |
49 | * @return the empty match | 48 | * @return the empty match |
50 | */ | 49 | */ |
51 | public abstract IPatternMatch newEmptyMatch(); | 50 | public abstract IPatternMatch newEmptyMatch(); |
52 | 51 | ||
53 | /** | 52 | /** |
54 | * Returns a new (partial) Match object compatible with matchers of this query. | 53 | * Returns a new (partial) Match object compatible with matchers of this query. |
55 | * This can be used e.g. to call the matcher with a partial | 54 | * This can be used e.g. to call the matcher with a partial |
56 | * match. | 55 | * match. |
57 | * | 56 | * |
58 | * <p>The returned match will be immutable. Use {@link #newEmptyMatch()} to obtain a mutable match object. | 57 | * <p>The returned match will be immutable. Use {@link #newEmptyMatch()} to obtain a mutable match object. |
59 | * | 58 | * |
60 | * @param parameters | 59 | * @param parameters |
61 | * the fixed value of pattern parameters, or null if not bound. | 60 | * the fixed value of pattern parameters, or null if not bound. |
62 | * @return the (partial) match object. | 61 | * @return the (partial) match object. |
63 | */ | 62 | */ |
64 | public abstract IPatternMatch newMatch(Object... parameters); | 63 | public abstract IPatternMatch newMatch(Object... parameters); |
65 | 64 | ||
66 | /** | 65 | /** |
67 | * The query is formulated over this kind of modeling platform. | 66 | * The query is formulated over this kind of modeling platform. |
68 | * E.g. for queries over EMF models, the {@link EMFScope} class is returned. | 67 | * E.g. for queries over EMF models, the {@link EMFScope} class is returned. |
69 | */ | 68 | */ |
70 | public Class<? extends QueryScope> getPreferredScopeClass(); | 69 | public Class<? extends QueryScope> getPreferredScopeClass(); |
71 | 70 | ||
72 | /** | 71 | /** |
73 | * Returns the definition of the query in a format intended for consumption by the query evaluator. | 72 | * Returns the definition of the query in a format intended for consumption by the query evaluator. |
74 | * @return the internal representation of the query. | 73 | * @return the internal representation of the query. |
75 | */ | 74 | */ |
76 | public PQuery getInternalQueryRepresentation(); | 75 | public PQuery getInternalQueryRepresentation(); |
77 | 76 | ||
78 | /** | 77 | /** |
79 | * Creates a new uninitialized matcher, which is not functional until an engine initializes it. Clients | 78 | * Creates a new uninitialized matcher, which is not functional until an engine initializes it. Clients |
80 | * should not call this method, it is used by the {@link ViatraQueryEngine} instance to instantiate matchers. | 79 | * should not call this method, it is used by the {@link ViatraQueryEngine} instance to instantiate matchers. |
81 | * @throws ViatraQueryRuntimeException | 80 | * @throws ViatraQueryRuntimeException |
82 | * @noreference This method is not intended to be referenced by clients. | 81 | * @noreference This method is not intended to be referenced by clients. |
83 | * @since 1.4 | 82 | * @since 1.4 |
84 | */ | 83 | */ |
85 | public Matcher instantiate(); | 84 | public Matcher instantiate(); |
86 | 85 | ||
87 | } | 86 | } |
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/IRunOnceQueryEngine.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/IRunOnceQueryEngine.java deleted file mode 100644 index b625980b..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/IRunOnceQueryEngine.java +++ /dev/null | |||
@@ -1,68 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2013, Abel Hegedus, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.api; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | |||
13 | import org.eclipse.emf.common.notify.Notifier; | ||
14 | import tools.refinery.viatra.runtime.base.api.BaseIndexOptions; | ||
15 | import tools.refinery.viatra.runtime.base.api.NavigationHelper; | ||
16 | |||
17 | /** | ||
18 | * A run-once query engine is used to get matches for queries without incremental support. | ||
19 | * Users can create a query engine with a given {@link Notifier} as scope and use a query specification | ||
20 | * to retrieve the current match set with this scope (see {@link #getAllMatches}). | ||
21 | * | ||
22 | * @author Abel Hegedus | ||
23 | * | ||
24 | */ | ||
25 | public interface IRunOnceQueryEngine { | ||
26 | |||
27 | /** | ||
28 | * Returns the set of all matches for the given query in the scope of the engine. | ||
29 | * | ||
30 | * @param querySpecification the query that is evaluated | ||
31 | * @return matches represented as a Match object. | ||
32 | */ | ||
33 | <Match extends IPatternMatch> Collection<Match> getAllMatches( | ||
34 | final IQuerySpecification<? extends ViatraQueryMatcher<Match>> querySpecification); | ||
35 | |||
36 | /** | ||
37 | * @return the scope of pattern matching, i.e. the root of the EMF model tree that this engine is attached to. | ||
38 | */ | ||
39 | Notifier getScope(); | ||
40 | |||
41 | /** | ||
42 | * The base index options specifies how the base index is built, including wildcard mode (defaults to false) and | ||
43 | * dynamic EMF mode (defaults to false). See {@link NavigationHelper} for the explanation of wildcard mode and | ||
44 | * dynamic EMF mode. | ||
45 | * | ||
46 | * <p/> The returned options can be modified in order to affect subsequent calls of {@link #getAllMatches}. | ||
47 | * | ||
48 | * @return the base index options used by the engine. | ||
49 | */ | ||
50 | BaseIndexOptions getBaseIndexOptions(); | ||
51 | |||
52 | /** | ||
53 | * When set to true, the run-once query engine will not dispose it's engine and will resample the values of derived | ||
54 | * features before returning matches if the model changed since the last call. | ||
55 | * | ||
56 | * If the values of derived features may change without any model modification, call {@link #resampleOnNextCall()} | ||
57 | * before subsequent calls of {@link #getAllMatches}. | ||
58 | * | ||
59 | * @param automaticResampling | ||
60 | */ | ||
61 | void setAutomaticResampling(boolean automaticResampling); | ||
62 | |||
63 | /** | ||
64 | * If automatic resampling is enabled and the value of derived features may change without model modifications, | ||
65 | * calling this method will make sure that re-sampling will occur before returning match results. | ||
66 | */ | ||
67 | void resampleOnNextCall(); | ||
68 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/LazyLoadingQueryGroup.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/LazyLoadingQueryGroup.java deleted file mode 100644 index 6ae44b7c..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/LazyLoadingQueryGroup.java +++ /dev/null | |||
@@ -1,64 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, 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 | import java.util.Collections; | ||
12 | import java.util.Objects; | ||
13 | import java.util.Set; | ||
14 | import java.util.function.Supplier; | ||
15 | import java.util.stream.Collectors; | ||
16 | |||
17 | import tools.refinery.viatra.runtime.api.impl.BaseQueryGroup; | ||
18 | import tools.refinery.viatra.runtime.matchers.util.Preconditions; | ||
19 | import tools.refinery.viatra.runtime.util.ViatraQueryLoggingUtil; | ||
20 | |||
21 | /** | ||
22 | * Initializes a query group from a set of query providers. The query providers are not executed until the queries | ||
23 | * themselves are asked in the {@link #getSpecifications()} method. | ||
24 | * | ||
25 | * @author Zoltan Ujhelyi | ||
26 | * @since 1.3 | ||
27 | * | ||
28 | */ | ||
29 | public class LazyLoadingQueryGroup extends BaseQueryGroup { | ||
30 | |||
31 | private final Set<? extends Supplier<IQuerySpecification<?>>> providers; | ||
32 | private Set<IQuerySpecification<?>> specifications = null; | ||
33 | |||
34 | /** | ||
35 | * @param providers a non-null set to initialize the group | ||
36 | */ | ||
37 | public LazyLoadingQueryGroup(Set<? extends Supplier<IQuerySpecification<?>>> providers) { | ||
38 | Preconditions.checkArgument(providers != null, "The set of providers must not be null"); | ||
39 | this.providers = providers; | ||
40 | } | ||
41 | |||
42 | /** | ||
43 | * @param providers a non-null set to initialize the group | ||
44 | */ | ||
45 | public static IQueryGroup of(Set<? extends Supplier<IQuerySpecification<?>>> querySpecifications) { | ||
46 | return new LazyLoadingQueryGroup(querySpecifications); | ||
47 | } | ||
48 | |||
49 | @Override | ||
50 | public Set<IQuerySpecification<?>> getSpecifications() { | ||
51 | if (specifications == null) { | ||
52 | try { | ||
53 | specifications = providers.stream().filter(Objects::nonNull).map(Supplier::get).filter(Objects::nonNull).collect(Collectors.toSet()); | ||
54 | } catch (Exception e) { | ||
55 | // TODO maybe store in issue list and provide better error reporting in general | ||
56 | String errorMessage = "Exception occurred while accessing query specification from provider: " + e.getMessage(); | ||
57 | ViatraQueryLoggingUtil.getLogger(getClass()).error(errorMessage); | ||
58 | return Collections.emptySet(); | ||
59 | } | ||
60 | } | ||
61 | return specifications; | ||
62 | } | ||
63 | |||
64 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/PackageBasedQueryGroup.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/PackageBasedQueryGroup.java deleted file mode 100644 index 252bb7fd..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/PackageBasedQueryGroup.java +++ /dev/null | |||
@@ -1,133 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2012, Abel Hegedus, Mark Czotter, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.api; | ||
10 | |||
11 | import java.util.Collections; | ||
12 | import java.util.HashSet; | ||
13 | import java.util.Set; | ||
14 | |||
15 | import tools.refinery.viatra.runtime.api.impl.BaseQueryGroup; | ||
16 | import tools.refinery.viatra.runtime.registry.IQuerySpecificationRegistry; | ||
17 | import tools.refinery.viatra.runtime.registry.IQuerySpecificationRegistryEntry; | ||
18 | import tools.refinery.viatra.runtime.registry.IQuerySpecificationRegistryChangeListener; | ||
19 | import tools.refinery.viatra.runtime.registry.IRegistryView; | ||
20 | import tools.refinery.viatra.runtime.registry.IRegistryViewFilter; | ||
21 | import tools.refinery.viatra.runtime.registry.QuerySpecificationRegistry; | ||
22 | |||
23 | /** | ||
24 | * Package based {@link BaseQueryGroup} implementation. It handles patterns as a group within the same package. | ||
25 | * | ||
26 | * @author Abel Hegedus, Mark Czotter | ||
27 | * | ||
28 | */ | ||
29 | public class PackageBasedQueryGroup extends BaseQueryGroup { | ||
30 | |||
31 | private final Set<IQuerySpecification<?>> querySpecifications = new HashSet<>(); | ||
32 | private final String packageName; | ||
33 | private final boolean includeSubPackages; | ||
34 | private IRegistryView view; | ||
35 | |||
36 | /** | ||
37 | * Creates a query group with specifications of a given package from the {@link QuerySpecificationRegistry}. Only | ||
38 | * query specifications with the exact package fully qualified name are included. | ||
39 | * | ||
40 | * @param packageName | ||
41 | * that contains the specifications | ||
42 | */ | ||
43 | public PackageBasedQueryGroup(String packageName) { | ||
44 | this(packageName, false); | ||
45 | } | ||
46 | |||
47 | /** | ||
48 | * Creates a query group with specifications of a given package from the {@link QuerySpecificationRegistry}. | ||
49 | * | ||
50 | * @param packageName | ||
51 | * that contain the specifications | ||
52 | * @param includeSubPackages | ||
53 | * if true all query specifications with package names starting with the given package are included | ||
54 | */ | ||
55 | public PackageBasedQueryGroup(String packageName, boolean includeSubPackages) { | ||
56 | super(); | ||
57 | this.packageName = packageName; | ||
58 | this.includeSubPackages = includeSubPackages; | ||
59 | IQuerySpecificationRegistry registry = QuerySpecificationRegistry.getInstance(); | ||
60 | view = registry.createView(new PackageNameBasedViewFilter()); | ||
61 | for (IQuerySpecificationRegistryEntry entry : view.getEntries()) { | ||
62 | this.querySpecifications.add(entry.get()); | ||
63 | } | ||
64 | SpecificationSetUpdater listener = new SpecificationSetUpdater(); | ||
65 | view.addViewListener(listener); | ||
66 | } | ||
67 | |||
68 | @Override | ||
69 | public Set<IQuerySpecification<?>> getSpecifications() { | ||
70 | return Collections.unmodifiableSet(new HashSet<>(querySpecifications)); | ||
71 | } | ||
72 | |||
73 | public String getPackageName() { | ||
74 | return packageName; | ||
75 | } | ||
76 | |||
77 | public boolean isIncludeSubPackages() { | ||
78 | return includeSubPackages; | ||
79 | } | ||
80 | |||
81 | /** | ||
82 | * Refreshes the pattern group from the query specification registry based on the parameters used during the | ||
83 | * initialization. | ||
84 | */ | ||
85 | public void refresh() { | ||
86 | // do nothing, view is automatically refreshed | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * Listener to update the specification set | ||
91 | * | ||
92 | * @author Abel Hegedus | ||
93 | * | ||
94 | */ | ||
95 | private final class SpecificationSetUpdater implements IQuerySpecificationRegistryChangeListener { | ||
96 | @Override | ||
97 | public void entryAdded(IQuerySpecificationRegistryEntry entry) { | ||
98 | querySpecifications.add(entry.get()); | ||
99 | } | ||
100 | |||
101 | @Override | ||
102 | public void entryRemoved(IQuerySpecificationRegistryEntry entry) { | ||
103 | querySpecifications.remove(entry.get()); | ||
104 | } | ||
105 | } | ||
106 | |||
107 | /** | ||
108 | * Registry view filter that checks FQNs against the given package name. | ||
109 | * | ||
110 | * @author Abel Hegedus | ||
111 | * | ||
112 | */ | ||
113 | private final class PackageNameBasedViewFilter implements IRegistryViewFilter { | ||
114 | @Override | ||
115 | public boolean isEntryRelevant(IQuerySpecificationRegistryEntry entry) { | ||
116 | String fqn = entry.getFullyQualifiedName(); | ||
117 | if (packageName.length() + 1 < fqn.length()) { | ||
118 | if (includeSubPackages) { | ||
119 | if (fqn.startsWith(packageName + '.')) { | ||
120 | return true; | ||
121 | } | ||
122 | } else { | ||
123 | String name = fqn.substring(fqn.lastIndexOf('.') + 1, fqn.length()); | ||
124 | if (fqn.equals(packageName + '.' + name)) { | ||
125 | return true; | ||
126 | } | ||
127 | } | ||
128 | } | ||
129 | return false; | ||
130 | } | ||
131 | } | ||
132 | |||
133 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/ViatraQueryEngine.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/ViatraQueryEngine.java index fd8ff848..ebae57a7 100644 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/ViatraQueryEngine.java +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/ViatraQueryEngine.java | |||
@@ -12,8 +12,6 @@ package tools.refinery.viatra.runtime.api; | |||
12 | import org.eclipse.emf.common.notify.Notifier; | 12 | import org.eclipse.emf.common.notify.Notifier; |
13 | import tools.refinery.viatra.runtime.api.scope.IBaseIndex; | 13 | import tools.refinery.viatra.runtime.api.scope.IBaseIndex; |
14 | import tools.refinery.viatra.runtime.api.scope.QueryScope; | 14 | import tools.refinery.viatra.runtime.api.scope.QueryScope; |
15 | import tools.refinery.viatra.runtime.base.api.BaseIndexOptions; | ||
16 | import tools.refinery.viatra.runtime.emf.EMFScope; | ||
17 | import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException; | 15 | import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException; |
18 | 16 | ||
19 | import java.util.Set; | 17 | import java.util.Set; |
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/ViatraQueryEngineManager.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/ViatraQueryEngineManager.java index ca709b02..4a256aea 100644 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/ViatraQueryEngineManager.java +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/ViatraQueryEngineManager.java | |||
@@ -3,47 +3,42 @@ | |||
3 | * This program and the accompanying materials are made available under the | 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 | 4 | * terms of the Eclipse Public License v. 2.0 which is available at |
5 | * http://www.eclipse.org/legal/epl-v20.html. | 5 | * http://www.eclipse.org/legal/epl-v20.html. |
6 | * | 6 | * |
7 | * SPDX-License-Identifier: EPL-2.0 | 7 | * SPDX-License-Identifier: EPL-2.0 |
8 | *******************************************************************************/ | 8 | *******************************************************************************/ |
9 | 9 | ||
10 | package tools.refinery.viatra.runtime.api; | 10 | package tools.refinery.viatra.runtime.api; |
11 | 11 | ||
12 | import static tools.refinery.viatra.runtime.matchers.util.Preconditions.checkArgument; | ||
13 | |||
14 | import java.lang.ref.WeakReference; | ||
15 | import java.util.Collections; | ||
16 | import java.util.HashSet; | ||
17 | import java.util.Map; | ||
18 | import java.util.Set; | ||
19 | import java.util.WeakHashMap; | ||
20 | |||
21 | import tools.refinery.viatra.runtime.api.scope.QueryScope; | 12 | import tools.refinery.viatra.runtime.api.scope.QueryScope; |
22 | import tools.refinery.viatra.runtime.emf.EMFScope; | ||
23 | import tools.refinery.viatra.runtime.internal.apiimpl.ViatraQueryEngineImpl; | 13 | import tools.refinery.viatra.runtime.internal.apiimpl.ViatraQueryEngineImpl; |
24 | import tools.refinery.viatra.runtime.util.ViatraQueryLoggingUtil; | 14 | import tools.refinery.viatra.runtime.util.ViatraQueryLoggingUtil; |
25 | 15 | ||
16 | import java.lang.ref.WeakReference; | ||
17 | import java.util.*; | ||
18 | |||
19 | import static tools.refinery.viatra.runtime.matchers.util.Preconditions.checkArgument; | ||
20 | |||
26 | /** | 21 | /** |
27 | * Global registry of active VIATRA Query Engines. | 22 | * Global registry of active VIATRA Query Engines. |
28 | * | 23 | * |
29 | * <p> | 24 | * <p> |
30 | * Manages an {@link ViatraQueryEngine} for each model (more precisely scope), that is created on demand. Managed engines are shared between | 25 | * Manages an {@link ViatraQueryEngine} for each model (more precisely scope), that is created on demand. Managed engines are shared between |
31 | * clients querying the same model. | 26 | * clients querying the same model. |
32 | * | 27 | * |
33 | * <p> | 28 | * <p> |
34 | * It is also possible to create private, unmanaged engines that are not shared between clients. | 29 | * It is also possible to create private, unmanaged engines that are not shared between clients. |
35 | * | 30 | * |
36 | * <p> | 31 | * <p> |
37 | * Only weak references are retained on the managed engines. So if there are no other references to the matchers or the | 32 | * Only weak references are retained on the managed engines. So if there are no other references to the matchers or the |
38 | * engine, they can eventually be GC'ed, and they won't block the model from being GC'ed either. | 33 | * engine, they can eventually be GC'ed, and they won't block the model from being GC'ed either. |
39 | * | 34 | * |
40 | * | 35 | * |
41 | * @author Bergmann Gabor | 36 | * @author Bergmann Gabor |
42 | * | 37 | * |
43 | */ | 38 | */ |
44 | public class ViatraQueryEngineManager { | 39 | public class ViatraQueryEngineManager { |
45 | private static ViatraQueryEngineManager instance = new ViatraQueryEngineManager(); | 40 | private static ViatraQueryEngineManager instance = new ViatraQueryEngineManager(); |
46 | 41 | ||
47 | 42 | ||
48 | /** | 43 | /** |
49 | * @return the singleton instance | 44 | * @return the singleton instance |
@@ -68,32 +63,32 @@ public class ViatraQueryEngineManager { | |||
68 | } | 63 | } |
69 | 64 | ||
70 | /** | 65 | /** |
71 | * Creates a managed VIATRA Query Engine at a given scope (e.g. an EMF Resource or ResourceSet, as in {@link EMFScope}) | 66 | * Creates a managed VIATRA Query Engine at a given scope (e.g. an EMF Resource or ResourceSet, as in {@link EMFScope}) |
72 | * or retrieves an already existing one. Repeated invocations for a single model root will return the same engine. | 67 | * or retrieves an already existing one. Repeated invocations for a single model root will return the same engine. |
73 | * Consequently, the engine will be reused between different clients querying the same model, providing performance benefits. | 68 | * Consequently, the engine will be reused between different clients querying the same model, providing performance benefits. |
74 | * | 69 | * |
75 | * <p> | 70 | * <p> |
76 | * The match set of any patterns will be incrementally refreshed upon updates from this scope. | 71 | * The match set of any patterns will be incrementally refreshed upon updates from this scope. |
77 | * | 72 | * |
78 | * @param scope | 73 | * @param scope |
79 | * the scope of query evaluation; the definition of the set of model elements that this engine is operates on. | 74 | * the scope of query evaluation; the definition of the set of model elements that this engine is operates on. |
80 | * Provide e.g. a {@link EMFScope} for evaluating queries on an EMF model. | 75 | * Provide e.g. a {@link EMFScope} for evaluating queries on an EMF model. |
81 | * @return a new or previously existing engine | 76 | * @return a new or previously existing engine |
82 | */ | 77 | */ |
83 | public ViatraQueryEngine getQueryEngine(QueryScope scope) { | 78 | public ViatraQueryEngine getQueryEngine(QueryScope scope) { |
84 | return getQueryEngine(scope, ViatraQueryEngineOptions.getDefault()); | 79 | return getQueryEngine(scope, ViatraQueryEngineOptions.getDefault()); |
85 | } | 80 | } |
86 | 81 | ||
87 | /** | 82 | /** |
88 | * Creates a managed VIATRA Query Engine at a given scope (e.g. an EMF Resource or ResourceSet, as in {@link EMFScope}) | 83 | * Creates a managed VIATRA Query Engine at a given scope (e.g. an EMF Resource or ResourceSet, as in {@link EMFScope}) |
89 | * or retrieves an already existing one. Repeated invocations for a single model root will return the same engine. | 84 | * or retrieves an already existing one. Repeated invocations for a single model root will return the same engine. |
90 | * Consequently, the engine will be reused between different clients querying the same model, providing performance benefits. | 85 | * Consequently, the engine will be reused between different clients querying the same model, providing performance benefits. |
91 | * | 86 | * |
92 | * <p> | 87 | * <p> |
93 | * The match set of any patterns will be incrementally refreshed upon updates from this scope. | 88 | * The match set of any patterns will be incrementally refreshed upon updates from this scope. |
94 | * | 89 | * |
95 | * @param scope | 90 | * @param scope |
96 | * the scope of query evaluation; the definition of the set of model elements that this engine is operates on. | 91 | * the scope of query evaluation; the definition of the set of model elements that this engine is operates on. |
97 | * Provide e.g. a {@link EMFScope} for evaluating queries on an EMF model. | 92 | * Provide e.g. a {@link EMFScope} for evaluating queries on an EMF model. |
98 | * @return a new or previously existing engine | 93 | * @return a new or previously existing engine |
99 | * @since 1.4 | 94 | * @since 1.4 |
@@ -110,9 +105,9 @@ public class ViatraQueryEngineManager { | |||
110 | 105 | ||
111 | /** | 106 | /** |
112 | * Retrieves an already existing managed VIATRA Query Engine. | 107 | * Retrieves an already existing managed VIATRA Query Engine. |
113 | * | 108 | * |
114 | * @param scope | 109 | * @param scope |
115 | * the scope of query evaluation; the definition of the set of model elements that this engine is operates on. | 110 | * the scope of query evaluation; the definition of the set of model elements that this engine is operates on. |
116 | * Provide e.g. a {@link EMFScope} for evaluating queries on an EMF model. | 111 | * Provide e.g. a {@link EMFScope} for evaluating queries on an EMF model. |
117 | * @return a previously existing engine, or null if no engine is active for the given EMF model root | 112 | * @return a previously existing engine, or null if no engine is active for the given EMF model root |
118 | */ | 113 | */ |
@@ -122,7 +117,7 @@ public class ViatraQueryEngineManager { | |||
122 | 117 | ||
123 | /** | 118 | /** |
124 | * Collects all {@link ViatraQueryEngine} instances that still exist. | 119 | * Collects all {@link ViatraQueryEngine} instances that still exist. |
125 | * | 120 | * |
126 | * @return set of engines if there is any, otherwise EMTPY_SET | 121 | * @return set of engines if there is any, otherwise EMTPY_SET |
127 | */ | 122 | */ |
128 | public Set<ViatraQueryEngine> getExistingQueryEngines(){ | 123 | public Set<ViatraQueryEngine> getExistingQueryEngines(){ |
@@ -139,14 +134,14 @@ public class ViatraQueryEngineManager { | |||
139 | } | 134 | } |
140 | return existingEngines; | 135 | return existingEngines; |
141 | } | 136 | } |
142 | 137 | ||
143 | private final Set<ViatraQueryEngineInitializationListener> initializationListeners; | 138 | private final Set<ViatraQueryEngineInitializationListener> initializationListeners; |
144 | 139 | ||
145 | /** | 140 | /** |
146 | * Registers a listener for new engine initialization. | 141 | * Registers a listener for new engine initialization. |
147 | * | 142 | * |
148 | * <p/> For removal, use {@link #removeQueryEngineInitializationListener} | 143 | * <p/> For removal, use {@link #removeQueryEngineInitializationListener} |
149 | * | 144 | * |
150 | * @param listener the listener to register | 145 | * @param listener the listener to register |
151 | */ | 146 | */ |
152 | public void addQueryEngineInitializationListener(ViatraQueryEngineInitializationListener listener) { | 147 | public void addQueryEngineInitializationListener(ViatraQueryEngineInitializationListener listener) { |
@@ -156,7 +151,7 @@ public class ViatraQueryEngineManager { | |||
156 | 151 | ||
157 | /** | 152 | /** |
158 | * Removes a registered listener added with {@link #addQueryEngineInitializationListener} | 153 | * Removes a registered listener added with {@link #addQueryEngineInitializationListener} |
159 | * | 154 | * |
160 | * @param listener | 155 | * @param listener |
161 | */ | 156 | */ |
162 | public void removeQueryEngineInitializationListener(ViatraQueryEngineInitializationListener listener) { | 157 | public void removeQueryEngineInitializationListener(ViatraQueryEngineInitializationListener listener) { |
@@ -166,7 +161,7 @@ public class ViatraQueryEngineManager { | |||
166 | 161 | ||
167 | /** | 162 | /** |
168 | * Notifies listeners that a new engine has been initialized. | 163 | * Notifies listeners that a new engine has been initialized. |
169 | * | 164 | * |
170 | * @param engine the initialized engine | 165 | * @param engine the initialized engine |
171 | */ | 166 | */ |
172 | protected void notifyInitializationListeners(AdvancedViatraQueryEngine engine) { | 167 | protected void notifyInitializationListeners(AdvancedViatraQueryEngine engine) { |
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/impl/BaseGeneratedEMFPQuery.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/impl/BaseGeneratedEMFPQuery.java deleted file mode 100644 index c1fb0622..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/impl/BaseGeneratedEMFPQuery.java +++ /dev/null | |||
@@ -1,110 +0,0 @@ | |||
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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.api.impl; | ||
10 | |||
11 | import org.eclipse.emf.ecore.EClass; | ||
12 | import org.eclipse.emf.ecore.EClassifier; | ||
13 | import org.eclipse.emf.ecore.EEnum; | ||
14 | import org.eclipse.emf.ecore.EEnumLiteral; | ||
15 | import org.eclipse.emf.ecore.EPackage; | ||
16 | import org.eclipse.emf.ecore.EStructuralFeature; | ||
17 | import tools.refinery.viatra.runtime.exception.ViatraQueryException; | ||
18 | import tools.refinery.viatra.runtime.matchers.psystem.queries.BasePQuery; | ||
19 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PVisibility; | ||
20 | import tools.refinery.viatra.runtime.matchers.psystem.queries.QueryInitializationException; | ||
21 | |||
22 | /** | ||
23 | * Common superclass for EMF-based generated PQueries. | ||
24 | * @author Bergmann Gabor | ||
25 | * | ||
26 | */ | ||
27 | public abstract class BaseGeneratedEMFPQuery extends BasePQuery { | ||
28 | |||
29 | public BaseGeneratedEMFPQuery() { | ||
30 | this(PVisibility.PUBLIC); | ||
31 | } | ||
32 | |||
33 | /** | ||
34 | * @since 2.0 | ||
35 | */ | ||
36 | public BaseGeneratedEMFPQuery(PVisibility visibility) { | ||
37 | super(visibility); | ||
38 | } | ||
39 | |||
40 | protected QueryInitializationException processDependencyException(ViatraQueryException ex) { | ||
41 | if (ex.getCause() instanceof QueryInitializationException) | ||
42 | return (QueryInitializationException) ex.getCause(); | ||
43 | return new QueryInitializationException( | ||
44 | "Failed to initialize external dependencies of query specification - see 'caused by' for details.", | ||
45 | null, "Problem with query dependencies.", this, ex); | ||
46 | } | ||
47 | |||
48 | protected EClassifier getClassifierLiteral(String packageUri, String classifierName) { | ||
49 | EPackage ePackage = EPackage.Registry.INSTANCE.getEPackage(packageUri); | ||
50 | if (ePackage == null) | ||
51 | throw new QueryInitializationException( | ||
52 | "Query refers to EPackage {1} not found in EPackage Registry.", | ||
53 | new String[]{packageUri}, | ||
54 | "Query refers to missing EPackage.", this); | ||
55 | EClassifier literal = ePackage.getEClassifier(classifierName); | ||
56 | if (literal == null) | ||
57 | throw new QueryInitializationException( | ||
58 | "Query refers to classifier {1} not found in EPackage {2}.", | ||
59 | new String[]{classifierName, packageUri}, | ||
60 | "Query refers to missing type in EPackage.", this); | ||
61 | return literal; | ||
62 | } | ||
63 | |||
64 | /** | ||
65 | * For parameter type retrieval only. | ||
66 | * | ||
67 | * <p>If parameter type declaration is erroneous, we still get a working parameter list (without the type declaration); | ||
68 | * the exception will be thrown again later when the body is processed. | ||
69 | */ | ||
70 | protected EClassifier getClassifierLiteralSafe(String packageURI, String classifierName) { | ||
71 | try { | ||
72 | return getClassifierLiteral(packageURI, classifierName); | ||
73 | } catch (QueryInitializationException e) { | ||
74 | return null; | ||
75 | } | ||
76 | } | ||
77 | |||
78 | protected EStructuralFeature getFeatureLiteral(String packageUri, String className, String featureName) { | ||
79 | EClassifier container = getClassifierLiteral(packageUri, className); | ||
80 | if (! (container instanceof EClass)) | ||
81 | throw new QueryInitializationException( | ||
82 | "Query refers to EClass {1} in EPackage {2} which turned out not be an EClass.", | ||
83 | new String[]{className, packageUri}, | ||
84 | "Query refers to missing EClass.", this); | ||
85 | EStructuralFeature feature = ((EClass)container).getEStructuralFeature(featureName); | ||
86 | if (feature == null) | ||
87 | throw new QueryInitializationException( | ||
88 | "Query refers to feature {1} not found in EClass {2}.", | ||
89 | new String[]{featureName, className}, | ||
90 | "Query refers to missing feature.", this); | ||
91 | return feature; | ||
92 | } | ||
93 | |||
94 | protected EEnumLiteral getEnumLiteral(String packageUri, String enumName, String literalName) { | ||
95 | EClassifier enumContainer = getClassifierLiteral(packageUri, enumName); | ||
96 | if (! (enumContainer instanceof EEnum)) | ||
97 | throw new QueryInitializationException( | ||
98 | "Query refers to EEnum {1} in EPackage {2} which turned out not be an EEnum.", | ||
99 | new String[]{enumName, packageUri}, | ||
100 | "Query refers to missing enumeration type.", this); | ||
101 | EEnumLiteral literal = ((EEnum)enumContainer).getEEnumLiteral(literalName); | ||
102 | if (literal == null) | ||
103 | throw new QueryInitializationException( | ||
104 | "Query refers to enumeration literal {1} not found in EEnum {2}.", | ||
105 | new String[]{literalName, enumName}, | ||
106 | "Query refers to missing enumeration literal.", this); | ||
107 | return literal; | ||
108 | } | ||
109 | |||
110 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/impl/BaseGeneratedEMFQuerySpecification.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/impl/BaseGeneratedEMFQuerySpecification.java deleted file mode 100644 index 9956983d..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/impl/BaseGeneratedEMFQuerySpecification.java +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
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 tools.refinery.viatra.runtime.api.IPatternMatch; | ||
13 | import tools.refinery.viatra.runtime.api.ViatraQueryMatcher; | ||
14 | import tools.refinery.viatra.runtime.api.scope.QueryScope; | ||
15 | import tools.refinery.viatra.runtime.emf.EMFScope; | ||
16 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
17 | |||
18 | /** | ||
19 | * Provides common functionality of pattern-specific generated query specifications over the EMF scope. | ||
20 | * | ||
21 | * @author Bergmann Gábor | ||
22 | * @author Mark Czotter | ||
23 | */ | ||
24 | public abstract class BaseGeneratedEMFQuerySpecification<Matcher extends ViatraQueryMatcher<? extends IPatternMatch>> extends | ||
25 | BaseQuerySpecification<Matcher> { | ||
26 | |||
27 | |||
28 | /** | ||
29 | * Instantiates query specification for the given internal query representation. | ||
30 | */ | ||
31 | public BaseGeneratedEMFQuerySpecification(PQuery wrappedPQuery) { | ||
32 | super(wrappedPQuery); | ||
33 | } | ||
34 | |||
35 | @Override | ||
36 | public Class<? extends QueryScope> getPreferredScopeClass() { | ||
37 | return EMFScope.class; | ||
38 | } | ||
39 | |||
40 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/impl/BaseGeneratedEMFQuerySpecificationWithGenericMatcher.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/impl/BaseGeneratedEMFQuerySpecificationWithGenericMatcher.java deleted file mode 100644 index 949dd112..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/impl/BaseGeneratedEMFQuerySpecificationWithGenericMatcher.java +++ /dev/null | |||
@@ -1,58 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, 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.impl; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.api.GenericPatternMatch; | ||
12 | import tools.refinery.viatra.runtime.api.GenericPatternMatcher; | ||
13 | import tools.refinery.viatra.runtime.api.GenericQuerySpecification; | ||
14 | import tools.refinery.viatra.runtime.api.ViatraQueryEngine; | ||
15 | import tools.refinery.viatra.runtime.api.scope.QueryScope; | ||
16 | import tools.refinery.viatra.runtime.emf.EMFScope; | ||
17 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
18 | |||
19 | /** | ||
20 | * Provides common functionality of pattern-specific generated query specifications for without generated | ||
21 | * pattern-specific match and matcher classes, including private patterns. | ||
22 | * | ||
23 | * @since 1.7 | ||
24 | * | ||
25 | */ | ||
26 | public abstract class BaseGeneratedEMFQuerySpecificationWithGenericMatcher | ||
27 | extends GenericQuerySpecification<GenericPatternMatcher> { | ||
28 | |||
29 | public BaseGeneratedEMFQuerySpecificationWithGenericMatcher(PQuery wrappedPQuery) { | ||
30 | super(wrappedPQuery); | ||
31 | } | ||
32 | |||
33 | @Override | ||
34 | public Class<? extends QueryScope> getPreferredScopeClass() { | ||
35 | return EMFScope.class; | ||
36 | } | ||
37 | |||
38 | @Override | ||
39 | protected GenericPatternMatcher instantiate(final ViatraQueryEngine engine) { | ||
40 | return defaultInstantiate(engine); | ||
41 | } | ||
42 | |||
43 | @Override | ||
44 | public GenericPatternMatcher instantiate() { | ||
45 | return new GenericPatternMatcher(this); | ||
46 | } | ||
47 | |||
48 | @Override | ||
49 | public GenericPatternMatch newEmptyMatch() { | ||
50 | return GenericPatternMatch.newEmptyMatch(this); | ||
51 | } | ||
52 | |||
53 | @Override | ||
54 | public GenericPatternMatch newMatch(final Object... parameters) { | ||
55 | return GenericPatternMatch.newMatch(this, parameters); | ||
56 | } | ||
57 | |||
58 | } \ No newline at end of file | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/impl/BasePatternMatch.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/impl/BasePatternMatch.java index 7690daf6..182bb466 100644 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/impl/BasePatternMatch.java +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/impl/BasePatternMatch.java | |||
@@ -3,25 +3,23 @@ | |||
3 | * This program and the accompanying materials are made available under the | 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 | 4 | * terms of the Eclipse Public License v. 2.0 which is available at |
5 | * http://www.eclipse.org/legal/epl-v20.html. | 5 | * http://www.eclipse.org/legal/epl-v20.html. |
6 | * | 6 | * |
7 | * SPDX-License-Identifier: EPL-2.0 | 7 | * SPDX-License-Identifier: EPL-2.0 |
8 | *******************************************************************************/ | 8 | *******************************************************************************/ |
9 | 9 | ||
10 | package tools.refinery.viatra.runtime.api.impl; | 10 | package tools.refinery.viatra.runtime.api.impl; |
11 | 11 | ||
12 | import tools.refinery.viatra.runtime.api.IPatternMatch; | ||
13 | |||
12 | import java.util.Arrays; | 14 | import java.util.Arrays; |
13 | import java.util.Collections; | 15 | import java.util.Collections; |
14 | import java.util.List; | 16 | import java.util.List; |
15 | 17 | ||
16 | import org.eclipse.emf.ecore.EObject; | ||
17 | import org.eclipse.emf.ecore.EStructuralFeature; | ||
18 | import tools.refinery.viatra.runtime.api.IPatternMatch; | ||
19 | |||
20 | /** | 18 | /** |
21 | * Base implementation of IPatternMatch. | 19 | * Base implementation of IPatternMatch. |
22 | * | 20 | * |
23 | * @author Bergmann Gábor | 21 | * @author Bergmann Gábor |
24 | * | 22 | * |
25 | */ | 23 | */ |
26 | public abstract class BasePatternMatch implements IPatternMatch { | 24 | public abstract class BasePatternMatch implements IPatternMatch { |
27 | 25 | ||
@@ -29,36 +27,14 @@ public abstract class BasePatternMatch implements IPatternMatch { | |||
29 | protected static <T> List<T> makeImmutableList(T... elements) { | 27 | protected static <T> List<T> makeImmutableList(T... elements) { |
30 | return Collections.unmodifiableList(Arrays.asList(elements)); | 28 | return Collections.unmodifiableList(Arrays.asList(elements)); |
31 | } | 29 | } |
32 | 30 | ||
33 | public static String prettyPrintValue(Object o) { | 31 | public static String prettyPrintValue(Object o) { |
34 | if (o == null) { | 32 | if (o == null) { |
35 | return "(null)"; | 33 | return "(null)"; |
36 | } | 34 | } |
37 | String name = prettyPrintFeature(o, "name"); | ||
38 | if (name != null) { | ||
39 | return name; | ||
40 | } | ||
41 | /* | ||
42 | * if (o instanceof EObject) { EStructuralFeature feature = ((EObject)o).eClass().getEStructuralFeature("name"); | ||
43 | * if (feature != null) { Object name = ((EObject)o).eGet(feature); if (name != null) return name.toString(); } | ||
44 | * } | ||
45 | */ | ||
46 | return o.toString(); | 35 | return o.toString(); |
47 | } | 36 | } |
48 | 37 | ||
49 | public static String prettyPrintFeature(Object o, String featureName) { | ||
50 | if (o instanceof EObject) { | ||
51 | EStructuralFeature feature = ((EObject) o).eClass().getEStructuralFeature(featureName); | ||
52 | if (feature != null) { | ||
53 | Object value = ((EObject) o).eGet(feature); | ||
54 | if (value != null) { | ||
55 | return value.toString(); | ||
56 | } | ||
57 | } | ||
58 | } | ||
59 | return null; | ||
60 | } | ||
61 | |||
62 | // TODO performance can be improved here somewhat | 38 | // TODO performance can be improved here somewhat |
63 | 39 | ||
64 | @Override | 40 | @Override |
@@ -83,7 +59,7 @@ public abstract class BasePatternMatch implements IPatternMatch { | |||
83 | public String toString() { | 59 | public String toString() { |
84 | return "Match<" + patternName() + ">{" + prettyPrint() + "}"; | 60 | return "Match<" + patternName() + ">{" + prettyPrint() + "}"; |
85 | } | 61 | } |
86 | 62 | ||
87 | @Override | 63 | @Override |
88 | public boolean isCompatibleWith(IPatternMatch other) { | 64 | public boolean isCompatibleWith(IPatternMatch other) { |
89 | if(other == null) { | 65 | if(other == null) { |
@@ -102,7 +78,7 @@ public abstract class BasePatternMatch implements IPatternMatch { | |||
102 | } | 78 | } |
103 | return true; | 79 | return true; |
104 | } | 80 | } |
105 | 81 | ||
106 | @Override | 82 | @Override |
107 | public String patternName() { | 83 | public String patternName() { |
108 | return specification().getFullyQualifiedName(); | 84 | return specification().getFullyQualifiedName(); |
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/impl/RunOnceQueryEngine.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/impl/RunOnceQueryEngine.java deleted file mode 100644 index a97dea5d..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/impl/RunOnceQueryEngine.java +++ /dev/null | |||
@@ -1,140 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2013, Abel Hegedus, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.api.impl; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | |||
13 | import org.eclipse.emf.common.notify.Notifier; | ||
14 | import tools.refinery.viatra.runtime.api.AdvancedViatraQueryEngine; | ||
15 | import tools.refinery.viatra.runtime.api.IPatternMatch; | ||
16 | import tools.refinery.viatra.runtime.api.IQuerySpecification; | ||
17 | import tools.refinery.viatra.runtime.api.IRunOnceQueryEngine; | ||
18 | import tools.refinery.viatra.runtime.api.ViatraQueryEngine; | ||
19 | import tools.refinery.viatra.runtime.api.ViatraQueryMatcher; | ||
20 | import tools.refinery.viatra.runtime.api.ViatraQueryModelUpdateListener; | ||
21 | import tools.refinery.viatra.runtime.base.api.BaseIndexOptions; | ||
22 | import tools.refinery.viatra.runtime.emf.EMFScope; | ||
23 | |||
24 | /** | ||
25 | * Run-once query engines can be used to retrieve the current match set of query specifications | ||
26 | * in a given scope. The engine is initialized with a {@link Notifier} as scope and a base index options | ||
27 | * that specifically allows traversing derived features that are not well-behaving. | ||
28 | * | ||
29 | * @author Abel Hegedus | ||
30 | * | ||
31 | */ | ||
32 | public class RunOnceQueryEngine implements IRunOnceQueryEngine { | ||
33 | |||
34 | /** | ||
35 | * If the model changes, we know that a resampling is required. | ||
36 | * | ||
37 | * @author Abel Hegedus | ||
38 | * | ||
39 | */ | ||
40 | private final class RunOnceSamplingModelUpdateListener implements ViatraQueryModelUpdateListener { | ||
41 | @Override | ||
42 | public void notifyChanged(ChangeLevel changeLevel) { | ||
43 | // any model change may require re-sampling | ||
44 | reSamplingNeeded = true; | ||
45 | } | ||
46 | |||
47 | @Override | ||
48 | public ChangeLevel getLevel() { | ||
49 | return ChangeLevel.MODEL; | ||
50 | } | ||
51 | } | ||
52 | |||
53 | /** | ||
54 | * Override the default base index options to allow traversing and indexing derived features | ||
55 | * that would be problematic in incremental evaluation. | ||
56 | * | ||
57 | * @author Abel Hegedus | ||
58 | * | ||
59 | */ | ||
60 | private static final class RunOnceBaseIndexOptions extends BaseIndexOptions { | ||
61 | |||
62 | public RunOnceBaseIndexOptions() { | ||
63 | this.traverseOnlyWellBehavingDerivedFeatures = false; | ||
64 | } | ||
65 | |||
66 | } | ||
67 | |||
68 | /** | ||
69 | * The scope of the engine that is used when creating one-time {@link ViatraQueryEngine}s. | ||
70 | */ | ||
71 | private Notifier notifier; | ||
72 | /** | ||
73 | * The options that are used for initializing the {@link ViatraQueryEngine}. | ||
74 | */ | ||
75 | private RunOnceBaseIndexOptions baseIndexOptions; | ||
76 | private AdvancedViatraQueryEngine engine; | ||
77 | private boolean reSamplingNeeded = false; | ||
78 | protected boolean samplingMode = false; | ||
79 | private RunOnceSamplingModelUpdateListener modelUpdateListener; | ||
80 | |||
81 | /** | ||
82 | * Creates a run-once query engine on the given notifier. | ||
83 | */ | ||
84 | public RunOnceQueryEngine(Notifier notifier) { | ||
85 | this.notifier = notifier; | ||
86 | this.baseIndexOptions = new RunOnceBaseIndexOptions(); | ||
87 | } | ||
88 | |||
89 | @Override | ||
90 | public <Match extends IPatternMatch> Collection<Match> getAllMatches( | ||
91 | IQuerySpecification<? extends ViatraQueryMatcher<Match>> querySpecification) { | ||
92 | |||
93 | if(samplingMode && reSamplingNeeded && engine != null) { | ||
94 | // engine exists from earlier, but may need resampling if model changed | ||
95 | engine.getBaseIndex().resampleDerivedFeatures(); | ||
96 | } else { | ||
97 | // create new engine if it doesn't exists | ||
98 | //TODO correct scope handling | ||
99 | engine = AdvancedViatraQueryEngine.createUnmanagedEngine(new EMFScope(notifier, baseIndexOptions)); | ||
100 | } | ||
101 | ViatraQueryMatcher<Match> matcher = engine.getMatcher(querySpecification); | ||
102 | Collection<Match> allMatches = matcher.getAllMatches(); | ||
103 | if(samplingMode) { | ||
104 | engine.addModelUpdateListener(modelUpdateListener); | ||
105 | } else { | ||
106 | engine.dispose(); | ||
107 | engine = null; | ||
108 | } | ||
109 | return allMatches; | ||
110 | } | ||
111 | |||
112 | @Override | ||
113 | public BaseIndexOptions getBaseIndexOptions() { | ||
114 | return baseIndexOptions; | ||
115 | } | ||
116 | |||
117 | @Override | ||
118 | public Notifier getScope() { | ||
119 | return notifier; | ||
120 | } | ||
121 | |||
122 | @Override | ||
123 | public void setAutomaticResampling(boolean automaticResampling) { | ||
124 | samplingMode = automaticResampling; | ||
125 | if(automaticResampling) { | ||
126 | if (modelUpdateListener == null) { | ||
127 | modelUpdateListener = new RunOnceSamplingModelUpdateListener(); | ||
128 | } | ||
129 | } else if(engine != null) { | ||
130 | engine.dispose(); | ||
131 | engine = null; | ||
132 | } | ||
133 | } | ||
134 | |||
135 | @Override | ||
136 | public void resampleOnNextCall() { | ||
137 | reSamplingNeeded = true; | ||
138 | } | ||
139 | |||
140 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/scope/IIndexingErrorListener.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/scope/IIndexingErrorListener.java index d144bba6..f61a5edb 100644 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/scope/IIndexingErrorListener.java +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/scope/IIndexingErrorListener.java | |||
@@ -3,17 +3,15 @@ | |||
3 | * This program and the accompanying materials are made available under the | 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 | 4 | * terms of the Eclipse Public License v. 2.0 which is available at |
5 | * http://www.eclipse.org/legal/epl-v20.html. | 5 | * http://www.eclipse.org/legal/epl-v20.html. |
6 | * | 6 | * |
7 | * SPDX-License-Identifier: EPL-2.0 | 7 | * SPDX-License-Identifier: EPL-2.0 |
8 | *******************************************************************************/ | 8 | *******************************************************************************/ |
9 | package tools.refinery.viatra.runtime.api.scope; | 9 | package tools.refinery.viatra.runtime.api.scope; |
10 | 10 | ||
11 | import tools.refinery.viatra.runtime.base.api.NavigationHelper; | ||
12 | |||
13 | /** | 11 | /** |
14 | * | 12 | * |
15 | * This interface contains callbacks for various internal errors from the {@link NavigationHelper base index}. | 13 | * This interface contains callbacks for various internal errors from the {@link NavigationHelper base index}. |
16 | * | 14 | * |
17 | * @author Zoltan Ujhelyi | 15 | * @author Zoltan Ujhelyi |
18 | * @since 0.9 | 16 | * @since 0.9 |
19 | * | 17 | * |
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/DynamicEMFQueryRuntimeContext.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/DynamicEMFQueryRuntimeContext.java deleted file mode 100644 index a6da213e..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/DynamicEMFQueryRuntimeContext.java +++ /dev/null | |||
@@ -1,47 +0,0 @@ | |||
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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.emf; | ||
10 | |||
11 | import org.apache.log4j.Logger; | ||
12 | import tools.refinery.viatra.runtime.base.api.NavigationHelper; | ||
13 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
14 | import tools.refinery.viatra.runtime.matchers.tuple.Tuples; | ||
15 | |||
16 | /** | ||
17 | * In dynamic EMF mode, we need to make sure that EEnum literal constants and values returned by eval() expressions | ||
18 | * are canonicalized in the same way as enum literals from the EMF model. | ||
19 | * | ||
20 | * <p> This canonicalization is a one-way mapping, so | ||
21 | * {@link #unwrapElement(Object)} and {@link #unwrapTuple(Object)} remain NOPs. | ||
22 | * | ||
23 | * @author Bergmann Gabor | ||
24 | * | ||
25 | */ | ||
26 | public class DynamicEMFQueryRuntimeContext extends EMFQueryRuntimeContext { | ||
27 | |||
28 | public DynamicEMFQueryRuntimeContext(NavigationHelper baseIndex, Logger logger, EMFScope emfScope) { | ||
29 | super(baseIndex, logger, emfScope); | ||
30 | } | ||
31 | |||
32 | @Override | ||
33 | public Object wrapElement(Object externalElement) { | ||
34 | return baseIndex.toCanonicalValueRepresentation(externalElement); | ||
35 | } | ||
36 | |||
37 | @Override | ||
38 | public Tuple wrapTuple(Tuple externalElements) { | ||
39 | Object[] elements = externalElements.getElements(); | ||
40 | for (int i=0; i< elements.length; ++i) | ||
41 | elements[i] = wrapElement(elements[i]); | ||
42 | return Tuples.flatTupleOf(elements); | ||
43 | } | ||
44 | |||
45 | |||
46 | |||
47 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/EMFBaseIndexWrapper.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/EMFBaseIndexWrapper.java deleted file mode 100644 index 433c5f72..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/EMFBaseIndexWrapper.java +++ /dev/null | |||
@@ -1,160 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.emf; | ||
10 | |||
11 | import java.lang.reflect.InvocationTargetException; | ||
12 | import java.util.HashMap; | ||
13 | import java.util.Map; | ||
14 | import java.util.concurrent.Callable; | ||
15 | |||
16 | import org.eclipse.emf.common.notify.Notification; | ||
17 | import org.eclipse.emf.ecore.EObject; | ||
18 | import org.eclipse.emf.ecore.EStructuralFeature; | ||
19 | import tools.refinery.viatra.runtime.api.scope.IBaseIndex; | ||
20 | import tools.refinery.viatra.runtime.api.scope.IIndexingErrorListener; | ||
21 | import tools.refinery.viatra.runtime.api.scope.IInstanceObserver; | ||
22 | import tools.refinery.viatra.runtime.api.scope.ViatraBaseIndexChangeListener; | ||
23 | import tools.refinery.viatra.runtime.base.api.EMFBaseIndexChangeListener; | ||
24 | import tools.refinery.viatra.runtime.base.api.IEMFIndexingErrorListener; | ||
25 | import tools.refinery.viatra.runtime.base.api.LightweightEObjectObserver; | ||
26 | import tools.refinery.viatra.runtime.base.api.NavigationHelper; | ||
27 | |||
28 | /** | ||
29 | * Wraps the EMF base index into the IBaseIndex interface. | ||
30 | * @author Bergmann Gabor | ||
31 | * | ||
32 | */ | ||
33 | public class EMFBaseIndexWrapper implements IBaseIndex { | ||
34 | |||
35 | private final NavigationHelper navigationHelper; | ||
36 | /** | ||
37 | * @return the underlying index object | ||
38 | */ | ||
39 | public NavigationHelper getNavigationHelper() { | ||
40 | return navigationHelper; | ||
41 | } | ||
42 | |||
43 | /** | ||
44 | * @param navigationHelper | ||
45 | */ | ||
46 | public EMFBaseIndexWrapper(NavigationHelper navigationHelper) { | ||
47 | this.navigationHelper = navigationHelper; | ||
48 | } | ||
49 | |||
50 | @Override | ||
51 | public void resampleDerivedFeatures() { | ||
52 | navigationHelper.resampleDerivedFeatures(); | ||
53 | } | ||
54 | |||
55 | |||
56 | @Override | ||
57 | public <V> V coalesceTraversals(Callable<V> callable) throws InvocationTargetException { | ||
58 | return navigationHelper.coalesceTraversals(callable); | ||
59 | } | ||
60 | |||
61 | Map<IIndexingErrorListener, IEMFIndexingErrorListener> indexErrorListeners = | ||
62 | new HashMap<IIndexingErrorListener, IEMFIndexingErrorListener>(); | ||
63 | @Override | ||
64 | public boolean addIndexingErrorListener(final IIndexingErrorListener listener) { | ||
65 | if (indexErrorListeners.containsKey(listener)) return false; | ||
66 | IEMFIndexingErrorListener emfListener = new IEMFIndexingErrorListener() { | ||
67 | @Override | ||
68 | public void fatal(String description, Throwable t) { | ||
69 | listener.fatal(description, t); | ||
70 | } | ||
71 | @Override | ||
72 | public void error(String description, Throwable t) { | ||
73 | listener.error(description, t); | ||
74 | } | ||
75 | }; | ||
76 | indexErrorListeners.put(listener, emfListener); | ||
77 | return navigationHelper.addIndexingErrorListener(emfListener); | ||
78 | } | ||
79 | @Override | ||
80 | public boolean removeIndexingErrorListener(IIndexingErrorListener listener) { | ||
81 | if (!indexErrorListeners.containsKey(listener)) return false; | ||
82 | return navigationHelper.removeIndexingErrorListener(indexErrorListeners.remove(listener)); | ||
83 | } | ||
84 | |||
85 | |||
86 | Map<ViatraBaseIndexChangeListener, EMFBaseIndexChangeListener> indexChangeListeners = | ||
87 | new HashMap<ViatraBaseIndexChangeListener, EMFBaseIndexChangeListener>(); | ||
88 | @Override | ||
89 | public void addBaseIndexChangeListener(final ViatraBaseIndexChangeListener listener) { | ||
90 | EMFBaseIndexChangeListener emfListener = new EMFBaseIndexChangeListener() { | ||
91 | @Override | ||
92 | public boolean onlyOnIndexChange() { | ||
93 | return listener.onlyOnIndexChange(); | ||
94 | } | ||
95 | |||
96 | @Override | ||
97 | public void notifyChanged(boolean indexChanged) { | ||
98 | listener.notifyChanged(indexChanged); | ||
99 | } | ||
100 | }; | ||
101 | indexChangeListeners.put(listener, emfListener); | ||
102 | navigationHelper.addBaseIndexChangeListener(emfListener); | ||
103 | } | ||
104 | @Override | ||
105 | public void removeBaseIndexChangeListener(ViatraBaseIndexChangeListener listener) { | ||
106 | final EMFBaseIndexChangeListener cListener = indexChangeListeners.remove(listener); | ||
107 | if (cListener != null) | ||
108 | navigationHelper.removeBaseIndexChangeListener(cListener); | ||
109 | } | ||
110 | |||
111 | Map<IInstanceObserver, EObjectObserver> instanceObservers = | ||
112 | new HashMap<IInstanceObserver, EObjectObserver>(); | ||
113 | @Override | ||
114 | public boolean addInstanceObserver(final IInstanceObserver observer, | ||
115 | Object observedObject) { | ||
116 | if (observedObject instanceof EObject) { | ||
117 | EObjectObserver emfObserver = instanceObservers.computeIfAbsent(observer, EObjectObserver::new); | ||
118 | boolean success = | ||
119 | navigationHelper.addLightweightEObjectObserver(emfObserver, (EObject) observedObject); | ||
120 | if (success) emfObserver.usageCount++; | ||
121 | return success; | ||
122 | } else return false; | ||
123 | } | ||
124 | @Override | ||
125 | public boolean removeInstanceObserver(IInstanceObserver observer, | ||
126 | Object observedObject) { | ||
127 | if (observedObject instanceof EObject) { | ||
128 | EObjectObserver emfObserver = instanceObservers.get(observer); | ||
129 | if (emfObserver == null) | ||
130 | return false; | ||
131 | boolean success = | ||
132 | navigationHelper.removeLightweightEObjectObserver(emfObserver, (EObject)observedObject); | ||
133 | if (success) | ||
134 | if (0 == --emfObserver.usageCount) | ||
135 | instanceObservers.remove(observer); | ||
136 | return success; | ||
137 | } else return false; | ||
138 | } | ||
139 | private static class EObjectObserver implements LightweightEObjectObserver { | ||
140 | /** | ||
141 | * | ||
142 | */ | ||
143 | private final IInstanceObserver observer; | ||
144 | int usageCount = 0; | ||
145 | |||
146 | /** | ||
147 | * @param observer | ||
148 | */ | ||
149 | private EObjectObserver(IInstanceObserver observer) { | ||
150 | this.observer = observer; | ||
151 | } | ||
152 | |||
153 | @Override | ||
154 | public void notifyFeatureChanged(EObject host, | ||
155 | EStructuralFeature feature, Notification notification) { | ||
156 | observer.notifyBinaryChanged(host, feature); | ||
157 | } | ||
158 | } | ||
159 | |||
160 | } \ No newline at end of file | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/EMFEngineContext.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/EMFEngineContext.java deleted file mode 100644 index 5fe9e23a..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/EMFEngineContext.java +++ /dev/null | |||
@@ -1,110 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Bergmann Gabor, Denes Harmath, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.emf; | ||
10 | |||
11 | import org.apache.log4j.Logger; | ||
12 | import org.eclipse.emf.common.notify.Notifier; | ||
13 | import tools.refinery.viatra.runtime.api.ViatraQueryEngine; | ||
14 | import tools.refinery.viatra.runtime.api.scope.IBaseIndex; | ||
15 | import tools.refinery.viatra.runtime.api.scope.IEngineContext; | ||
16 | import tools.refinery.viatra.runtime.api.scope.IIndexingErrorListener; | ||
17 | import tools.refinery.viatra.runtime.base.api.ViatraBaseFactory; | ||
18 | import tools.refinery.viatra.runtime.base.api.NavigationHelper; | ||
19 | import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException; | ||
20 | import tools.refinery.viatra.runtime.matchers.context.IQueryRuntimeContext; | ||
21 | |||
22 | /** | ||
23 | * Implements an engine context on EMF models. | ||
24 | * @author Bergmann Gabor | ||
25 | * | ||
26 | */ | ||
27 | class EMFEngineContext implements IEngineContext { | ||
28 | |||
29 | private final EMFScope emfScope; | ||
30 | ViatraQueryEngine engine; | ||
31 | Logger logger; | ||
32 | NavigationHelper navHelper; | ||
33 | IBaseIndex baseIndex; | ||
34 | IIndexingErrorListener taintListener; | ||
35 | private EMFQueryRuntimeContext runtimeContext; | ||
36 | |||
37 | public EMFEngineContext(EMFScope emfScope, ViatraQueryEngine engine, IIndexingErrorListener taintListener, Logger logger) { | ||
38 | this.emfScope = emfScope; | ||
39 | this.engine = engine; | ||
40 | this.logger = logger; | ||
41 | this.taintListener = taintListener; | ||
42 | } | ||
43 | |||
44 | /** | ||
45 | * @throws ViatraQueryRuntimeException thrown if the navigation helper cannot be initialized | ||
46 | */ | ||
47 | public NavigationHelper getNavHelper() { | ||
48 | return getNavHelper(true); | ||
49 | } | ||
50 | |||
51 | private NavigationHelper getNavHelper(boolean ensureInitialized) { | ||
52 | if (navHelper == null) { | ||
53 | // sync to avoid crazy compiler reordering which would matter if derived features use VIATRA and call this | ||
54 | // reentrantly | ||
55 | synchronized (this) { | ||
56 | navHelper = ViatraBaseFactory.getInstance().createNavigationHelper(null, this.emfScope.getOptions(), | ||
57 | logger); | ||
58 | getBaseIndex().addIndexingErrorListener(taintListener); | ||
59 | } | ||
60 | |||
61 | if (ensureInitialized) { | ||
62 | ensureIndexLoaded(); | ||
63 | } | ||
64 | |||
65 | } | ||
66 | return navHelper; | ||
67 | } | ||
68 | |||
69 | private void ensureIndexLoaded() { | ||
70 | for (Notifier scopeRoot : this.emfScope.getScopeRoots()) { | ||
71 | navHelper.addRoot(scopeRoot); | ||
72 | } | ||
73 | } | ||
74 | |||
75 | @Override | ||
76 | public IQueryRuntimeContext getQueryRuntimeContext() { | ||
77 | NavigationHelper nh = getNavHelper(false); | ||
78 | if (runtimeContext == null) { | ||
79 | runtimeContext = | ||
80 | emfScope.getOptions().isDynamicEMFMode() ? | ||
81 | new DynamicEMFQueryRuntimeContext(nh, logger, emfScope) : | ||
82 | new EMFQueryRuntimeContext(nh, logger, emfScope); | ||
83 | |||
84 | ensureIndexLoaded(); | ||
85 | } | ||
86 | |||
87 | return runtimeContext; | ||
88 | } | ||
89 | |||
90 | @Override | ||
91 | public void dispose() { | ||
92 | if (runtimeContext != null) runtimeContext.dispose(); | ||
93 | if (navHelper != null) navHelper.dispose(); | ||
94 | |||
95 | this.baseIndex = null; | ||
96 | this.engine = null; | ||
97 | this.logger = null; | ||
98 | this.navHelper = null; | ||
99 | } | ||
100 | |||
101 | |||
102 | @Override | ||
103 | public IBaseIndex getBaseIndex() { | ||
104 | if (baseIndex == null) { | ||
105 | final NavigationHelper navigationHelper = getNavHelper(); | ||
106 | baseIndex = new EMFBaseIndexWrapper(navigationHelper); | ||
107 | } | ||
108 | return baseIndex; | ||
109 | } | ||
110 | } \ No newline at end of file | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/EMFQueryMetaContext.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/EMFQueryMetaContext.java deleted file mode 100644 index c316d308..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/EMFQueryMetaContext.java +++ /dev/null | |||
@@ -1,405 +0,0 @@ | |||
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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.emf; | ||
10 | |||
11 | import java.util.Arrays; | ||
12 | import java.util.Collection; | ||
13 | import java.util.Collections; | ||
14 | import java.util.Comparator; | ||
15 | import java.util.HashMap; | ||
16 | import java.util.HashSet; | ||
17 | import java.util.Map; | ||
18 | import java.util.Set; | ||
19 | |||
20 | import org.eclipse.emf.common.util.EList; | ||
21 | import org.eclipse.emf.ecore.EAttribute; | ||
22 | import org.eclipse.emf.ecore.EClass; | ||
23 | import org.eclipse.emf.ecore.EClassifier; | ||
24 | import org.eclipse.emf.ecore.EDataType; | ||
25 | import org.eclipse.emf.ecore.EObject; | ||
26 | import org.eclipse.emf.ecore.EReference; | ||
27 | import org.eclipse.emf.ecore.EStructuralFeature; | ||
28 | import org.eclipse.emf.ecore.EcorePackage; | ||
29 | import tools.refinery.viatra.runtime.emf.types.BaseEMFTypeKey; | ||
30 | import tools.refinery.viatra.runtime.emf.types.EClassTransitiveInstancesKey; | ||
31 | import tools.refinery.viatra.runtime.emf.types.EClassUnscopedTransitiveInstancesKey; | ||
32 | import tools.refinery.viatra.runtime.emf.types.EDataTypeInSlotsKey; | ||
33 | import tools.refinery.viatra.runtime.emf.types.EStructuralFeatureInstancesKey; | ||
34 | import tools.refinery.viatra.runtime.matchers.context.AbstractQueryMetaContext; | ||
35 | import tools.refinery.viatra.runtime.matchers.context.IInputKey; | ||
36 | import tools.refinery.viatra.runtime.matchers.context.InputKeyImplication; | ||
37 | import tools.refinery.viatra.runtime.matchers.context.common.JavaTransitiveInstancesKey; | ||
38 | |||
39 | /** | ||
40 | * The meta context information for EMF scopes. | ||
41 | * | ||
42 | * <p> The runtime context may specialize answers with a given scope. | ||
43 | * In a static context, a conservative default version ({@link #DEFAULT}) can be used instead. | ||
44 | * | ||
45 | * <p> TODO generics? | ||
46 | * @author Bergmann Gabor | ||
47 | * | ||
48 | */ | ||
49 | public final class EMFQueryMetaContext extends AbstractQueryMetaContext { | ||
50 | |||
51 | /** | ||
52 | * Default static instance that only makes conservative assumptions that are valid for any {@link EMFScope} (but not if objects are used). | ||
53 | * @since 1.6 | ||
54 | */ | ||
55 | public static final EMFQueryMetaContext DEFAULT = new EMFQueryMetaContext(false, true, UnscopedTypeSupport.EMIT_ALWAYS); | ||
56 | |||
57 | /** | ||
58 | * Default static instance that only makes conservative assumptions that are valid for any scope, even with surrogate objects. | ||
59 | * Unscoped types are used for inference, but not emitted as replacement candidates, as they cannot be checked at runtime. | ||
60 | * @since 2.1 | ||
61 | */ | ||
62 | public static final EMFQueryMetaContext DEFAULT_SURROGATE = new EMFQueryMetaContext(false, true, UnscopedTypeSupport.EMIT_EXCEPT_AS_WEAKENED_REPLACEMENT); | ||
63 | |||
64 | |||
65 | private static final EClass EOBJECT_CLASS = | ||
66 | EcorePackage.eINSTANCE.getEObject(); | ||
67 | private static final EClassTransitiveInstancesKey EOBJECT_SCOPED_KEY = | ||
68 | new EClassTransitiveInstancesKey(EOBJECT_CLASS); | ||
69 | private static final EClassUnscopedTransitiveInstancesKey EOBJECT_UNSCOPED_KEY = | ||
70 | new EClassUnscopedTransitiveInstancesKey(EOBJECT_CLASS); | ||
71 | |||
72 | private boolean assumeNonDangling; | ||
73 | private boolean subResourceScopeSplit; | ||
74 | private UnscopedTypeSupport emitUnscopedEClassTypes; | ||
75 | |||
76 | private enum UnscopedTypeSupport { | ||
77 | EMIT_ALWAYS, | ||
78 | EMIT_EXCEPT_AS_WEAKENED_REPLACEMENT, | ||
79 | EMIT_NEVER | ||
80 | } | ||
81 | |||
82 | |||
83 | /** | ||
84 | * Instantiates a specialized meta information that is aware of scope-specific details. | ||
85 | * Note that this API is not stable and thus non-public. | ||
86 | * | ||
87 | * @param assumeNonDangling assumes that all cross-references are non-dangling (do not lead out of scope), no matter what | ||
88 | * @param subResourceScopeSplit the scope granularity may be finer than resource-level, i.e. proxy-non-resolving references can lead out of scope | ||
89 | * @param emitUnscopedEClassTypes if requested, the metacontext will suppress unscoped input keys; this is recommended if surrogates are used instead of EObjects | ||
90 | */ | ||
91 | EMFQueryMetaContext(boolean assumeNonDangling, boolean subResourceScopeSplit, UnscopedTypeSupport emitUnscopedEClassTypes) { | ||
92 | this.assumeNonDangling = assumeNonDangling; | ||
93 | this.subResourceScopeSplit = subResourceScopeSplit; | ||
94 | this.emitUnscopedEClassTypes = emitUnscopedEClassTypes; | ||
95 | } | ||
96 | |||
97 | /** | ||
98 | * Instantiates a specialized meta information that is aware of scope-specific details. | ||
99 | * @since 2.1 | ||
100 | */ | ||
101 | public EMFQueryMetaContext(EMFScope scope) { | ||
102 | this(scope.getOptions().isDanglingFreeAssumption(), | ||
103 | scope.getScopeRoots().size()==1 && scope.getScopeRoots().iterator().next() instanceof EObject, | ||
104 | UnscopedTypeSupport.EMIT_ALWAYS); | ||
105 | } | ||
106 | |||
107 | |||
108 | @Override | ||
109 | public boolean isEnumerable(IInputKey key) { | ||
110 | ensureValidKey(key); | ||
111 | return key.isEnumerable(); | ||
112 | // if (key instanceof JavaTransitiveInstancesKey) | ||
113 | // return false; | ||
114 | // else | ||
115 | // return true; | ||
116 | } | ||
117 | |||
118 | @Override | ||
119 | public boolean canLeadOutOfScope(IInputKey key) { | ||
120 | ensureValidKey(key); | ||
121 | if (key instanceof EStructuralFeatureInstancesKey) { | ||
122 | EStructuralFeature feature = ((EStructuralFeatureInstancesKey) key).getEmfKey(); | ||
123 | if (feature instanceof EReference){ | ||
124 | return canLeadOutOfScope((EReference) feature); | ||
125 | } | ||
126 | } | ||
127 | return false; | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * Tells whether the given reference may lead out of scope. | ||
132 | * @since 2.1 | ||
133 | */ | ||
134 | public boolean canLeadOutOfScope(EReference reference) { | ||
135 | // Is it possible that this edge is dangling, i.e. its target lies outside of the scope? | ||
136 | // Unless non-dangling is globally assumed, | ||
137 | // proxy-resolving references (incl. containment) might point to proxies and are thus considered unsafe. | ||
138 | // Additionally, if the scope is sub-resource (containment subtree of object), | ||
139 | // all non-containment edges are also unsafe. | ||
140 | // Note that in case of cross-resource containment, | ||
141 | // the scope includes the contained object even if it is in a foreign resource. | ||
142 | return (!assumeNonDangling) | ||
143 | && (reference.isResolveProxies() || (subResourceScopeSplit && !reference.isContainment())); | ||
144 | } | ||
145 | |||
146 | @Override | ||
147 | public boolean isStateless(IInputKey key) { | ||
148 | ensureValidKey(key); | ||
149 | return key instanceof JavaTransitiveInstancesKey || key instanceof EClassUnscopedTransitiveInstancesKey; | ||
150 | } | ||
151 | |||
152 | @Override | ||
153 | public Map<Set<Integer>, Set<Integer>> getFunctionalDependencies(IInputKey key) { | ||
154 | ensureValidKey(key); | ||
155 | if (key instanceof EStructuralFeatureInstancesKey) { | ||
156 | EStructuralFeature feature = ((EStructuralFeatureInstancesKey) key).getEmfKey(); | ||
157 | final Map<Set<Integer>, Set<Integer>> result = | ||
158 | new HashMap<Set<Integer>, Set<Integer>>(); | ||
159 | if (isFeatureMultiplicityToOne(feature)) | ||
160 | result.put(Collections.singleton(0), Collections.singleton(1)); | ||
161 | if (isFeatureMultiplicityOneTo(feature)) | ||
162 | result.put(Collections.singleton(1), Collections.singleton(0)); | ||
163 | return result; | ||
164 | } else { | ||
165 | return Collections.emptyMap(); | ||
166 | } | ||
167 | } | ||
168 | |||
169 | /** | ||
170 | * @since 2.1 | ||
171 | */ | ||
172 | public EClassTransitiveInstancesKey getSourceTypeKey(EStructuralFeatureInstancesKey key) { | ||
173 | return new EClassTransitiveInstancesKey(key.getEmfKey().getEContainingClass()); | ||
174 | } | ||
175 | /** | ||
176 | * @since 2.1 | ||
177 | */ | ||
178 | public IInputKey getTargetTypeKey(EStructuralFeatureInstancesKey key) { | ||
179 | EStructuralFeature feature = key.getEmfKey(); | ||
180 | if (feature instanceof EAttribute) { | ||
181 | return new EDataTypeInSlotsKey(((EAttribute) feature).getEAttributeType()); | ||
182 | } else if (feature instanceof EReference) { | ||
183 | EClass eReferenceType = ((EReference) feature).getEReferenceType(); | ||
184 | if (canLeadOutOfScope(key)) { | ||
185 | return new EClassUnscopedTransitiveInstancesKey(eReferenceType); | ||
186 | } else { | ||
187 | return new EClassTransitiveInstancesKey(eReferenceType); | ||
188 | } | ||
189 | } else throw new IllegalArgumentException(); | ||
190 | } | ||
191 | |||
192 | @Override | ||
193 | public Collection<InputKeyImplication> getImplications(IInputKey implyingKey) { | ||
194 | ensureValidKey(implyingKey); | ||
195 | Collection<InputKeyImplication> result = new HashSet<InputKeyImplication>(); | ||
196 | |||
197 | if (implyingKey instanceof EClassTransitiveInstancesKey) { | ||
198 | EClass eClass = ((EClassTransitiveInstancesKey) implyingKey).getEmfKey(); | ||
199 | |||
200 | // direct eSuperClasses | ||
201 | EList<EClass> directSuperTypes = eClass.getESuperTypes(); | ||
202 | if (!directSuperTypes.isEmpty()) { | ||
203 | for (EClass superType : directSuperTypes) { | ||
204 | final EClassTransitiveInstancesKey implied = new EClassTransitiveInstancesKey(superType); | ||
205 | result.add(new InputKeyImplication(implyingKey, implied, Arrays.asList(0))); | ||
206 | } | ||
207 | } else { | ||
208 | if (!EOBJECT_SCOPED_KEY.equals(implyingKey)) { | ||
209 | result.add(new InputKeyImplication(implyingKey, EOBJECT_SCOPED_KEY, Arrays.asList(0))); | ||
210 | } | ||
211 | } | ||
212 | // implies unscoped | ||
213 | if (UnscopedTypeSupport.EMIT_NEVER != emitUnscopedEClassTypes) | ||
214 | result.add(new InputKeyImplication(implyingKey, | ||
215 | new EClassUnscopedTransitiveInstancesKey(eClass), | ||
216 | Arrays.asList(0))); | ||
217 | } else if (implyingKey instanceof EClassUnscopedTransitiveInstancesKey) { | ||
218 | EClass eClass = ((EClassUnscopedTransitiveInstancesKey) implyingKey).getEmfKey(); | ||
219 | |||
220 | // direct eSuperClasses | ||
221 | EList<EClass> directSuperTypes = eClass.getESuperTypes(); | ||
222 | if (!directSuperTypes.isEmpty()) { | ||
223 | for (EClass superType : directSuperTypes) { | ||
224 | final EClassUnscopedTransitiveInstancesKey implied = new EClassUnscopedTransitiveInstancesKey( | ||
225 | superType); | ||
226 | result.add(new InputKeyImplication(implyingKey, implied, Arrays.asList(0))); | ||
227 | } | ||
228 | } else { | ||
229 | if (!EOBJECT_UNSCOPED_KEY.equals(implyingKey)) { | ||
230 | result.add(new InputKeyImplication(implyingKey, EOBJECT_UNSCOPED_KEY, Arrays.asList(0))); | ||
231 | } | ||
232 | } | ||
233 | |||
234 | } else if (implyingKey instanceof JavaTransitiveInstancesKey) { | ||
235 | Class<?> instanceClass = ((JavaTransitiveInstancesKey) implyingKey).getInstanceClass(); | ||
236 | if (instanceClass != null) { // resolution successful | ||
237 | // direct Java superClass | ||
238 | Class<?> superclass = instanceClass.getSuperclass(); | ||
239 | if (superclass != null) { | ||
240 | JavaTransitiveInstancesKey impliedSuper = new JavaTransitiveInstancesKey(superclass); | ||
241 | result.add(new InputKeyImplication(implyingKey, impliedSuper, Arrays.asList(0))); | ||
242 | } | ||
243 | |||
244 | // direct Java superInterfaces | ||
245 | for (Class<?> superInterface : instanceClass.getInterfaces()) { | ||
246 | if (superInterface != null) { | ||
247 | JavaTransitiveInstancesKey impliedInterface = new JavaTransitiveInstancesKey(superInterface); | ||
248 | result.add(new InputKeyImplication(implyingKey, impliedInterface, Arrays.asList(0))); | ||
249 | } | ||
250 | } | ||
251 | } | ||
252 | |||
253 | } else if (implyingKey instanceof EStructuralFeatureInstancesKey) { | ||
254 | EStructuralFeature feature = ((EStructuralFeatureInstancesKey) implyingKey).getEmfKey(); | ||
255 | |||
256 | // source and target type | ||
257 | final EClass sourceType = featureSourceType(feature); | ||
258 | final EClassTransitiveInstancesKey impliedSource = new EClassTransitiveInstancesKey(sourceType); | ||
259 | final EClassifier targetType = featureTargetType(feature); | ||
260 | final IInputKey impliedTarget; | ||
261 | if (feature instanceof EReference) { | ||
262 | EReference reference = (EReference) feature; | ||
263 | |||
264 | if (!canLeadOutOfScope(reference)) { | ||
265 | impliedTarget = new EClassTransitiveInstancesKey((EClass) targetType); | ||
266 | } else { | ||
267 | impliedTarget = (UnscopedTypeSupport.EMIT_NEVER != emitUnscopedEClassTypes) ? | ||
268 | new EClassUnscopedTransitiveInstancesKey((EClass) targetType) | ||
269 | : null; | ||
270 | } | ||
271 | } else { // EDatatype | ||
272 | impliedTarget = new EDataTypeInSlotsKey((EDataType) targetType); | ||
273 | } | ||
274 | |||
275 | result.add(new InputKeyImplication(implyingKey, impliedSource, Arrays.asList(0))); | ||
276 | if (impliedTarget != null) | ||
277 | result.add(new InputKeyImplication(implyingKey, impliedTarget, Arrays.asList(1))); | ||
278 | |||
279 | // opposite | ||
280 | EReference opposite = featureOpposite(feature); | ||
281 | if (opposite != null && !canLeadOutOfScope((EReference) feature)) { | ||
282 | EStructuralFeatureInstancesKey impliedOpposite = new EStructuralFeatureInstancesKey(opposite); | ||
283 | result.add(new InputKeyImplication(implyingKey, impliedOpposite, Arrays.asList(1, 0))); | ||
284 | } | ||
285 | |||
286 | // containment | ||
287 | // TODO | ||
288 | } else if (implyingKey instanceof EDataTypeInSlotsKey) { | ||
289 | EDataType dataType = ((EDataTypeInSlotsKey) implyingKey).getEmfKey(); | ||
290 | |||
291 | // instance class of datatype | ||
292 | // TODO this can have a generation gap! (could be some dynamic EMF impl or whatever) | ||
293 | Class<?> instanceClass = dataType.getInstanceClass(); | ||
294 | if (instanceClass != null) { | ||
295 | JavaTransitiveInstancesKey implied = new JavaTransitiveInstancesKey(instanceClass); | ||
296 | result.add(new InputKeyImplication(implyingKey, implied, Arrays.asList(0))); | ||
297 | } | ||
298 | } else { | ||
299 | illegalInputKey(implyingKey); | ||
300 | } | ||
301 | |||
302 | return result; | ||
303 | } | ||
304 | |||
305 | @Override | ||
306 | public Map<InputKeyImplication, Set<InputKeyImplication>> getConditionalImplications(IInputKey implyingKey) { | ||
307 | ensureValidKey(implyingKey); | ||
308 | if (implyingKey instanceof EClassUnscopedTransitiveInstancesKey) { | ||
309 | EClass emfKey = ((EClassUnscopedTransitiveInstancesKey) implyingKey).getEmfKey(); | ||
310 | |||
311 | Map<InputKeyImplication, Set<InputKeyImplication>> result = new HashMap<>(); | ||
312 | result.put( | ||
313 | new InputKeyImplication(implyingKey, EOBJECT_SCOPED_KEY, Arrays.asList(0)), | ||
314 | new HashSet<>(Arrays.asList(new InputKeyImplication(implyingKey, new EClassTransitiveInstancesKey(emfKey), Arrays.asList(0)))) | ||
315 | ); | ||
316 | return result; | ||
317 | } else return super.getConditionalImplications(implyingKey); | ||
318 | } | ||
319 | |||
320 | @Override | ||
321 | public Collection<InputKeyImplication> getWeakenedAlternatives(IInputKey implyingKey) { | ||
322 | ensureValidKey(implyingKey); | ||
323 | if (UnscopedTypeSupport.EMIT_ALWAYS == emitUnscopedEClassTypes && implyingKey instanceof EClassTransitiveInstancesKey) { | ||
324 | EClass emfKey = ((EClassTransitiveInstancesKey) implyingKey).getEmfKey(); | ||
325 | |||
326 | Collection<InputKeyImplication> result = new HashSet<InputKeyImplication>(); | ||
327 | result.add( | ||
328 | // in some cases, filtering by the the unscoped key may be sufficient | ||
329 | new InputKeyImplication(implyingKey, new EClassUnscopedTransitiveInstancesKey(emfKey), Arrays.asList(0)) | ||
330 | ); | ||
331 | return result; | ||
332 | } else return super.getWeakenedAlternatives(implyingKey); | ||
333 | } | ||
334 | |||
335 | public void ensureValidKey(IInputKey key) { | ||
336 | if (! (key instanceof BaseEMFTypeKey<?>) && ! (key instanceof JavaTransitiveInstancesKey)) | ||
337 | illegalInputKey(key); | ||
338 | } | ||
339 | |||
340 | public void illegalInputKey(IInputKey key) { | ||
341 | throw new IllegalArgumentException("The input key " + key + " is not a valid EMF input key."); | ||
342 | } | ||
343 | |||
344 | public boolean isFeatureMultiplicityToOne(EStructuralFeature feature) { | ||
345 | return !feature.isMany(); | ||
346 | } | ||
347 | |||
348 | public boolean isFeatureMultiplicityOneTo(EStructuralFeature typeObject) { | ||
349 | if (typeObject instanceof EReference) { | ||
350 | final EReference feature = (EReference)typeObject; | ||
351 | final EReference eOpposite = feature.getEOpposite(); | ||
352 | return feature.isContainment() || (eOpposite != null && !eOpposite.isMany()); | ||
353 | } else return false; | ||
354 | } | ||
355 | |||
356 | public EClass featureSourceType(EStructuralFeature feature) { | ||
357 | return feature.getEContainingClass(); | ||
358 | } | ||
359 | public EClassifier featureTargetType(EStructuralFeature typeObject) { | ||
360 | if (typeObject instanceof EAttribute) { | ||
361 | EAttribute attribute = (EAttribute) typeObject; | ||
362 | return attribute.getEAttributeType(); | ||
363 | } else if (typeObject instanceof EReference) { | ||
364 | EReference reference = (EReference) typeObject; | ||
365 | return reference.getEReferenceType(); | ||
366 | } else | ||
367 | throw new IllegalArgumentException("typeObject has invalid type " + typeObject.getClass().getName()); | ||
368 | } | ||
369 | public EReference featureOpposite(EStructuralFeature typeObject) { | ||
370 | if (typeObject instanceof EReference) { | ||
371 | EReference reference = (EReference) typeObject; | ||
372 | return reference.getEOpposite(); | ||
373 | } else return null; | ||
374 | } | ||
375 | |||
376 | @Override | ||
377 | public Comparator<IInputKey> getSuggestedEliminationOrdering() { | ||
378 | return SUGGESTED_ELIMINATION_ORDERING; | ||
379 | } | ||
380 | |||
381 | private static final Comparator<IInputKey> SUGGESTED_ELIMINATION_ORDERING = new Comparator<IInputKey>() { | ||
382 | @Override | ||
383 | public int compare(IInputKey o1, IInputKey o2) { | ||
384 | if (o1 instanceof EClassTransitiveInstancesKey && o2 instanceof EClassTransitiveInstancesKey) { | ||
385 | // common EClass types with many instances should be eliminated before rare types | ||
386 | return getRarity((EClassTransitiveInstancesKey)o1) - getRarity((EClassTransitiveInstancesKey)o2); | ||
387 | } else { | ||
388 | return getKeyTypeEliminationSequence(o1) - getKeyTypeEliminationSequence(o2); | ||
389 | } | ||
390 | } | ||
391 | |||
392 | // The more supertypes there are, the more specialized the type | ||
393 | // the more specialized the type, the rarer instances are expected to be found | ||
394 | private int getRarity(EClassTransitiveInstancesKey key) { | ||
395 | return key.getEmfKey().getEAllSuperTypes().size() + (EOBJECT_SCOPED_KEY.equals(key) ? 0 : 1); | ||
396 | } | ||
397 | |||
398 | // Scoped EClass transitive instance keys are attempted to be eliminated before all else | ||
399 | // so that e.g. their unscoped version can eliminate them is variable is known to be scoped | ||
400 | private int getKeyTypeEliminationSequence(IInputKey o1) { | ||
401 | return (o1 instanceof EClassTransitiveInstancesKey) ? -1 : 0; | ||
402 | } | ||
403 | }; | ||
404 | |||
405 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/EMFQueryRuntimeContext.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/EMFQueryRuntimeContext.java deleted file mode 100644 index 7809cd24..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/EMFQueryRuntimeContext.java +++ /dev/null | |||
@@ -1,839 +0,0 @@ | |||
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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.emf; | ||
10 | |||
11 | import java.lang.reflect.InvocationTargetException; | ||
12 | import java.util.Collection; | ||
13 | import java.util.Collections; | ||
14 | import java.util.EnumSet; | ||
15 | import java.util.HashMap; | ||
16 | import java.util.HashSet; | ||
17 | import java.util.Map; | ||
18 | import java.util.Optional; | ||
19 | import java.util.Set; | ||
20 | import java.util.concurrent.Callable; | ||
21 | import java.util.function.Function; | ||
22 | import java.util.stream.Collectors; | ||
23 | |||
24 | import org.apache.log4j.Logger; | ||
25 | import org.eclipse.emf.ecore.EClass; | ||
26 | import org.eclipse.emf.ecore.EDataType; | ||
27 | import org.eclipse.emf.ecore.EObject; | ||
28 | import org.eclipse.emf.ecore.EStructuralFeature; | ||
29 | import tools.refinery.viatra.runtime.base.api.DataTypeListener; | ||
30 | import tools.refinery.viatra.runtime.base.api.FeatureListener; | ||
31 | import tools.refinery.viatra.runtime.base.api.IndexingLevel; | ||
32 | import tools.refinery.viatra.runtime.base.api.InstanceListener; | ||
33 | import tools.refinery.viatra.runtime.base.api.NavigationHelper; | ||
34 | import tools.refinery.viatra.runtime.emf.types.EClassTransitiveInstancesKey; | ||
35 | import tools.refinery.viatra.runtime.emf.types.EClassUnscopedTransitiveInstancesKey; | ||
36 | import tools.refinery.viatra.runtime.emf.types.EDataTypeInSlotsKey; | ||
37 | import tools.refinery.viatra.runtime.emf.types.EStructuralFeatureInstancesKey; | ||
38 | import tools.refinery.viatra.runtime.matchers.context.AbstractQueryRuntimeContext; | ||
39 | import tools.refinery.viatra.runtime.matchers.context.IInputKey; | ||
40 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
41 | import tools.refinery.viatra.runtime.matchers.context.IQueryRuntimeContextListener; | ||
42 | import tools.refinery.viatra.runtime.matchers.context.IndexingService; | ||
43 | import tools.refinery.viatra.runtime.matchers.context.common.JavaTransitiveInstancesKey; | ||
44 | import tools.refinery.viatra.runtime.matchers.tuple.ITuple; | ||
45 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
46 | import tools.refinery.viatra.runtime.matchers.tuple.TupleMask; | ||
47 | import tools.refinery.viatra.runtime.matchers.tuple.Tuples; | ||
48 | import tools.refinery.viatra.runtime.matchers.util.Accuracy; | ||
49 | |||
50 | /** | ||
51 | * The EMF-based runtime query context, backed by an IQBase NavigationHelper. | ||
52 | * | ||
53 | * @author Bergmann Gabor | ||
54 | * | ||
55 | * <p> TODO: {@link #ensureIndexed(EClass)} may be inefficient if supertype already cached. | ||
56 | * @since 1.4 | ||
57 | */ | ||
58 | public class EMFQueryRuntimeContext extends AbstractQueryRuntimeContext { | ||
59 | protected final NavigationHelper baseIndex; | ||
60 | //private BaseIndexListener listener; | ||
61 | |||
62 | protected final Map<EClass, EnumSet<IndexingService>> indexedClasses = new HashMap<>(); | ||
63 | protected final Map<EDataType, EnumSet<IndexingService>> indexedDataTypes = new HashMap<>(); | ||
64 | protected final Map<EStructuralFeature, EnumSet<IndexingService>> indexedFeatures = new HashMap<>(); | ||
65 | |||
66 | protected final EMFQueryMetaContext metaContext; | ||
67 | |||
68 | protected Logger logger; | ||
69 | |||
70 | private EMFScope emfScope; | ||
71 | |||
72 | public EMFQueryRuntimeContext(NavigationHelper baseIndex, Logger logger, EMFScope emfScope) { | ||
73 | this.baseIndex = baseIndex; | ||
74 | this.logger = logger; | ||
75 | this.metaContext = new EMFQueryMetaContext(emfScope); | ||
76 | this.emfScope = emfScope; | ||
77 | } | ||
78 | |||
79 | public EMFScope getEmfScope() { | ||
80 | return emfScope; | ||
81 | } | ||
82 | |||
83 | /** | ||
84 | * Utility method to add an indexing service to a given key. Returns true if the requested service was | ||
85 | * not present before this call. | ||
86 | * @param map | ||
87 | * @param key | ||
88 | * @param service | ||
89 | * @return | ||
90 | */ | ||
91 | private static <K> boolean addIndexingService(Map<K, EnumSet<IndexingService>> map, K key, IndexingService service){ | ||
92 | EnumSet<IndexingService> current = map.get(key); | ||
93 | if (current == null){ | ||
94 | current = EnumSet.of(service); | ||
95 | map.put(key, current); | ||
96 | return true; | ||
97 | }else{ | ||
98 | return current.add(service); | ||
99 | } | ||
100 | } | ||
101 | |||
102 | public void dispose() { | ||
103 | //baseIndex.removeFeatureListener(indexedFeatures, listener); | ||
104 | indexedFeatures.clear(); | ||
105 | //baseIndex.removeInstanceListener(indexedClasses, listener); | ||
106 | indexedClasses.clear(); | ||
107 | //baseIndex.removeDataTypeListener(indexedDataTypes, listener); | ||
108 | indexedDataTypes.clear(); | ||
109 | |||
110 | // No need to remove listeners, as NavHelper will be disposed imminently. | ||
111 | } | ||
112 | |||
113 | @Override | ||
114 | public <V> V coalesceTraversals(Callable<V> callable) throws InvocationTargetException { | ||
115 | return baseIndex.coalesceTraversals(callable); | ||
116 | } | ||
117 | |||
118 | @Override | ||
119 | public boolean isCoalescing() { | ||
120 | return baseIndex.isCoalescing(); | ||
121 | } | ||
122 | |||
123 | @Override | ||
124 | public IQueryMetaContext getMetaContext() { | ||
125 | return metaContext; | ||
126 | } | ||
127 | |||
128 | @Override | ||
129 | public void ensureIndexed(IInputKey key, IndexingService service) { | ||
130 | ensureEnumerableKey(key); | ||
131 | if (key instanceof EClassTransitiveInstancesKey) { | ||
132 | EClass eClass = ((EClassTransitiveInstancesKey) key).getEmfKey(); | ||
133 | ensureIndexed(eClass, service); | ||
134 | } else if (key instanceof EDataTypeInSlotsKey) { | ||
135 | EDataType dataType = ((EDataTypeInSlotsKey) key).getEmfKey(); | ||
136 | ensureIndexed(dataType, service); | ||
137 | } else if (key instanceof EStructuralFeatureInstancesKey) { | ||
138 | EStructuralFeature feature = ((EStructuralFeatureInstancesKey) key).getEmfKey(); | ||
139 | ensureIndexed(feature, service); | ||
140 | } else { | ||
141 | illegalInputKey(key); | ||
142 | } | ||
143 | } | ||
144 | |||
145 | /** | ||
146 | * Retrieve the current registered indexing services for the given key. May not return null, | ||
147 | * returns an empty set if no indexing is registered. | ||
148 | * | ||
149 | * @since 1.4 | ||
150 | */ | ||
151 | protected EnumSet<IndexingService> getCurrentIndexingServiceFor(IInputKey key){ | ||
152 | ensureEnumerableKey(key); | ||
153 | if (key instanceof EClassTransitiveInstancesKey) { | ||
154 | EClass eClass = ((EClassTransitiveInstancesKey) key).getEmfKey(); | ||
155 | EnumSet<IndexingService> is = indexedClasses.get(eClass); | ||
156 | return is == null ? EnumSet.noneOf(IndexingService.class) : is; | ||
157 | } else if (key instanceof EDataTypeInSlotsKey) { | ||
158 | EDataType dataType = ((EDataTypeInSlotsKey) key).getEmfKey(); | ||
159 | EnumSet<IndexingService> is = indexedDataTypes.get(dataType); | ||
160 | return is == null ? EnumSet.noneOf(IndexingService.class) : is; | ||
161 | } else if (key instanceof EStructuralFeatureInstancesKey) { | ||
162 | EStructuralFeature feature = ((EStructuralFeatureInstancesKey) key).getEmfKey(); | ||
163 | EnumSet<IndexingService> is = indexedFeatures.get(feature); | ||
164 | return is == null ? EnumSet.noneOf(IndexingService.class) : is; | ||
165 | } else { | ||
166 | illegalInputKey(key); | ||
167 | return EnumSet.noneOf(IndexingService.class); | ||
168 | } | ||
169 | } | ||
170 | |||
171 | @Override | ||
172 | public boolean isIndexed(IInputKey key, IndexingService service) { | ||
173 | return getCurrentIndexingServiceFor(key).contains(service); | ||
174 | } | ||
175 | |||
176 | @Override | ||
177 | public boolean containsTuple(IInputKey key, ITuple seed) { | ||
178 | ensureValidKey(key); | ||
179 | if (key instanceof JavaTransitiveInstancesKey) { | ||
180 | Class<?> instanceClass = forceGetWrapperInstanceClass((JavaTransitiveInstancesKey) key); | ||
181 | return instanceClass != null && instanceClass.isInstance(seed.get(0)); | ||
182 | } else if (key instanceof EClassUnscopedTransitiveInstancesKey) { | ||
183 | EClass emfKey = ((EClassUnscopedTransitiveInstancesKey) key).getEmfKey(); | ||
184 | Object candidateInstance = seed.get(0); | ||
185 | return candidateInstance instanceof EObject | ||
186 | && baseIndex.isInstanceOfUnscoped((EObject) candidateInstance, emfKey); | ||
187 | } else { | ||
188 | ensureIndexed(key, IndexingService.INSTANCES); | ||
189 | if (key instanceof EClassTransitiveInstancesKey) { | ||
190 | EClass eClass = ((EClassTransitiveInstancesKey) key).getEmfKey(); | ||
191 | // instance check not enough to satisfy scoping, must lookup from index | ||
192 | Object candidateInstance = seed.get(0); | ||
193 | return candidateInstance instanceof EObject | ||
194 | && baseIndex.isInstanceOfScoped((EObject) candidateInstance, eClass); | ||
195 | } else if (key instanceof EDataTypeInSlotsKey) { | ||
196 | EDataType dataType = ((EDataTypeInSlotsKey) key).getEmfKey(); | ||
197 | return baseIndex.isInstanceOfDatatype(seed.get(0), dataType); | ||
198 | } else if (key instanceof EStructuralFeatureInstancesKey) { | ||
199 | EStructuralFeature feature = ((EStructuralFeatureInstancesKey) key).getEmfKey(); | ||
200 | Object sourceCandidate = seed.get(0); | ||
201 | return sourceCandidate instanceof EObject | ||
202 | && baseIndex.isFeatureInstance((EObject) sourceCandidate, seed.get(1), feature); | ||
203 | } else { | ||
204 | illegalInputKey(key); | ||
205 | return false; | ||
206 | } | ||
207 | } | ||
208 | } | ||
209 | |||
210 | private Class<?> forceGetWrapperInstanceClass(JavaTransitiveInstancesKey key) { | ||
211 | Class<?> instanceClass; | ||
212 | try { | ||
213 | instanceClass = key.forceGetWrapperInstanceClass(); | ||
214 | } catch (ClassNotFoundException e) { | ||
215 | logger.error("Could not load instance class for type constraint " + key.getWrappedKey(), e); | ||
216 | instanceClass = null; | ||
217 | } | ||
218 | return instanceClass; | ||
219 | } | ||
220 | |||
221 | @Override | ||
222 | public Iterable<Tuple> enumerateTuples(IInputKey key, TupleMask seedMask, ITuple seed) { | ||
223 | ensureIndexed(key, IndexingService.INSTANCES); | ||
224 | final Collection<Tuple> result = new HashSet<Tuple>(); | ||
225 | |||
226 | if (key instanceof EClassTransitiveInstancesKey) { | ||
227 | EClass eClass = ((EClassTransitiveInstancesKey) key).getEmfKey(); | ||
228 | |||
229 | if (seedMask.indices.length == 0) { // unseeded | ||
230 | return baseIndex.getAllInstances(eClass).stream().map(wrapUnary).collect(Collectors.toSet()); | ||
231 | } else { // fully seeded | ||
232 | Object seedInstance = seedMask.getValue(seed, 0); | ||
233 | if (containsTuple(key, seed)) | ||
234 | result.add(Tuples.staticArityFlatTupleOf(seedInstance)); | ||
235 | } | ||
236 | } else if (key instanceof EDataTypeInSlotsKey) { | ||
237 | EDataType dataType = ((EDataTypeInSlotsKey) key).getEmfKey(); | ||
238 | |||
239 | if (seedMask.indices.length == 0) { // unseeded | ||
240 | return baseIndex.getDataTypeInstances(dataType).stream().map(wrapUnary).collect(Collectors.toSet()); | ||
241 | } else { // fully seeded | ||
242 | Object seedInstance = seedMask.getValue(seed, 0); | ||
243 | if (containsTuple(key, seed)) | ||
244 | result.add(Tuples.staticArityFlatTupleOf(seedInstance)); | ||
245 | } | ||
246 | } else if (key instanceof EStructuralFeatureInstancesKey) { | ||
247 | EStructuralFeature feature = ((EStructuralFeatureInstancesKey) key).getEmfKey(); | ||
248 | |||
249 | boolean isSourceBound = false; | ||
250 | int sourceIndex = -1; | ||
251 | boolean isTargetBound = false; | ||
252 | int targetIndex = -1; | ||
253 | for (int i = 0; i < seedMask.getSize(); i++) { | ||
254 | int index = seedMask.indices[i]; | ||
255 | if (index == 0) { | ||
256 | isSourceBound = true; | ||
257 | sourceIndex = i; | ||
258 | } else if (index == 1) { | ||
259 | isTargetBound = true; | ||
260 | targetIndex = i; | ||
261 | } | ||
262 | } | ||
263 | |||
264 | if (!isSourceBound && isTargetBound) { | ||
265 | final Object seedTarget = seed.get(targetIndex); | ||
266 | final Set<EObject> results = baseIndex.findByFeatureValue(seedTarget, feature); | ||
267 | return results.stream().map(obj -> Tuples.staticArityFlatTupleOf(obj, seedTarget)).collect(Collectors.toSet()); | ||
268 | } else if (isSourceBound && isTargetBound) { // fully seeded | ||
269 | final Object seedSource = seed.get(sourceIndex); | ||
270 | final Object seedTarget = seed.get(targetIndex); | ||
271 | if (containsTuple(key, seed)) | ||
272 | result.add(Tuples.staticArityFlatTupleOf(seedSource, seedTarget)); | ||
273 | } else if (!isSourceBound && !isTargetBound) { // fully unseeded | ||
274 | baseIndex.processAllFeatureInstances(feature, (source, target) -> result.add(Tuples.staticArityFlatTupleOf(source, target))); | ||
275 | } else if (isSourceBound && !isTargetBound) { | ||
276 | final Object seedSource = seed.get(sourceIndex); | ||
277 | final Set<Object> results = baseIndex.getFeatureTargets((EObject) seedSource, feature); | ||
278 | return results.stream().map(obj -> Tuples.staticArityFlatTupleOf(seedSource, obj)).collect(Collectors.toSet()); | ||
279 | } | ||
280 | } else { | ||
281 | illegalInputKey(key); | ||
282 | } | ||
283 | |||
284 | |||
285 | return result; | ||
286 | } | ||
287 | |||
288 | private static Function<Object, Tuple> wrapUnary = Tuples::staticArityFlatTupleOf; | ||
289 | |||
290 | @Override | ||
291 | public Iterable<? extends Object> enumerateValues(IInputKey key, TupleMask seedMask, ITuple seed) { | ||
292 | ensureIndexed(key, IndexingService.INSTANCES); | ||
293 | |||
294 | if (key instanceof EClassTransitiveInstancesKey) { | ||
295 | EClass eClass = ((EClassTransitiveInstancesKey) key).getEmfKey(); | ||
296 | |||
297 | if (seedMask.indices.length == 0) { // unseeded | ||
298 | return baseIndex.getAllInstances(eClass); | ||
299 | } else { | ||
300 | // must be unseeded, this is enumerateValues after all! | ||
301 | illegalEnumerateValues(seed.toImmutable()); | ||
302 | } | ||
303 | } else if (key instanceof EDataTypeInSlotsKey) { | ||
304 | EDataType dataType = ((EDataTypeInSlotsKey) key).getEmfKey(); | ||
305 | |||
306 | if (seedMask.indices.length == 0) { // unseeded | ||
307 | return baseIndex.getDataTypeInstances(dataType); | ||
308 | } else { | ||
309 | // must be unseeded, this is enumerateValues after all! | ||
310 | illegalEnumerateValues(seed.toImmutable()); | ||
311 | } | ||
312 | } else if (key instanceof EStructuralFeatureInstancesKey) { | ||
313 | EStructuralFeature feature = ((EStructuralFeatureInstancesKey) key).getEmfKey(); | ||
314 | |||
315 | boolean isSourceBound = false; | ||
316 | int sourceIndex = -1; | ||
317 | boolean isTargetBound = false; | ||
318 | int targetIndex = -1; | ||
319 | for (int i = 0; i < seedMask.getSize(); i++) { | ||
320 | int index = seedMask.indices[i]; | ||
321 | if (index == 0) { | ||
322 | isSourceBound = true; | ||
323 | sourceIndex = i; | ||
324 | } else if (index == 1) { | ||
325 | isTargetBound = true; | ||
326 | targetIndex = i; | ||
327 | } | ||
328 | } | ||
329 | |||
330 | if (!isSourceBound && isTargetBound) { | ||
331 | Object seedTarget = seed.get(targetIndex); | ||
332 | return baseIndex.findByFeatureValue(seedTarget, feature); | ||
333 | } else if (isSourceBound && !isTargetBound) { | ||
334 | Object seedSource = seed.get(sourceIndex); | ||
335 | return baseIndex.getFeatureTargets((EObject) seedSource, feature); | ||
336 | } else { | ||
337 | // must be singly unseeded, this is enumerateValues after all! | ||
338 | illegalEnumerateValues(seed.toImmutable()); | ||
339 | } | ||
340 | } else { | ||
341 | illegalInputKey(key); | ||
342 | } | ||
343 | return null; | ||
344 | } | ||
345 | |||
346 | @Override | ||
347 | public int countTuples(IInputKey key, TupleMask seedMask, ITuple seed) { | ||
348 | ensureIndexed(key, IndexingService.STATISTICS); | ||
349 | |||
350 | if (key instanceof EClassTransitiveInstancesKey) { | ||
351 | EClass eClass = ((EClassTransitiveInstancesKey) key).getEmfKey(); | ||
352 | |||
353 | if (seedMask.indices.length == 0) { // unseeded | ||
354 | return baseIndex.countAllInstances(eClass); | ||
355 | } else { // fully seeded | ||
356 | return (containsTuple(key, seed)) ? 1 : 0; | ||
357 | } | ||
358 | } else if (key instanceof EDataTypeInSlotsKey) { | ||
359 | EDataType dataType = ((EDataTypeInSlotsKey) key).getEmfKey(); | ||
360 | |||
361 | if (seedMask.indices.length == 0) { // unseeded | ||
362 | return baseIndex.countDataTypeInstances(dataType); | ||
363 | } else { // fully seeded | ||
364 | return (containsTuple(key, seed)) ? 1 : 0; | ||
365 | } | ||
366 | } else if (key instanceof EStructuralFeatureInstancesKey) { | ||
367 | EStructuralFeature feature = ((EStructuralFeatureInstancesKey) key).getEmfKey(); | ||
368 | |||
369 | boolean isSourceBound = false; | ||
370 | int sourceIndex = -1; | ||
371 | boolean isTargetBound = false; | ||
372 | int targetIndex = -1; | ||
373 | for (int i = 0; i < seedMask.getSize(); i++) { | ||
374 | int index = seedMask.indices[i]; | ||
375 | if (index == 0) { | ||
376 | isSourceBound = true; | ||
377 | sourceIndex = i; | ||
378 | } else if (index == 1) { | ||
379 | isTargetBound = true; | ||
380 | targetIndex = i; | ||
381 | } | ||
382 | } | ||
383 | |||
384 | if (!isSourceBound && isTargetBound) { | ||
385 | final Object seedTarget = seed.get(targetIndex); | ||
386 | return baseIndex.findByFeatureValue(seedTarget, feature).size(); | ||
387 | } else if (isSourceBound && isTargetBound) { // fully seeded | ||
388 | return (containsTuple(key, seed)) ? 1 : 0; | ||
389 | } else if (!isSourceBound && !isTargetBound) { // fully unseeded | ||
390 | return baseIndex.countFeatures(feature); | ||
391 | } else if (isSourceBound && !isTargetBound) { | ||
392 | final Object seedSource = seed.get(sourceIndex); | ||
393 | return baseIndex.countFeatureTargets((EObject) seedSource, feature); | ||
394 | } | ||
395 | } else { | ||
396 | illegalInputKey(key); | ||
397 | } | ||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | |||
402 | /** | ||
403 | * @since 2.1 | ||
404 | */ | ||
405 | @Override | ||
406 | public Optional<Long> estimateCardinality(IInputKey key, TupleMask groupMask, Accuracy requiredAccuracy) { | ||
407 | |||
408 | if (key instanceof EClassTransitiveInstancesKey) { | ||
409 | EClass eClass = ((EClassTransitiveInstancesKey) key).getEmfKey(); | ||
410 | |||
411 | if (isIndexed(key, IndexingService.STATISTICS)) { // exact answer known | ||
412 | if (groupMask.indices.length == 0) { // empty projection | ||
413 | return (0 != baseIndex.countAllInstances(eClass)) ? Optional.of(1L) : Optional.of(0L); | ||
414 | } else { // unprojected | ||
415 | return Optional.of((long)baseIndex.countAllInstances(eClass)); | ||
416 | } | ||
417 | } else return Optional.empty(); // TODO use known supertype counts as upper, subtypes as lower bounds | ||
418 | |||
419 | } else if (key instanceof EClassUnscopedTransitiveInstancesKey) { | ||
420 | EClass eClass = ((EClassUnscopedTransitiveInstancesKey) key).getEmfKey(); | ||
421 | |||
422 | // can give only lower bound based on the scoped key | ||
423 | if (Accuracy.BEST_LOWER_BOUND.atLeastAsPreciseAs(requiredAccuracy)) { | ||
424 | return estimateCardinality(new EClassTransitiveInstancesKey(eClass), groupMask, requiredAccuracy); | ||
425 | } else return Optional.empty(); | ||
426 | |||
427 | } else if (key instanceof EDataTypeInSlotsKey) { | ||
428 | EDataType dataType = ((EDataTypeInSlotsKey) key).getEmfKey(); | ||
429 | |||
430 | if (isIndexed(key, IndexingService.STATISTICS)) { | ||
431 | if (groupMask.indices.length == 0) { // empty projection | ||
432 | return (0 != baseIndex.countDataTypeInstances(dataType)) ? Optional.of(1L) : Optional.of(0L); | ||
433 | } else { // unprojected | ||
434 | return Optional.of((long)baseIndex.countDataTypeInstances(dataType)); | ||
435 | } | ||
436 | } else return Optional.empty(); | ||
437 | |||
438 | } else if (key instanceof EStructuralFeatureInstancesKey) { | ||
439 | EStructuralFeatureInstancesKey featureKey = (EStructuralFeatureInstancesKey) key; | ||
440 | EStructuralFeature feature = featureKey.getEmfKey(); | ||
441 | |||
442 | |||
443 | boolean isSourceSelected = false; | ||
444 | boolean isTargetSelected = false; | ||
445 | for (int i = 0; i < groupMask.getSize(); i++) { | ||
446 | int index = groupMask.indices[i]; | ||
447 | if (index == 0) { | ||
448 | isSourceSelected = true; | ||
449 | } else if (index == 1) { | ||
450 | isTargetSelected = true; | ||
451 | } | ||
452 | } | ||
453 | |||
454 | Optional<Long> sourceTypeUpperEstimate = | ||
455 | estimateCardinality(metaContext.getSourceTypeKey(featureKey), | ||
456 | TupleMask.identity(1), Accuracy.BEST_UPPER_BOUND); | ||
457 | Optional<Long> targetTypeUpperEstimate = | ||
458 | estimateCardinality(metaContext.getTargetTypeKey(featureKey), | ||
459 | TupleMask.identity(1), Accuracy.BEST_UPPER_BOUND); | ||
460 | |||
461 | if (!isSourceSelected && !isTargetSelected) { // empty projection | ||
462 | if (isIndexed(key, IndexingService.STATISTICS)) { // we have exact node counts | ||
463 | return (0 == baseIndex.countFeatures(feature)) ? Optional.of(0L) : Optional.of(1L); | ||
464 | } else { // we can still say 0 in a few cases | ||
465 | if (0 == sourceTypeUpperEstimate.orElse(-1L)) | ||
466 | return Optional.of(0L); | ||
467 | |||
468 | if (0 == targetTypeUpperEstimate.orElse(-1L)) | ||
469 | return Optional.of(0L); | ||
470 | |||
471 | return Optional.empty(); | ||
472 | } | ||
473 | |||
474 | } else if (isSourceSelected && !isTargetSelected) { // count sources | ||
475 | if (isIndexed(key, IndexingService.INSTANCES)) { // we have instances, therefore feature end counts | ||
476 | return Optional.of((long)(baseIndex.getHoldersOfFeature(feature).size())); | ||
477 | } else if (metaContext.isFeatureMultiplicityToOne(feature) && | ||
478 | isIndexed(key, IndexingService.STATISTICS)) { // count of edges = count of sources due to func. dep. | ||
479 | return Optional.of((long)(baseIndex.countFeatures(feature))); | ||
480 | } else if (Accuracy.BEST_UPPER_BOUND.atLeastAsPreciseAs(requiredAccuracy)) { | ||
481 | // upper bound by source type | ||
482 | Optional<Long> estimate = sourceTypeUpperEstimate; | ||
483 | // total edge counts are another upper bound (even if instances are unindexed) | ||
484 | if (isIndexed(key, IndexingService.STATISTICS)) { | ||
485 | estimate = Optional.of(Math.min( | ||
486 | baseIndex.countFeatures(feature), | ||
487 | estimate.orElse(Long.MAX_VALUE))); | ||
488 | } | ||
489 | return estimate; | ||
490 | } else return Optional.empty(); | ||
491 | |||
492 | } else if (!isSourceSelected /*&& isTargetSelected*/) { // count targets | ||
493 | if (isIndexed(key, IndexingService.INSTANCES)) { // we have instances, therefore feature end counts | ||
494 | return Optional.of((long)(baseIndex.getValuesOfFeature(feature).size())); | ||
495 | } else if (metaContext.isFeatureMultiplicityOneTo(feature) && | ||
496 | isIndexed(key, IndexingService.STATISTICS)) { // count of edges = count of targets due to func. dep. | ||
497 | return Optional.of((long)(baseIndex.countFeatures(feature))); | ||
498 | } else if (Accuracy.BEST_UPPER_BOUND.atLeastAsPreciseAs(requiredAccuracy)) { // upper bound by target type | ||
499 | // upper bound by target type | ||
500 | Optional<Long> estimate = targetTypeUpperEstimate; | ||
501 | // total edge counts are another upper bound (even if instances are unindexed) | ||
502 | if (isIndexed(key, IndexingService.STATISTICS)) { | ||
503 | estimate = Optional.of(Math.min( | ||
504 | baseIndex.countFeatures(feature), | ||
505 | estimate.orElse(Long.MAX_VALUE))); | ||
506 | } | ||
507 | return estimate; | ||
508 | } else return Optional.empty(); | ||
509 | |||
510 | } else { // (isSourceSelected && isTargetSelected) // count edges | ||
511 | if (isIndexed(key, IndexingService.STATISTICS)) { // we have exact edge counts | ||
512 | return Optional.of((long)baseIndex.countFeatures(feature)); | ||
513 | } else if (Accuracy.BEST_UPPER_BOUND.atLeastAsPreciseAs(requiredAccuracy)) { // overestimates may still be available | ||
514 | Optional<Long> estimate = // trivial upper bound: product of source & target type sizes (if available) | ||
515 | (sourceTypeUpperEstimate.isPresent() && targetTypeUpperEstimate.isPresent()) ? | ||
516 | Optional.of( | ||
517 | ((long)sourceTypeUpperEstimate.get()) * targetTypeUpperEstimate.get() | ||
518 | ) : Optional.empty(); | ||
519 | |||
520 | if (metaContext.isFeatureMultiplicityToOne(feature) && sourceTypeUpperEstimate.isPresent()) { | ||
521 | // upper bounded by source type due to func. dep. | ||
522 | estimate = Optional.of(Math.min( | ||
523 | sourceTypeUpperEstimate.get(), | ||
524 | estimate.orElse(Long.MAX_VALUE))); | ||
525 | } | ||
526 | if (metaContext.isFeatureMultiplicityOneTo(feature) && targetTypeUpperEstimate.isPresent()) { | ||
527 | // upper bounded by target type due to func. dep. | ||
528 | estimate = Optional.of(Math.min( | ||
529 | targetTypeUpperEstimate.get(), | ||
530 | estimate.orElse(Long.MAX_VALUE))); | ||
531 | } | ||
532 | |||
533 | return estimate; | ||
534 | } else return Optional.empty(); | ||
535 | } | ||
536 | |||
537 | } else { | ||
538 | return Optional.empty(); | ||
539 | } | ||
540 | } | ||
541 | |||
542 | /** | ||
543 | * @since 2.1 | ||
544 | */ | ||
545 | @Override | ||
546 | public Optional<Double> estimateAverageBucketSize(IInputKey key, TupleMask groupMask, Accuracy requiredAccuracy) { | ||
547 | // smart handling of special cases | ||
548 | if (key instanceof EStructuralFeatureInstancesKey) { | ||
549 | EStructuralFeatureInstancesKey featureKey = (EStructuralFeatureInstancesKey) key; | ||
550 | EStructuralFeature feature = featureKey.getEmfKey(); | ||
551 | |||
552 | // special treatment for edge navigation | ||
553 | if (1 == groupMask.getSize()) { | ||
554 | if (0 == groupMask.indices[0] && metaContext.isFeatureMultiplicityToOne(feature)) { // count targets per source | ||
555 | return Optional.of(1.0); | ||
556 | } else if (1 == groupMask.indices[0] && metaContext.isFeatureMultiplicityOneTo(feature)) { // count sources per target | ||
557 | return Optional.of(1.0); | ||
558 | } | ||
559 | } | ||
560 | } | ||
561 | |||
562 | // keep the default behaviour | ||
563 | return super.estimateAverageBucketSize(key, groupMask, requiredAccuracy); | ||
564 | } | ||
565 | |||
566 | |||
567 | public void ensureEnumerableKey(IInputKey key) { | ||
568 | ensureValidKey(key); | ||
569 | if (! metaContext.isEnumerable(key)) | ||
570 | throw new IllegalArgumentException("Key is not enumerable: " + key); | ||
571 | |||
572 | } | ||
573 | |||
574 | public void ensureValidKey(IInputKey key) { | ||
575 | metaContext.ensureValidKey(key); | ||
576 | } | ||
577 | public void illegalInputKey(IInputKey key) { | ||
578 | metaContext.illegalInputKey(key); | ||
579 | } | ||
580 | public void illegalEnumerateValues(Tuple seed) { | ||
581 | throw new IllegalArgumentException("Must have exactly one unseeded element in enumerateValues() invocation, received instead: " + seed); | ||
582 | } | ||
583 | |||
584 | /** | ||
585 | * @since 1.4 | ||
586 | */ | ||
587 | public void ensureIndexed(EClass eClass, IndexingService service) { | ||
588 | if (addIndexingService(indexedClasses, eClass, service)) { | ||
589 | final Set<EClass> newClasses = Collections.singleton(eClass); | ||
590 | IndexingLevel level = IndexingLevel.toLevel(service); | ||
591 | if (!baseIndex.getIndexingLevel(eClass).providesLevel(level)) { | ||
592 | baseIndex.registerEClasses(newClasses, level); | ||
593 | } | ||
594 | //baseIndex.addInstanceListener(newClasses, listener); | ||
595 | } | ||
596 | } | ||
597 | |||
598 | /** | ||
599 | * @since 1.4 | ||
600 | */ | ||
601 | public void ensureIndexed(EDataType eDataType, IndexingService service) { | ||
602 | if (addIndexingService(indexedDataTypes, eDataType, service)) { | ||
603 | final Set<EDataType> newDataTypes = Collections.singleton(eDataType); | ||
604 | IndexingLevel level = IndexingLevel.toLevel(service); | ||
605 | if (!baseIndex.getIndexingLevel(eDataType).providesLevel(level)) { | ||
606 | baseIndex.registerEDataTypes(newDataTypes, level); | ||
607 | } | ||
608 | //baseIndex.addDataTypeListener(newDataTypes, listener); | ||
609 | } | ||
610 | } | ||
611 | |||
612 | /** | ||
613 | * @since 1.4 | ||
614 | */ | ||
615 | public void ensureIndexed(EStructuralFeature feature, IndexingService service) { | ||
616 | if (addIndexingService(indexedFeatures, feature, service)) { | ||
617 | final Set<EStructuralFeature> newFeatures = Collections.singleton(feature); | ||
618 | IndexingLevel level = IndexingLevel.toLevel(service); | ||
619 | if (!baseIndex.getIndexingLevel(feature).providesLevel(level)) { | ||
620 | baseIndex.registerEStructuralFeatures(newFeatures, level); | ||
621 | } | ||
622 | //baseIndex.addFeatureListener(newFeatures, listener); | ||
623 | } | ||
624 | } | ||
625 | |||
626 | |||
627 | |||
628 | // UPDATE HANDLING SECTION | ||
629 | |||
630 | /** | ||
631 | * Abstract internal listener wrapper for a {@link IQueryRuntimeContextListener}. | ||
632 | * Due to the overridden equals/hashCode(), it is safe to create a new instance for the same listener. | ||
633 | * | ||
634 | * @author Bergmann Gabor | ||
635 | */ | ||
636 | private abstract static class ListenerAdapter { | ||
637 | IQueryRuntimeContextListener listener; | ||
638 | Tuple seed; | ||
639 | /** | ||
640 | * @param listener | ||
641 | * @param seed must be non-null | ||
642 | */ | ||
643 | public ListenerAdapter(IQueryRuntimeContextListener listener, Object... seed) { | ||
644 | this.listener = listener; | ||
645 | this.seed = Tuples.flatTupleOf(seed); | ||
646 | } | ||
647 | |||
648 | @Override | ||
649 | public int hashCode() { | ||
650 | final int prime = 31; | ||
651 | int result = 1; | ||
652 | result = prime * result | ||
653 | + ((listener == null) ? 0 : listener.hashCode()); | ||
654 | result = prime * result + ((seed == null) ? 0 : seed.hashCode()); | ||
655 | return result; | ||
656 | } | ||
657 | |||
658 | @Override | ||
659 | public boolean equals(Object obj) { | ||
660 | if (this == obj) | ||
661 | return true; | ||
662 | if (obj == null) | ||
663 | return false; | ||
664 | if (!(obj.getClass().equals(this.getClass()))) | ||
665 | return false; | ||
666 | ListenerAdapter other = (ListenerAdapter) obj; | ||
667 | if (listener == null) { | ||
668 | if (other.listener != null) | ||
669 | return false; | ||
670 | } else if (!listener.equals(other.listener)) | ||
671 | return false; | ||
672 | if (seed == null) { | ||
673 | if (other.seed != null) | ||
674 | return false; | ||
675 | } else if (!seed.equals(other.seed)) | ||
676 | return false; | ||
677 | return true; | ||
678 | } | ||
679 | |||
680 | |||
681 | @Override | ||
682 | public String toString() { | ||
683 | return "Wrapped<Seed:" + seed + ">#" + listener; | ||
684 | } | ||
685 | |||
686 | |||
687 | } | ||
688 | private static class EClassTransitiveInstancesAdapter extends ListenerAdapter implements InstanceListener { | ||
689 | private Object seedInstance; | ||
690 | public EClassTransitiveInstancesAdapter(IQueryRuntimeContextListener listener, Object seedInstance) { | ||
691 | super(listener, seedInstance); | ||
692 | this.seedInstance = seedInstance; | ||
693 | } | ||
694 | @Override | ||
695 | public void instanceInserted(EClass clazz, EObject instance) { | ||
696 | if (seedInstance != null && !seedInstance.equals(instance)) return; | ||
697 | listener.update(new EClassTransitiveInstancesKey(clazz), | ||
698 | Tuples.staticArityFlatTupleOf(instance), true); | ||
699 | } | ||
700 | @Override | ||
701 | public void instanceDeleted(EClass clazz, EObject instance) { | ||
702 | if (seedInstance != null && !seedInstance.equals(instance)) return; | ||
703 | listener.update(new EClassTransitiveInstancesKey(clazz), | ||
704 | Tuples.staticArityFlatTupleOf(instance), false); | ||
705 | } | ||
706 | } | ||
707 | private static class EDataTypeInSlotsAdapter extends ListenerAdapter implements DataTypeListener { | ||
708 | private Object seedValue; | ||
709 | public EDataTypeInSlotsAdapter(IQueryRuntimeContextListener listener, Object seedValue) { | ||
710 | super(listener, seedValue); | ||
711 | this.seedValue = seedValue; | ||
712 | } | ||
713 | @Override | ||
714 | public void dataTypeInstanceInserted(EDataType type, Object instance, | ||
715 | boolean firstOccurrence) { | ||
716 | if (firstOccurrence) { | ||
717 | if (seedValue != null && !seedValue.equals(instance)) return; | ||
718 | listener.update(new EDataTypeInSlotsKey(type), | ||
719 | Tuples.staticArityFlatTupleOf(instance), true); | ||
720 | } | ||
721 | } | ||
722 | @Override | ||
723 | public void dataTypeInstanceDeleted(EDataType type, Object instance, | ||
724 | boolean lastOccurrence) { | ||
725 | if (lastOccurrence) { | ||
726 | if (seedValue != null && !seedValue.equals(instance)) return; | ||
727 | listener.update(new EDataTypeInSlotsKey(type), | ||
728 | Tuples.staticArityFlatTupleOf(instance), false); | ||
729 | } | ||
730 | } | ||
731 | } | ||
732 | private static class EStructuralFeatureInstancesKeyAdapter extends ListenerAdapter implements FeatureListener { | ||
733 | private Object seedHost; | ||
734 | private Object seedValue; | ||
735 | public EStructuralFeatureInstancesKeyAdapter(IQueryRuntimeContextListener listener, Object seedHost, Object seedValue) { | ||
736 | super(listener, seedHost, seedValue); | ||
737 | this.seedHost = seedHost; | ||
738 | this.seedValue = seedValue; | ||
739 | } | ||
740 | @Override | ||
741 | public void featureInserted(EObject host, EStructuralFeature feature, | ||
742 | Object value) { | ||
743 | if (seedHost != null && !seedHost.equals(host)) return; | ||
744 | if (seedValue != null && !seedValue.equals(value)) return; | ||
745 | listener.update(new EStructuralFeatureInstancesKey(feature), | ||
746 | Tuples.staticArityFlatTupleOf(host, value), true); | ||
747 | } | ||
748 | @Override | ||
749 | public void featureDeleted(EObject host, EStructuralFeature feature, | ||
750 | Object value) { | ||
751 | if (seedHost != null && !seedHost.equals(host)) return; | ||
752 | if (seedValue != null && !seedValue.equals(value)) return; | ||
753 | listener.update(new EStructuralFeatureInstancesKey(feature), | ||
754 | Tuples.staticArityFlatTupleOf(host, value), false); | ||
755 | } | ||
756 | } | ||
757 | |||
758 | @Override | ||
759 | public void addUpdateListener(IInputKey key, Tuple seed /* TODO ignored */, IQueryRuntimeContextListener listener) { | ||
760 | // stateless, so NOP | ||
761 | if (key instanceof JavaTransitiveInstancesKey) return; | ||
762 | |||
763 | ensureIndexed(key, IndexingService.INSTANCES); | ||
764 | if (key instanceof EClassTransitiveInstancesKey) { | ||
765 | EClass eClass = ((EClassTransitiveInstancesKey) key).getEmfKey(); | ||
766 | baseIndex.addInstanceListener(Collections.singleton(eClass), | ||
767 | new EClassTransitiveInstancesAdapter(listener, seed.get(0))); | ||
768 | } else if (key instanceof EDataTypeInSlotsKey) { | ||
769 | EDataType dataType = ((EDataTypeInSlotsKey) key).getEmfKey(); | ||
770 | baseIndex.addDataTypeListener(Collections.singleton(dataType), | ||
771 | new EDataTypeInSlotsAdapter(listener, seed.get(0))); | ||
772 | } else if (key instanceof EStructuralFeatureInstancesKey) { | ||
773 | EStructuralFeature feature = ((EStructuralFeatureInstancesKey) key).getEmfKey(); | ||
774 | baseIndex.addFeatureListener(Collections.singleton(feature), | ||
775 | new EStructuralFeatureInstancesKeyAdapter(listener, seed.get(0), seed.get(1))); | ||
776 | } else { | ||
777 | illegalInputKey(key); | ||
778 | } | ||
779 | } | ||
780 | @Override | ||
781 | public void removeUpdateListener(IInputKey key, Tuple seed, IQueryRuntimeContextListener listener) { | ||
782 | // stateless, so NOP | ||
783 | if (key instanceof JavaTransitiveInstancesKey) return; | ||
784 | |||
785 | ensureIndexed(key, IndexingService.INSTANCES); | ||
786 | if (key instanceof EClassTransitiveInstancesKey) { | ||
787 | EClass eClass = ((EClassTransitiveInstancesKey) key).getEmfKey(); | ||
788 | baseIndex.removeInstanceListener(Collections.singleton(eClass), | ||
789 | new EClassTransitiveInstancesAdapter(listener, seed.get(0))); | ||
790 | } else if (key instanceof EDataTypeInSlotsKey) { | ||
791 | EDataType dataType = ((EDataTypeInSlotsKey) key).getEmfKey(); | ||
792 | baseIndex.removeDataTypeListener(Collections.singleton(dataType), | ||
793 | new EDataTypeInSlotsAdapter(listener, seed.get(0))); | ||
794 | } else if (key instanceof EStructuralFeatureInstancesKey) { | ||
795 | EStructuralFeature feature = ((EStructuralFeatureInstancesKey) key).getEmfKey(); | ||
796 | baseIndex.removeFeatureListener(Collections.singleton(feature), | ||
797 | new EStructuralFeatureInstancesKeyAdapter(listener, seed.get(0), seed.get(1))); | ||
798 | } else { | ||
799 | illegalInputKey(key); | ||
800 | } | ||
801 | } | ||
802 | |||
803 | // TODO wrap / unwrap enum literals | ||
804 | // TODO use this in all other public methods (maybe wrap & delegate?) | ||
805 | |||
806 | @Override | ||
807 | public Object unwrapElement(Object internalElement) { | ||
808 | return internalElement; | ||
809 | } | ||
810 | @Override | ||
811 | public Tuple unwrapTuple(Tuple internalElements) { | ||
812 | return internalElements; | ||
813 | } | ||
814 | @Override | ||
815 | public Object wrapElement(Object externalElement) { | ||
816 | return externalElement; | ||
817 | } | ||
818 | @Override | ||
819 | public Tuple wrapTuple(Tuple externalElements) { | ||
820 | return externalElements; | ||
821 | } | ||
822 | |||
823 | /** | ||
824 | * @since 1.4 | ||
825 | */ | ||
826 | @Override | ||
827 | public void ensureWildcardIndexing(IndexingService service) { | ||
828 | baseIndex.setWildcardLevel(IndexingLevel.toLevel(service)); | ||
829 | } | ||
830 | |||
831 | /** | ||
832 | * @since 1.4 | ||
833 | */ | ||
834 | @Override | ||
835 | public void executeAfterTraversal(Runnable runnable) throws InvocationTargetException { | ||
836 | baseIndex.executeAfterTraversal(runnable); | ||
837 | } | ||
838 | } | ||
839 | |||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/EMFScope.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/EMFScope.java deleted file mode 100644 index dead9716..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/EMFScope.java +++ /dev/null | |||
@@ -1,199 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Bergmann Gabor, Denes Harmath, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.emf; | ||
10 | |||
11 | import java.util.Arrays; | ||
12 | import java.util.Collections; | ||
13 | import java.util.HashSet; | ||
14 | import java.util.Set; | ||
15 | import java.util.function.Predicate; | ||
16 | import java.util.stream.Collectors; | ||
17 | |||
18 | import org.apache.log4j.Logger; | ||
19 | import org.eclipse.emf.common.notify.Notifier; | ||
20 | import org.eclipse.emf.common.util.URI; | ||
21 | import org.eclipse.emf.ecore.EObject; | ||
22 | import org.eclipse.emf.ecore.resource.Resource; | ||
23 | import org.eclipse.emf.ecore.resource.ResourceSet; | ||
24 | import tools.refinery.viatra.runtime.api.AdvancedViatraQueryEngine; | ||
25 | import tools.refinery.viatra.runtime.api.ViatraQueryEngine; | ||
26 | import tools.refinery.viatra.runtime.api.scope.IEngineContext; | ||
27 | import tools.refinery.viatra.runtime.api.scope.IIndexingErrorListener; | ||
28 | import tools.refinery.viatra.runtime.api.scope.QueryScope; | ||
29 | import tools.refinery.viatra.runtime.base.api.BaseIndexOptions; | ||
30 | import tools.refinery.viatra.runtime.base.api.NavigationHelper; | ||
31 | import tools.refinery.viatra.runtime.exception.ViatraQueryException; | ||
32 | |||
33 | /** | ||
34 | * An {@link QueryScope} consisting of EMF objects contained in multiple {@link ResourceSet}s, a single {@link ResourceSet}, {@link Resource} or a containment subtree below a given {@link EObject}. | ||
35 | * | ||
36 | * <p> The scope is characterized by a root and some options (see {@link BaseIndexOptions}) such as dynamic EMF mode, subtree filtering etc. | ||
37 | * <p> | ||
38 | * The scope of pattern matching will be the given EMF model root(s) and below (see FAQ for more precise definition). | ||
39 | * | ||
40 | * <p> Note on <i>cross-resource containment</i>: in case of {@link EObject} scopes, cross-resource containments will be considered part of the scope. | ||
41 | * The same goes for {@link ResourceSet} scopes, provided that the resource of the contained element is successfully loaded into the resource set. | ||
42 | * In case of a {@link Resource} scope, containments pointing out from the resource will be excluded from the scope. | ||
43 | * Thus the boundaries of {@link EObject} scopes conform to the notion of EMF logical containment, while {@link Resource} and {@link ResourceSet} scopes adhere to persistence boundaries. | ||
44 | * | ||
45 | * @author Bergmann Gabor | ||
46 | * | ||
47 | */ | ||
48 | public class EMFScope extends QueryScope { | ||
49 | |||
50 | private Set<? extends Notifier> scopeRoots; | ||
51 | private BaseIndexOptions options; | ||
52 | |||
53 | /** | ||
54 | * Creates an EMF scope at the given root, with default options (recommended for most users). | ||
55 | * @param scopeRoot the root of the EMF scope | ||
56 | * @throws ViatraQueryRuntimeException- if scopeRoot is not an EMF ResourceSet, Resource or EObject | ||
57 | */ | ||
58 | public EMFScope(Notifier scopeRoot) { | ||
59 | this(Collections.singleton(scopeRoot), new BaseIndexOptions()); | ||
60 | } | ||
61 | |||
62 | /** | ||
63 | * Creates an EMF scope at the given root, with customizable options. | ||
64 | * <p> Most users should consider {@link #EMFScope(Notifier)} instead. | ||
65 | * @param scopeRoot the root of the EMF scope | ||
66 | * @param options the base index building settings | ||
67 | * @throws ViatraQueryRuntimeException if scopeRoot is not an EMF ResourceSet, Resource or EObject | ||
68 | */ | ||
69 | public EMFScope(Notifier scopeRoot, BaseIndexOptions options) { | ||
70 | this(Collections.singleton(scopeRoot), options); | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * Creates an EMF scope at the given roots, with default options (recommended for most users). | ||
75 | * @param scopeRoots the roots of the EMF scope, must be {@link ResourceSet}s | ||
76 | * @throws ViatraQueryRuntimeException if not all scopeRoots are {@link ResourceSet}s | ||
77 | */ | ||
78 | public EMFScope(Set<? extends ResourceSet> scopeRoots) { | ||
79 | this(scopeRoots, new BaseIndexOptions()); | ||
80 | } | ||
81 | |||
82 | /** | ||
83 | * Creates an EMF scope at the given roots, with customizable options. | ||
84 | * <p> Most users should consider {@link #EMFScope(Set)} instead. | ||
85 | * @param scopeRoots the roots of the EMF scope, must be {@link ResourceSet}s | ||
86 | * @param options the base index building settings | ||
87 | * @throws ViatraQueryRuntimeException if not all scopeRoots are {@link ResourceSet}s | ||
88 | */ | ||
89 | public EMFScope(Set<? extends Notifier> scopeRoots, BaseIndexOptions options) { | ||
90 | super(); | ||
91 | if (scopeRoots.isEmpty()) { | ||
92 | throw new IllegalArgumentException("No scope roots given"); | ||
93 | } else if (scopeRoots.size() == 1) { | ||
94 | checkScopeRoots(scopeRoots, EObject.class::isInstance, Resource.class::isInstance, ResourceSet.class::isInstance); | ||
95 | } else { | ||
96 | checkScopeRoots(scopeRoots, ResourceSet.class::isInstance); | ||
97 | } | ||
98 | this.scopeRoots = new HashSet<>(scopeRoots); | ||
99 | this.options = options.copy(); | ||
100 | } | ||
101 | |||
102 | @SafeVarargs | ||
103 | private final void checkScopeRoots(Set<? extends Notifier> scopeRoots, Predicate<Notifier>... predicates) { | ||
104 | for (Notifier scopeRoot : scopeRoots) { | ||
105 | // Creating compound predicate that checks the various branches of disjunction together | ||
106 | Predicate<Notifier> compoundPredicate = Arrays.stream(predicates).collect(Collectors.reducing(a -> true, a -> a, (a, b) -> a.or(b))); | ||
107 | if (!compoundPredicate.test(scopeRoot)) | ||
108 | throw new ViatraQueryException(ViatraQueryException.INVALID_EMFROOT | ||
109 | + (scopeRoot == null ? "(null)" : scopeRoot.getClass().getName()), | ||
110 | ViatraQueryException.INVALID_EMFROOT_SHORT); | ||
111 | } | ||
112 | } | ||
113 | |||
114 | /** | ||
115 | * @return the scope roots ({@link ResourceSet}s) containing the model | ||
116 | */ | ||
117 | public Set<? extends Notifier> getScopeRoots() { | ||
118 | return scopeRoots; | ||
119 | } | ||
120 | |||
121 | /** | ||
122 | * @return the options | ||
123 | */ | ||
124 | public BaseIndexOptions getOptions() { | ||
125 | return options.copy(); | ||
126 | } | ||
127 | |||
128 | @Override | ||
129 | public int hashCode() { | ||
130 | final int prime = 31; | ||
131 | int result = 1; | ||
132 | result = prime * result + ((options == null) ? 0 : options.hashCode()); | ||
133 | result = prime * result | ||
134 | + ((scopeRoots == null) ? 0 : scopeRoots.hashCode()); | ||
135 | return result; | ||
136 | } | ||
137 | @Override | ||
138 | public boolean equals(Object obj) { | ||
139 | if (this == obj) | ||
140 | return true; | ||
141 | if (obj == null) | ||
142 | return false; | ||
143 | if (!(obj instanceof EMFScope)) | ||
144 | return false; | ||
145 | EMFScope other = (EMFScope) obj; | ||
146 | if (options == null) { | ||
147 | if (other.options != null) | ||
148 | return false; | ||
149 | } else if (!options.equals(other.options)) | ||
150 | return false; | ||
151 | if (scopeRoots == null) { | ||
152 | if (other.scopeRoots != null) | ||
153 | return false; | ||
154 | } else if (!scopeRoots.equals(other.scopeRoots)) | ||
155 | return false; | ||
156 | return true; | ||
157 | } | ||
158 | |||
159 | |||
160 | @Override | ||
161 | public String toString() { | ||
162 | return String.format("EMFScope(%s):%s", options, scopeRoots.stream().map(this::scopeRootString).collect(Collectors.joining(","))); | ||
163 | } | ||
164 | |||
165 | private String scopeRootString(Notifier notifier) { | ||
166 | if (notifier instanceof Resource) { | ||
167 | Resource resource = (Resource) notifier; | ||
168 | return String.format("%s(%s)", resource.getClass(), resource.getURI()); | ||
169 | } else if (notifier instanceof ResourceSet) { | ||
170 | ResourceSet resourceSet = (ResourceSet) notifier; | ||
171 | return resourceSet.getResources().stream() | ||
172 | .map(Resource::getURI) | ||
173 | .map(URI::toString) | ||
174 | .collect(Collectors.joining(", ", resourceSet.getClass() + "(", ")")); | ||
175 | } else { | ||
176 | return notifier.toString(); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | @Override | ||
181 | protected IEngineContext createEngineContext(ViatraQueryEngine engine, IIndexingErrorListener errorListener, Logger logger) { | ||
182 | return new EMFEngineContext(this, engine, errorListener, logger); | ||
183 | } | ||
184 | |||
185 | /** | ||
186 | * Provides access to the underlying EMF model index ({@link NavigationHelper}) from a VIATRA Query engine instantiated on an EMFScope | ||
187 | * | ||
188 | * @param engine an already existing VIATRA Query engine instantiated on an EMFScope | ||
189 | * @return the underlying EMF base index that indexes the contents of the EMF model | ||
190 | * @throws ViatraQueryRuntimeException if base index initialization fails | ||
191 | */ | ||
192 | public static NavigationHelper extractUnderlyingEMFIndex(ViatraQueryEngine engine) { | ||
193 | final QueryScope scope = engine.getScope(); | ||
194 | if (scope instanceof EMFScope) | ||
195 | return ((EMFBaseIndexWrapper)AdvancedViatraQueryEngine.from(engine).getBaseIndex()).getNavigationHelper(); | ||
196 | else throw new IllegalArgumentException("Cannot extract EMF base index from VIATRA Query engine instantiated on non-EMF scope " + scope); | ||
197 | } | ||
198 | |||
199 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/helper/ViatraQueryRuntimeHelper.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/helper/ViatraQueryRuntimeHelper.java deleted file mode 100644 index 93ac97f2..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/helper/ViatraQueryRuntimeHelper.java +++ /dev/null | |||
@@ -1,161 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Abel Hegedus, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.emf.helper; | ||
10 | |||
11 | import java.util.function.Function; | ||
12 | |||
13 | import org.eclipse.emf.ecore.EClassifier; | ||
14 | import org.eclipse.emf.ecore.EObject; | ||
15 | import org.eclipse.emf.ecore.EPackage; | ||
16 | import org.eclipse.emf.ecore.EStructuralFeature; | ||
17 | import tools.refinery.viatra.runtime.api.IPatternMatch; | ||
18 | |||
19 | /** | ||
20 | * Helper functions for dealing with the EMF objects with VIATRA Queries. | ||
21 | * | ||
22 | * @author Abel Hegedus | ||
23 | * @since 0.9 | ||
24 | * | ||
25 | */ | ||
26 | public class ViatraQueryRuntimeHelper { | ||
27 | |||
28 | private ViatraQueryRuntimeHelper() {/*Utility class constructor*/} | ||
29 | |||
30 | private static final Function<Object, String> STRING_VALUE_TRANSFORMER = input -> (input == null) ? "(null)" : input.toString(); | ||
31 | |||
32 | /** | ||
33 | * Gives a human-readable name of an EMF type. | ||
34 | */ | ||
35 | public static String prettyPrintEMFType(Object typeObject) { | ||
36 | if (typeObject == null) { | ||
37 | return "(null)"; | ||
38 | } else if (typeObject instanceof EClassifier) { | ||
39 | final EClassifier eClassifier = (EClassifier) typeObject; | ||
40 | final EPackage ePackage = eClassifier.getEPackage(); | ||
41 | final String nsURI = ePackage == null ? null : ePackage.getNsURI(); | ||
42 | final String typeName = eClassifier.getName(); | ||
43 | return "" + nsURI + "/" + typeName; | ||
44 | } else if (typeObject instanceof EStructuralFeature) { | ||
45 | final EStructuralFeature feature = (EStructuralFeature) typeObject; | ||
46 | return prettyPrintEMFType(feature.getEContainingClass()) + "." + feature.getName(); | ||
47 | } else | ||
48 | return typeObject.toString(); | ||
49 | } | ||
50 | |||
51 | |||
52 | /** | ||
53 | * Get the structural feature with the given name of the given object. | ||
54 | * | ||
55 | * @param o | ||
56 | * the object (must be an EObject) | ||
57 | * @param featureName | ||
58 | * the name of the feature | ||
59 | * @return the EStructuralFeature of the object or null if it can not be found | ||
60 | */ | ||
61 | public static EStructuralFeature getFeature(Object o, String featureName) { | ||
62 | if (o instanceof EObject) { | ||
63 | EStructuralFeature feature = ((EObject) o).eClass().getEStructuralFeature(featureName); | ||
64 | return feature; | ||
65 | } | ||
66 | return null; | ||
67 | } | ||
68 | |||
69 | /** | ||
70 | * Returns the message for the given match using the given format. The format string can refer to the value of | ||
71 | * parameter A of the match with $A$ and even access features of A (if it's an EObject), e.g. $A.id$. | ||
72 | * | ||
73 | * <p/> | ||
74 | * If the selected parameter does not exist, the string "[no such parameter]" is added | ||
75 | * | ||
76 | * <p/> | ||
77 | * If no feature is defined, but A has a feature called "name", then its value is used. | ||
78 | * | ||
79 | * <p/> | ||
80 | * If the selected feature does not exist, A.toString() is added. | ||
81 | * | ||
82 | * <p/> | ||
83 | * If the selected feature is null, the string "null" is added. | ||
84 | * | ||
85 | * @param match | ||
86 | * cannot be null! | ||
87 | * @param messageFormat | ||
88 | * cannot be null! | ||
89 | */ | ||
90 | public static String getMessage(IPatternMatch match, String messageFormat) { | ||
91 | return getMessage(match, messageFormat, STRING_VALUE_TRANSFORMER); | ||
92 | } | ||
93 | |||
94 | /** | ||
95 | * Returns the message for the given match using the given format while transforming values with the given function. | ||
96 | * The format string can refer to the value of parameter A of the match with $A$ and even access features of A (if | ||
97 | * it's an EObject), e.g. $A.id$. The function will be called to compute the final string representation of the | ||
98 | * values selected by the message format. | ||
99 | * | ||
100 | * <p/> | ||
101 | * If the selected parameter does not exist, the string "[no such parameter]" is added | ||
102 | * | ||
103 | * <p/> | ||
104 | * If no feature is defined, but A has a feature called "name", then its value is passed to the function. | ||
105 | * | ||
106 | * <p/> | ||
107 | * If the selected feature does not exist, A is passed to the function. | ||
108 | * | ||
109 | * <p/> | ||
110 | * If the selected feature is null, the string "null" is added. | ||
111 | * | ||
112 | * @param match | ||
113 | * cannot be null! | ||
114 | * @param messageFormat | ||
115 | * cannot be null! | ||
116 | * @param parameterValueTransformer | ||
117 | * cannot be null! | ||
118 | * @since 2.0 | ||
119 | */ | ||
120 | public static String getMessage(IPatternMatch match, String messageFormat, Function<Object,String> parameterValueTransformer) { | ||
121 | String[] tokens = messageFormat.split("\\$"); | ||
122 | StringBuilder newText = new StringBuilder(); | ||
123 | |||
124 | for (int i = 0; i < tokens.length; i++) { | ||
125 | if (i % 2 == 0) { | ||
126 | newText.append(tokens[i]); | ||
127 | } else { | ||
128 | String[] objectTokens = tokens[i].split("\\."); | ||
129 | if (objectTokens.length > 0) { | ||
130 | Object o = null; | ||
131 | EStructuralFeature feature = null; | ||
132 | |||
133 | if (objectTokens.length == 1) { | ||
134 | o = match.get(objectTokens[0]); | ||
135 | feature = getFeature(o, "name"); | ||
136 | } | ||
137 | if (objectTokens.length == 2) { | ||
138 | o = match.get(objectTokens[0]); | ||
139 | feature = getFeature(o, objectTokens[1]); | ||
140 | } | ||
141 | |||
142 | if (o != null && feature != null) { | ||
143 | Object value = ((EObject) o).eGet(feature); | ||
144 | if (value != null) { | ||
145 | newText.append(parameterValueTransformer.apply(value)); | ||
146 | } else { | ||
147 | newText.append("null"); | ||
148 | } | ||
149 | } else if (o != null) { | ||
150 | newText.append(parameterValueTransformer.apply(o)); | ||
151 | } | ||
152 | } else { | ||
153 | newText.append("[no such parameter]"); | ||
154 | } | ||
155 | } | ||
156 | } | ||
157 | |||
158 | return newText.toString(); | ||
159 | } | ||
160 | |||
161 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/types/BaseEMFTypeKey.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/types/BaseEMFTypeKey.java deleted file mode 100644 index c5dfa966..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/types/BaseEMFTypeKey.java +++ /dev/null | |||
@@ -1,34 +0,0 @@ | |||
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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.emf.types; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.matchers.context.common.BaseInputKeyWrapper; | ||
12 | |||
13 | /** | ||
14 | * Base class for EMF Type keys. | ||
15 | * @author Bergmann Gabor | ||
16 | * | ||
17 | */ | ||
18 | public abstract class BaseEMFTypeKey<EMFKey> extends BaseInputKeyWrapper<EMFKey> { | ||
19 | |||
20 | public BaseEMFTypeKey(EMFKey emfKey) { | ||
21 | super(emfKey); | ||
22 | } | ||
23 | |||
24 | public EMFKey getEmfKey() { | ||
25 | return getWrappedKey(); | ||
26 | } | ||
27 | |||
28 | @Override | ||
29 | public String toString() { | ||
30 | return this.getPrettyPrintableName(); | ||
31 | } | ||
32 | |||
33 | |||
34 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/types/EClassExactInstancesKey.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/types/EClassExactInstancesKey.java deleted file mode 100644 index dd10502d..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/types/EClassExactInstancesKey.java +++ /dev/null | |||
@@ -1,51 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2018, Gabor Bergmann, 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 | |||
10 | package tools.refinery.viatra.runtime.emf.types; | ||
11 | |||
12 | import org.eclipse.emf.ecore.EClass; | ||
13 | import tools.refinery.viatra.runtime.emf.EMFScope; | ||
14 | import tools.refinery.viatra.runtime.emf.helper.ViatraQueryRuntimeHelper; | ||
15 | |||
16 | /** | ||
17 | * Instance tuples are of form (x), where x is an eObject instance of the given eClass, but <b>not</b> one of its subclasses, <b>within the scope</b>. | ||
18 | * <p> This input key has the strict semantics that instances must be within the scope. | ||
19 | * | ||
20 | * @noreference This class is not intended to be referenced by clients. Not currently supported by {@link EMFScope}, for internal use only at the time | ||
21 | * | ||
22 | * @author Bergmann Gabor | ||
23 | * @since 2.1 | ||
24 | */ | ||
25 | public class EClassExactInstancesKey extends BaseEMFTypeKey<EClass> { | ||
26 | |||
27 | public EClassExactInstancesKey(EClass emfKey) { | ||
28 | super(emfKey); | ||
29 | } | ||
30 | |||
31 | @Override | ||
32 | public String getPrettyPrintableName() { | ||
33 | return "(scoped,exact) "+ViatraQueryRuntimeHelper.prettyPrintEMFType(wrappedKey); | ||
34 | } | ||
35 | |||
36 | @Override | ||
37 | public String getStringID() { | ||
38 | return "eClass(scoped,exact)#"+ ViatraQueryRuntimeHelper.prettyPrintEMFType(wrappedKey); | ||
39 | } | ||
40 | |||
41 | @Override | ||
42 | public int getArity() { | ||
43 | return 1; | ||
44 | } | ||
45 | |||
46 | @Override | ||
47 | public boolean isEnumerable() { | ||
48 | return true; | ||
49 | } | ||
50 | |||
51 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/types/EClassTransitiveInstancesKey.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/types/EClassTransitiveInstancesKey.java deleted file mode 100644 index 4ca6b220..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/types/EClassTransitiveInstancesKey.java +++ /dev/null | |||
@@ -1,47 +0,0 @@ | |||
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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.emf.types; | ||
10 | |||
11 | import org.eclipse.emf.ecore.EClass; | ||
12 | import tools.refinery.viatra.runtime.emf.EMFScope; | ||
13 | import tools.refinery.viatra.runtime.emf.helper.ViatraQueryRuntimeHelper; | ||
14 | |||
15 | /** | ||
16 | * Instance tuples are of form (x), where x is an eObject instance of the given eClass or one of its subclasses <b>within the scope</b>. | ||
17 | * <p> As of version 1.6, this input key has the strict semantics that instances must be within the {@link EMFScope}. | ||
18 | * @author Bergmann Gabor | ||
19 | * | ||
20 | */ | ||
21 | public class EClassTransitiveInstancesKey extends BaseEMFTypeKey<EClass> { | ||
22 | |||
23 | public EClassTransitiveInstancesKey(EClass emfKey) { | ||
24 | super(emfKey); | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String getPrettyPrintableName() { | ||
29 | return "(scoped) "+ViatraQueryRuntimeHelper.prettyPrintEMFType(wrappedKey); | ||
30 | } | ||
31 | |||
32 | @Override | ||
33 | public String getStringID() { | ||
34 | return "eClass(scoped)#"+ ViatraQueryRuntimeHelper.prettyPrintEMFType(wrappedKey); | ||
35 | } | ||
36 | |||
37 | @Override | ||
38 | public int getArity() { | ||
39 | return 1; | ||
40 | } | ||
41 | |||
42 | @Override | ||
43 | public boolean isEnumerable() { | ||
44 | return true; | ||
45 | } | ||
46 | |||
47 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/types/EClassUnscopedTransitiveInstancesKey.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/types/EClassUnscopedTransitiveInstancesKey.java deleted file mode 100644 index 11c5b235..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/types/EClassUnscopedTransitiveInstancesKey.java +++ /dev/null | |||
@@ -1,46 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.emf.types; | ||
10 | |||
11 | import org.eclipse.emf.ecore.EClass; | ||
12 | import tools.refinery.viatra.runtime.emf.helper.ViatraQueryRuntimeHelper; | ||
13 | |||
14 | /** | ||
15 | * Instance tuples are of form (x), where x is an eObject instance of the given eClass or one of its subclasses <b>regardless whether it is within the scope</b>. | ||
16 | * | ||
17 | * @author Bergmann Gabor | ||
18 | * @since 1.6 | ||
19 | */ | ||
20 | public class EClassUnscopedTransitiveInstancesKey extends BaseEMFTypeKey<EClass> { | ||
21 | |||
22 | public EClassUnscopedTransitiveInstancesKey(EClass emfKey) { | ||
23 | super(emfKey); | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public String getPrettyPrintableName() { | ||
28 | return "(unscoped) "+ViatraQueryRuntimeHelper.prettyPrintEMFType(wrappedKey); | ||
29 | } | ||
30 | |||
31 | @Override | ||
32 | public String getStringID() { | ||
33 | return "eClass(unscoped)#"+ ViatraQueryRuntimeHelper.prettyPrintEMFType(wrappedKey); | ||
34 | } | ||
35 | |||
36 | @Override | ||
37 | public int getArity() { | ||
38 | return 1; | ||
39 | } | ||
40 | |||
41 | @Override | ||
42 | public boolean isEnumerable() { | ||
43 | return false; | ||
44 | } | ||
45 | |||
46 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/types/EDataTypeInSlotsKey.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/types/EDataTypeInSlotsKey.java deleted file mode 100644 index a1cc4863..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/types/EDataTypeInSlotsKey.java +++ /dev/null | |||
@@ -1,48 +0,0 @@ | |||
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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.emf.types; | ||
10 | |||
11 | import org.eclipse.emf.ecore.EDataType; | ||
12 | import tools.refinery.viatra.runtime.emf.helper.ViatraQueryRuntimeHelper; | ||
13 | |||
14 | /** | ||
15 | * Instance tuples are of form (x), where x is an instance of the given eDataType residing at an attribute slot of an eObject in the model. | ||
16 | * @author Bergmann Gabor | ||
17 | * | ||
18 | */ | ||
19 | public class EDataTypeInSlotsKey extends BaseEMFTypeKey<EDataType> { | ||
20 | |||
21 | /** | ||
22 | * @param emfKey | ||
23 | */ | ||
24 | public EDataTypeInSlotsKey(EDataType emfKey) { | ||
25 | super(emfKey); | ||
26 | } | ||
27 | |||
28 | @Override | ||
29 | public String getPrettyPrintableName() { | ||
30 | return "(Attribute Slot Values: " + ViatraQueryRuntimeHelper.prettyPrintEMFType(wrappedKey) + ")"; | ||
31 | } | ||
32 | |||
33 | @Override | ||
34 | public String getStringID() { | ||
35 | return "slotValue#" + ViatraQueryRuntimeHelper.prettyPrintEMFType(wrappedKey); | ||
36 | } | ||
37 | |||
38 | @Override | ||
39 | public int getArity() { | ||
40 | return 1; | ||
41 | } | ||
42 | |||
43 | @Override | ||
44 | public boolean isEnumerable() { | ||
45 | return true; | ||
46 | } | ||
47 | |||
48 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/types/EStructuralFeatureInstancesKey.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/types/EStructuralFeatureInstancesKey.java deleted file mode 100644 index 357f5e7e..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/emf/types/EStructuralFeatureInstancesKey.java +++ /dev/null | |||
@@ -1,48 +0,0 @@ | |||
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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.emf.types; | ||
10 | |||
11 | import org.eclipse.emf.ecore.EStructuralFeature; | ||
12 | import tools.refinery.viatra.runtime.emf.EMFScope; | ||
13 | import tools.refinery.viatra.runtime.emf.helper.ViatraQueryRuntimeHelper; | ||
14 | |||
15 | /** | ||
16 | * Instance tuples are of form (x, y), where x is an eObject that has y as the value of the given feature (or one of the values in case of multi-valued). | ||
17 | * | ||
18 | * <p> As of version 1.6, this input key has the strict semantics that x must be within the {@link EMFScope}, scoping is <b>not</b> implied for y. | ||
19 | * @author Bergmann Gabor | ||
20 | * | ||
21 | */ | ||
22 | public class EStructuralFeatureInstancesKey extends BaseEMFTypeKey<EStructuralFeature> { | ||
23 | |||
24 | public EStructuralFeatureInstancesKey(EStructuralFeature emfKey) { | ||
25 | super(emfKey); | ||
26 | } | ||
27 | |||
28 | @Override | ||
29 | public String getPrettyPrintableName() { | ||
30 | return ViatraQueryRuntimeHelper.prettyPrintEMFType(wrappedKey); | ||
31 | } | ||
32 | |||
33 | @Override | ||
34 | public String getStringID() { | ||
35 | return "feature#"+ getPrettyPrintableName(); | ||
36 | } | ||
37 | |||
38 | @Override | ||
39 | public int getArity() { | ||
40 | return 2; | ||
41 | } | ||
42 | |||
43 | @Override | ||
44 | public boolean isEnumerable() { | ||
45 | return true; | ||
46 | } | ||
47 | |||
48 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/extensibility/IQueryGroupProvider.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/extensibility/IQueryGroupProvider.java deleted file mode 100644 index 45594b5b..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/extensibility/IQueryGroupProvider.java +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.extensibility; | ||
10 | |||
11 | import java.util.Set; | ||
12 | |||
13 | import tools.refinery.viatra.runtime.api.IQueryGroup; | ||
14 | import tools.refinery.viatra.runtime.matchers.util.IProvider; | ||
15 | |||
16 | /** | ||
17 | * Provider interface for {@link IQueryGroup} instances with added method for | ||
18 | * requesting the set of FQNs for the query specifications in the group. | ||
19 | * | ||
20 | * @author Abel Hegedus | ||
21 | * @since 1.3 | ||
22 | * | ||
23 | */ | ||
24 | public interface IQueryGroupProvider extends IProvider<IQueryGroup> { | ||
25 | |||
26 | /** | ||
27 | * Note that the provider should load the query group class only if the FQNs can not be computed in other ways. | ||
28 | * | ||
29 | * @return the set of query specification FQNs in the group | ||
30 | */ | ||
31 | Set<String> getQuerySpecificationFQNs(); | ||
32 | |||
33 | /** | ||
34 | * Note that the provider should load the query group class only if the FQNs can not be computed in other ways. | ||
35 | * | ||
36 | * @return a set of providers for query specifications in the group | ||
37 | */ | ||
38 | Set<IQuerySpecificationProvider> getQuerySpecificationProviders(); | ||
39 | |||
40 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/extensibility/IQuerySpecificationProvider.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/extensibility/IQuerySpecificationProvider.java deleted file mode 100644 index 3c9c235d..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/extensibility/IQuerySpecificationProvider.java +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.extensibility; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.api.IQuerySpecification; | ||
12 | import tools.refinery.viatra.runtime.matchers.util.IProvider; | ||
13 | |||
14 | /** | ||
15 | * Provider interface for {@link IQuerySpecification} instances with added method for | ||
16 | * requesting the FQN for the query specification. | ||
17 | * | ||
18 | * @author Abel Hegedus | ||
19 | * @since 1.3 | ||
20 | * | ||
21 | */ | ||
22 | public interface IQuerySpecificationProvider extends IProvider<IQuerySpecification<?>> { | ||
23 | |||
24 | /** | ||
25 | * Note that the provider will usually not load the query specification class to return the FQN. | ||
26 | * | ||
27 | * @return the fully qualified name of the provided query specification | ||
28 | */ | ||
29 | String getFullyQualifiedName(); | ||
30 | |||
31 | /** | ||
32 | * Returns the name of project providing the specification (or null if not calculable) | ||
33 | */ | ||
34 | String getSourceProjectName(); | ||
35 | |||
36 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/extensibility/PQueryExtensionFactory.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/extensibility/PQueryExtensionFactory.java deleted file mode 100644 index 91e087d7..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/extensibility/PQueryExtensionFactory.java +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Zoltan Ujhelyi, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.extensibility; | ||
10 | |||
11 | import org.eclipse.core.runtime.CoreException; | ||
12 | import org.eclipse.core.runtime.IStatus; | ||
13 | import org.eclipse.core.runtime.Status; | ||
14 | import tools.refinery.viatra.runtime.api.IQuerySpecification; | ||
15 | |||
16 | /** | ||
17 | * An extension factory to access PQuery instances from Query Specifications. | ||
18 | * | ||
19 | * @author Zoltan Ujhelyi | ||
20 | * | ||
21 | */ | ||
22 | public class PQueryExtensionFactory extends SingletonExtensionFactory { | ||
23 | |||
24 | @Override | ||
25 | public Object create() throws CoreException { | ||
26 | final Object _spec = super.create(); | ||
27 | if (_spec instanceof IQuerySpecification<?>) { | ||
28 | return ((IQuerySpecification<?>) _spec).getInternalQueryRepresentation(); | ||
29 | } | ||
30 | throw new CoreException(new Status(IStatus.ERROR, getBundle().getSymbolicName(), "Cannot instantiate PQuery instance.")); | ||
31 | } | ||
32 | |||
33 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/extensibility/SingletonExtensionFactory.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/extensibility/SingletonExtensionFactory.java deleted file mode 100644 index 29705968..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/extensibility/SingletonExtensionFactory.java +++ /dev/null | |||
@@ -1,62 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Zoltan Ujhelyi, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.extensibility; | ||
10 | |||
11 | import java.lang.reflect.Method; | ||
12 | |||
13 | import org.eclipse.core.runtime.CoreException; | ||
14 | import org.eclipse.core.runtime.IConfigurationElement; | ||
15 | import org.eclipse.core.runtime.IExecutableExtension; | ||
16 | import org.eclipse.core.runtime.IExecutableExtensionFactory; | ||
17 | import org.eclipse.core.runtime.IStatus; | ||
18 | import org.eclipse.core.runtime.Platform; | ||
19 | import org.eclipse.core.runtime.Status; | ||
20 | import org.osgi.framework.Bundle; | ||
21 | |||
22 | /** | ||
23 | * Factory to register a static singleton instance in an extension point. | ||
24 | * | ||
25 | * @author Zoltan Ujhelyi | ||
26 | * | ||
27 | */ | ||
28 | public class SingletonExtensionFactory implements IExecutableExtension, IExecutableExtensionFactory { | ||
29 | |||
30 | private String clazzName; | ||
31 | private Bundle bundle; | ||
32 | |||
33 | protected Bundle getBundle() { | ||
34 | return bundle; | ||
35 | } | ||
36 | |||
37 | @Override | ||
38 | public Object create() throws CoreException { | ||
39 | try { | ||
40 | final Class<?> clazz = bundle.loadClass(clazzName); | ||
41 | Method method = clazz.getMethod("instance"); | ||
42 | return method.invoke(null); | ||
43 | } catch (Exception e) { | ||
44 | throw new CoreException(new Status(IStatus.ERROR, bundle.getSymbolicName(), "Error loading group " | ||
45 | + clazzName, e)); | ||
46 | } | ||
47 | } | ||
48 | |||
49 | @Override | ||
50 | public void setInitializationData(IConfigurationElement config, String propertyName, Object data) | ||
51 | throws CoreException { | ||
52 | String id = config.getContributor().getName(); | ||
53 | bundle = Platform.getBundle(id); | ||
54 | if (data instanceof String) { | ||
55 | clazzName = (String) data; | ||
56 | } else { | ||
57 | throw new CoreException(new Status(IStatus.ERROR, bundle.getSymbolicName(), | ||
58 | "Unsupported extension initialization data: " + data)); | ||
59 | } | ||
60 | } | ||
61 | |||
62 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/extensibility/SingletonQueryGroupProvider.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/extensibility/SingletonQueryGroupProvider.java deleted file mode 100644 index 758b51dd..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/extensibility/SingletonQueryGroupProvider.java +++ /dev/null | |||
@@ -1,46 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.extensibility; | ||
10 | |||
11 | import java.util.Set; | ||
12 | import java.util.stream.Collectors; | ||
13 | |||
14 | import tools.refinery.viatra.runtime.api.IQueryGroup; | ||
15 | import tools.refinery.viatra.runtime.api.IQuerySpecification; | ||
16 | import tools.refinery.viatra.runtime.matchers.util.SingletonInstanceProvider; | ||
17 | |||
18 | /** | ||
19 | * Provider implementation for storing an existing query group instance. | ||
20 | * | ||
21 | * @author Abel Hegedus | ||
22 | * @since 1.3 | ||
23 | * | ||
24 | */ | ||
25 | public class SingletonQueryGroupProvider extends SingletonInstanceProvider<IQueryGroup> implements IQueryGroupProvider { | ||
26 | |||
27 | /** | ||
28 | * @param instance the instance to wrap | ||
29 | */ | ||
30 | public SingletonQueryGroupProvider(IQueryGroup instance) { | ||
31 | super(instance); | ||
32 | } | ||
33 | |||
34 | @Override | ||
35 | public Set<String> getQuerySpecificationFQNs() { | ||
36 | return get().getSpecifications().stream().map(IQuerySpecification::getFullyQualifiedName) | ||
37 | .collect(Collectors.toSet()); | ||
38 | } | ||
39 | |||
40 | @Override | ||
41 | public Set<IQuerySpecificationProvider> getQuerySpecificationProviders() { | ||
42 | return get().getSpecifications().stream().map(SingletonQuerySpecificationProvider::new) | ||
43 | .collect(Collectors.toSet()); | ||
44 | } | ||
45 | |||
46 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/extensibility/SingletonQuerySpecificationProvider.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/extensibility/SingletonQuerySpecificationProvider.java deleted file mode 100644 index f8f3a741..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/extensibility/SingletonQuerySpecificationProvider.java +++ /dev/null | |||
@@ -1,42 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.extensibility; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.api.IQuerySpecification; | ||
12 | import tools.refinery.viatra.runtime.matchers.util.SingletonInstanceProvider; | ||
13 | |||
14 | /** | ||
15 | * Provider implementation for storing an existing query specification instance. | ||
16 | * | ||
17 | * @author Abel Hegedus | ||
18 | * @since 1.3 | ||
19 | * | ||
20 | */ | ||
21 | public class SingletonQuerySpecificationProvider extends SingletonInstanceProvider<IQuerySpecification<?>> | ||
22 | implements IQuerySpecificationProvider { | ||
23 | |||
24 | /** | ||
25 | * | ||
26 | * @param instance the instance to wrap | ||
27 | */ | ||
28 | public SingletonQuerySpecificationProvider(IQuerySpecification<?> instance) { | ||
29 | super(instance); | ||
30 | } | ||
31 | |||
32 | @Override | ||
33 | public String getFullyQualifiedName() { | ||
34 | return get().getFullyQualifiedName(); | ||
35 | } | ||
36 | |||
37 | @Override | ||
38 | public String getSourceProjectName() { | ||
39 | return null; | ||
40 | } | ||
41 | |||
42 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/extensibility/ViatraQueryRuntimeConstants.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/extensibility/ViatraQueryRuntimeConstants.java deleted file mode 100644 index 9b0850e4..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/extensibility/ViatraQueryRuntimeConstants.java +++ /dev/null | |||
@@ -1,27 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Abel Hegedus, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.extensibility; | ||
10 | |||
11 | /** | ||
12 | * Utility class for Viatra Query runtime constants, such as extension point identifiers. | ||
13 | * | ||
14 | * @author Abel Hegedus | ||
15 | * | ||
16 | */ | ||
17 | public final class ViatraQueryRuntimeConstants { | ||
18 | |||
19 | private ViatraQueryRuntimeConstants() {/* Constructor hidden for utility class */} | ||
20 | |||
21 | // Surrogate query extension | ||
22 | |||
23 | public static final String SURROGATE_QUERY_EXTENSIONID = "tools.refinery.viatra.runtime.surrogatequeryemf"; | ||
24 | |||
25 | |||
26 | |||
27 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/internal/ExtensionBasedSurrogateQueryLoader.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/internal/ExtensionBasedSurrogateQueryLoader.java deleted file mode 100644 index af7cdaf1..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/internal/ExtensionBasedSurrogateQueryLoader.java +++ /dev/null | |||
@@ -1,148 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Abel Hegedus, Zoltan Ujhelyi, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.internal; | ||
10 | |||
11 | import static tools.refinery.viatra.runtime.matchers.util.Preconditions.checkState; | ||
12 | |||
13 | import java.util.Arrays; | ||
14 | import java.util.Collection; | ||
15 | import java.util.HashMap; | ||
16 | import java.util.Map; | ||
17 | import java.util.Map.Entry; | ||
18 | |||
19 | import org.apache.log4j.Logger; | ||
20 | import org.eclipse.core.runtime.CoreException; | ||
21 | import org.eclipse.core.runtime.IConfigurationElement; | ||
22 | import org.eclipse.core.runtime.Platform; | ||
23 | import org.eclipse.emf.ecore.EClass; | ||
24 | import org.eclipse.emf.ecore.EClassifier; | ||
25 | import org.eclipse.emf.ecore.EPackage; | ||
26 | import org.eclipse.emf.ecore.EStructuralFeature; | ||
27 | import tools.refinery.viatra.runtime.emf.types.EStructuralFeatureInstancesKey; | ||
28 | import tools.refinery.viatra.runtime.extensibility.ViatraQueryRuntimeConstants; | ||
29 | import tools.refinery.viatra.runtime.matchers.context.IInputKey; | ||
30 | import tools.refinery.viatra.runtime.matchers.context.surrogate.SurrogateQueryRegistry; | ||
31 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
32 | import tools.refinery.viatra.runtime.matchers.util.IProvider; | ||
33 | |||
34 | /** | ||
35 | * @author Abel Hegedus | ||
36 | * | ||
37 | */ | ||
38 | public class ExtensionBasedSurrogateQueryLoader { | ||
39 | |||
40 | private static final String DUPLICATE_SURROGATE_QUERY = "Duplicate surrogate query definition %s for feature %s of EClass %s in package %s (FQN in map %s, contributing plug-ins %s, plug-in %s)"; | ||
41 | |||
42 | private Map<String, String> contributingPluginOfFeatureMap = new HashMap<>(); | ||
43 | private Map<EStructuralFeature, PQueryProvider> contributedSurrogateQueries; | ||
44 | |||
45 | private static final ExtensionBasedSurrogateQueryLoader INSTANCE = new ExtensionBasedSurrogateQueryLoader(); | ||
46 | |||
47 | /** | ||
48 | * A provider implementation for PQuery instances based on extension elements. It is expected that the getter will only | ||
49 | * @author Zoltan Ujhelyi | ||
50 | * | ||
51 | */ | ||
52 | private static final class PQueryProvider implements IProvider<PQuery> { | ||
53 | |||
54 | private final IConfigurationElement element; | ||
55 | private PQuery query; | ||
56 | |||
57 | public PQueryProvider(IConfigurationElement element) { | ||
58 | this.element = element; | ||
59 | this.query = null; | ||
60 | } | ||
61 | |||
62 | @Override | ||
63 | public PQuery get() { | ||
64 | try { | ||
65 | if (query == null) { | ||
66 | query = (PQuery) element.createExecutableExtension("surrogate-query"); | ||
67 | } | ||
68 | return query; | ||
69 | } catch (CoreException e) { | ||
70 | throw new IllegalArgumentException("Error initializing surrogate query", e); | ||
71 | } | ||
72 | } | ||
73 | } | ||
74 | |||
75 | public static ExtensionBasedSurrogateQueryLoader instance() { | ||
76 | return INSTANCE; | ||
77 | } | ||
78 | |||
79 | public void loadKnownSurrogateQueriesIntoRegistry() { | ||
80 | Map<EStructuralFeature, PQueryProvider> knownSurrogateQueryFQNs = getSurrogateQueryProviders(); | ||
81 | for (Entry<EStructuralFeature, PQueryProvider> entry : knownSurrogateQueryFQNs.entrySet()) { | ||
82 | final IInputKey inputKey = new EStructuralFeatureInstancesKey(entry.getKey()); | ||
83 | SurrogateQueryRegistry.instance().registerSurrogateQueryForFeature(inputKey, entry.getValue()); | ||
84 | } | ||
85 | } | ||
86 | |||
87 | private Map<EStructuralFeature, PQueryProvider> getSurrogateQueryProviders() { | ||
88 | if(contributedSurrogateQueries != null) { | ||
89 | return contributedSurrogateQueries; | ||
90 | } | ||
91 | contributedSurrogateQueries = new HashMap<>(); | ||
92 | if (Platform.isRunning()) { | ||
93 | for (IConfigurationElement e : Platform.getExtensionRegistry().getConfigurationElementsFor(ViatraQueryRuntimeConstants.SURROGATE_QUERY_EXTENSIONID)) { | ||
94 | if (e.isValid()) { | ||
95 | processExtension(e); | ||
96 | } | ||
97 | } | ||
98 | } | ||
99 | return contributedSurrogateQueries; | ||
100 | } | ||
101 | |||
102 | private void processExtension(IConfigurationElement el) { | ||
103 | |||
104 | try { | ||
105 | String packageUri = el.getAttribute("package-nsUri"); | ||
106 | String className = el.getAttribute("class-name"); | ||
107 | String featureName = el.getAttribute("feature-name"); | ||
108 | String queryFqn = el.getAttribute("query-fqn"); | ||
109 | if (queryFqn == null) { | ||
110 | queryFqn = ""; | ||
111 | } | ||
112 | PQueryProvider surrogateQueryProvider = new PQueryProvider(el); | ||
113 | |||
114 | String contributorName = el.getContributor().getName(); | ||
115 | StringBuilder featureIdBuilder = new StringBuilder(); | ||
116 | checkState(packageUri != null, "Package NsURI cannot be null in extension"); | ||
117 | checkState(className != null, "Class name cannot be null in extension"); | ||
118 | checkState(featureName != null, "Feature name cannot be null in extension"); | ||
119 | |||
120 | EPackage pckg = EPackage.Registry.INSTANCE.getEPackage(packageUri); | ||
121 | featureIdBuilder.append(packageUri); | ||
122 | checkState(pckg != null, "Package %s not found! (plug-in %s)", packageUri, contributorName); | ||
123 | |||
124 | EClassifier clsr = pckg.getEClassifier(className); | ||
125 | featureIdBuilder.append("##").append(className); | ||
126 | checkState(clsr instanceof EClass, "EClassifier %s does not exist in package %s! (plug-in %s)", className, packageUri, contributorName); | ||
127 | |||
128 | EClass cls = (EClass) clsr; | ||
129 | EStructuralFeature feature = cls.getEStructuralFeature(featureName); | ||
130 | featureIdBuilder.append("##").append(featureName); | ||
131 | checkState(feature != null, "Feature %s of EClass %s in package %s not found! (plug-in %s)", featureName, className, packageUri, contributorName); | ||
132 | |||
133 | PQueryProvider fqnInMap = contributedSurrogateQueries.get(feature); | ||
134 | if(fqnInMap != null) { | ||
135 | String duplicateSurrogateFormatString = DUPLICATE_SURROGATE_QUERY; | ||
136 | Collection<String> contributorPlugins = Arrays.asList(contributorName, contributingPluginOfFeatureMap.get(featureIdBuilder.toString())); | ||
137 | String duplicateSurrogateMessage = String.format(duplicateSurrogateFormatString, queryFqn, featureName, | ||
138 | className, packageUri, fqnInMap, contributorPlugins, contributorName); | ||
139 | throw new IllegalStateException(duplicateSurrogateMessage); | ||
140 | } | ||
141 | contributedSurrogateQueries.put(feature, surrogateQueryProvider); | ||
142 | contributingPluginOfFeatureMap.put(featureIdBuilder.toString(), contributorName); | ||
143 | } catch (Exception e) { | ||
144 | final Logger logger = Logger.getLogger(SurrogateQueryRegistry.class); | ||
145 | logger.error("Surrogate query registration failed", e); | ||
146 | } | ||
147 | } | ||
148 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/internal/ExtensionBasedSystemDefaultBackendLoader.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/internal/ExtensionBasedSystemDefaultBackendLoader.java deleted file mode 100644 index 4339b70c..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/internal/ExtensionBasedSystemDefaultBackendLoader.java +++ /dev/null | |||
@@ -1,60 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2018, Zoltan Ujhelyi, IncQuery Labs | ||
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.internal; | ||
10 | |||
11 | import org.eclipse.core.runtime.CoreException; | ||
12 | import org.eclipse.core.runtime.IConfigurationElement; | ||
13 | import org.eclipse.core.runtime.Platform; | ||
14 | import tools.refinery.viatra.runtime.api.ViatraQueryEngineOptions; | ||
15 | import tools.refinery.viatra.runtime.matchers.backend.IQueryBackendFactory; | ||
16 | import tools.refinery.viatra.runtime.matchers.backend.IQueryBackendFactoryProvider; | ||
17 | import tools.refinery.viatra.runtime.util.ViatraQueryLoggingUtil; | ||
18 | |||
19 | /** | ||
20 | * @since 2.0 | ||
21 | */ | ||
22 | public class ExtensionBasedSystemDefaultBackendLoader { | ||
23 | |||
24 | private static final String EXTENSION_ID = "tools.refinery.viatra.runtime.querybackend"; | ||
25 | private static final ExtensionBasedSystemDefaultBackendLoader INSTANCE = new ExtensionBasedSystemDefaultBackendLoader(); | ||
26 | |||
27 | public static ExtensionBasedSystemDefaultBackendLoader instance() { | ||
28 | return INSTANCE; | ||
29 | } | ||
30 | |||
31 | public void loadKnownBackends() { | ||
32 | IQueryBackendFactory defaultBackend = null; | ||
33 | IQueryBackendFactory defaultCachingBackend = null; | ||
34 | IQueryBackendFactory defaultSearchBackend = null; | ||
35 | final IConfigurationElement[] config = Platform.getExtensionRegistry().getConfigurationElementsFor(EXTENSION_ID); | ||
36 | for (IConfigurationElement e : config) { | ||
37 | try { | ||
38 | IQueryBackendFactoryProvider provider = (IQueryBackendFactoryProvider) e | ||
39 | .createExecutableExtension("provider"); | ||
40 | if (provider.isSystemDefaultEngine()) { | ||
41 | defaultBackend = provider.getFactory(); | ||
42 | } | ||
43 | if (provider.isSystemDefaultCachingBackend()) { | ||
44 | defaultCachingBackend = provider.getFactory(); | ||
45 | } | ||
46 | if (provider.isSystemDefaultSearchBackend()) { | ||
47 | defaultSearchBackend = provider.getFactory(); | ||
48 | } | ||
49 | |||
50 | } catch (CoreException ex) { | ||
51 | // In case errors try to continue with the next one | ||
52 | ViatraQueryLoggingUtil.getLogger(getClass()).error( | ||
53 | String.format("Error while initializing backend %s from plugin %s.", | ||
54 | e.getAttribute("backend"), e.getContributor().getName()), ex); | ||
55 | } | ||
56 | } | ||
57 | ViatraQueryEngineOptions.setSystemDefaultBackends(defaultBackend, defaultCachingBackend, defaultSearchBackend); | ||
58 | } | ||
59 | |||
60 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/internal/apiimpl/ViatraQueryEngineImpl.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/internal/apiimpl/ViatraQueryEngineImpl.java index c2341273..a3a9d073 100644 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/internal/apiimpl/ViatraQueryEngineImpl.java +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/internal/apiimpl/ViatraQueryEngineImpl.java | |||
@@ -34,9 +34,6 @@ import tools.refinery.viatra.runtime.matchers.util.CollectionsFactory; | |||
34 | import tools.refinery.viatra.runtime.matchers.util.CollectionsFactory.MemoryType; | 34 | import tools.refinery.viatra.runtime.matchers.util.CollectionsFactory.MemoryType; |
35 | import tools.refinery.viatra.runtime.matchers.util.IMultiLookup; | 35 | import tools.refinery.viatra.runtime.matchers.util.IMultiLookup; |
36 | import tools.refinery.viatra.runtime.matchers.util.Preconditions; | 36 | import tools.refinery.viatra.runtime.matchers.util.Preconditions; |
37 | import tools.refinery.viatra.runtime.registry.IDefaultRegistryView; | ||
38 | import tools.refinery.viatra.runtime.registry.IQuerySpecificationRegistry; | ||
39 | import tools.refinery.viatra.runtime.registry.QuerySpecificationRegistry; | ||
40 | import tools.refinery.viatra.runtime.util.ViatraQueryLoggingUtil; | 37 | import tools.refinery.viatra.runtime.util.ViatraQueryLoggingUtil; |
41 | 38 | ||
42 | import java.lang.ref.WeakReference; | 39 | import java.lang.ref.WeakReference; |
@@ -227,17 +224,7 @@ public final class ViatraQueryEngineImpl extends AdvancedViatraQueryEngine | |||
227 | 224 | ||
228 | @Override | 225 | @Override |
229 | public ViatraQueryMatcher<? extends IPatternMatch> getMatcher(String patternFQN) { | 226 | public ViatraQueryMatcher<? extends IPatternMatch> getMatcher(String patternFQN) { |
230 | IQuerySpecificationRegistry registry = QuerySpecificationRegistry.getInstance(); | 227 | throw new UnsupportedOperationException("Query specification registry is not available"); |
231 | IDefaultRegistryView view = registry.getDefaultView(); | ||
232 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> querySpecification = view | ||
233 | .getEntry(patternFQN).get(); | ||
234 | if (querySpecification != null) { | ||
235 | return getMatcher(querySpecification); | ||
236 | } else { | ||
237 | throw new ViatraQueryException(String.format( | ||
238 | "No matcher could be constructed for the pattern with FQN %s; if the generated matcher class is not available, please access for the first time using getMatcher(IQuerySpecification)", | ||
239 | patternFQN), "No matcher could be constructed for given pattern FQN."); | ||
240 | } | ||
241 | } | 228 | } |
242 | 229 | ||
243 | @Override | 230 | @Override |
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/ExtensionBasedQuerySpecificationLoader.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/ExtensionBasedQuerySpecificationLoader.java deleted file mode 100644 index 40bf3e67..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/ExtensionBasedQuerySpecificationLoader.java +++ /dev/null | |||
@@ -1,303 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.registry; | ||
10 | |||
11 | import java.util.HashMap; | ||
12 | import java.util.HashSet; | ||
13 | import java.util.Map; | ||
14 | import java.util.Objects; | ||
15 | import java.util.Set; | ||
16 | |||
17 | import org.eclipse.core.runtime.CoreException; | ||
18 | import org.eclipse.core.runtime.IConfigurationElement; | ||
19 | import org.eclipse.core.runtime.Platform; | ||
20 | import tools.refinery.viatra.runtime.IExtensions; | ||
21 | import tools.refinery.viatra.runtime.api.IQueryGroup; | ||
22 | import tools.refinery.viatra.runtime.api.IQuerySpecification; | ||
23 | import tools.refinery.viatra.runtime.extensibility.IQueryGroupProvider; | ||
24 | import tools.refinery.viatra.runtime.extensibility.IQuerySpecificationProvider; | ||
25 | import tools.refinery.viatra.runtime.matchers.util.CollectionsFactory; | ||
26 | import tools.refinery.viatra.runtime.matchers.util.CollectionsFactory.MemoryType; | ||
27 | import tools.refinery.viatra.runtime.matchers.util.IMemoryView; | ||
28 | import tools.refinery.viatra.runtime.matchers.util.IMultiLookup; | ||
29 | import tools.refinery.viatra.runtime.util.ViatraQueryLoggingUtil; | ||
30 | |||
31 | /** | ||
32 | * Loader for the {@link QuerySpecificationRegistry} based on the query group extensions generated by the VIATRA Query | ||
33 | * builder. The loader has a single instance that processes the extensions on demand if the platform is running, caches | ||
34 | * the results and updates the {@link QuerySpecificationRegistry}. Note that the loader does not perform class loading | ||
35 | * on the query group if possible. | ||
36 | * | ||
37 | * <p> | ||
38 | * The class has a single instance accessible with {@link #getInstance()}. | ||
39 | * | ||
40 | * @author Abel Hegedus | ||
41 | * @since 1.3 | ||
42 | * | ||
43 | */ | ||
44 | public class ExtensionBasedQuerySpecificationLoader { | ||
45 | |||
46 | public static final String CONNECTOR_ID = "tools.refinery.viatra.runtime.querygroup.extension.based.connector"; | ||
47 | |||
48 | private static final String DUPLICATE_QUERY_GROUP_MESSAGE = "Duplicate query group identifier %s for plugin %s (already contributed by %s)"; | ||
49 | private static final ExtensionBasedQuerySpecificationLoader INSTANCE = new ExtensionBasedQuerySpecificationLoader(); | ||
50 | |||
51 | private IMultiLookup<String, String> contributingPluginOfGroupMap = | ||
52 | CollectionsFactory.createMultiLookup(Object.class, MemoryType.SETS, Object.class); | ||
53 | private Map<String, QueryGroupProvider> contributedQueryGroups; | ||
54 | |||
55 | private ExtensionBasedSourceConnector sourceConnector; | ||
56 | |||
57 | |||
58 | /** | ||
59 | * @return the single instance of the loader. | ||
60 | */ | ||
61 | public static ExtensionBasedQuerySpecificationLoader getInstance() { | ||
62 | return INSTANCE; | ||
63 | } | ||
64 | |||
65 | /** | ||
66 | * Loads the query specifications that are registered through extension points into the | ||
67 | * {@link QuerySpecificationRegistry}. | ||
68 | */ | ||
69 | public void loadRegisteredQuerySpecificationsIntoRegistry() { | ||
70 | ((QuerySpecificationRegistry) QuerySpecificationRegistry.getInstance()).addDelayedSourceConnector(getSourceConnector()); | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * Return a source connector that can be used to load query specifications contributed through | ||
75 | * extensions into a {@link IQuerySpecificationRegistry}. | ||
76 | * | ||
77 | * @return the source connector | ||
78 | */ | ||
79 | public IRegistrySourceConnector getSourceConnector() { | ||
80 | if (this.sourceConnector == null) { | ||
81 | this.sourceConnector = new ExtensionBasedSourceConnector(); | ||
82 | } | ||
83 | return sourceConnector; | ||
84 | } | ||
85 | |||
86 | private Map<String, QueryGroupProvider> getRegisteredQueryGroups() { | ||
87 | if(contributedQueryGroups != null) { | ||
88 | return contributedQueryGroups; | ||
89 | } | ||
90 | contributedQueryGroups = new HashMap<>(); | ||
91 | if (Platform.isRunning()) { | ||
92 | for (IConfigurationElement e : Platform.getExtensionRegistry().getConfigurationElementsFor(IExtensions.QUERY_SPECIFICATION_EXTENSION_POINT_ID)) { | ||
93 | if (e.isValid()) { | ||
94 | processExtension(e); | ||
95 | } | ||
96 | } | ||
97 | } | ||
98 | return contributedQueryGroups; | ||
99 | } | ||
100 | |||
101 | private void processExtension(IConfigurationElement el) { | ||
102 | String id = null; | ||
103 | try { | ||
104 | String contributorName = el.getContributor().getName(); | ||
105 | id = el.getAttribute("id"); | ||
106 | if(id == null) { | ||
107 | throw new IllegalStateException(String.format("Query group extension identifier is required (plug-in: %s)!", contributorName)); | ||
108 | } | ||
109 | |||
110 | QueryGroupProvider provider = new QueryGroupProvider(el); | ||
111 | |||
112 | QueryGroupProvider queryGroupInMap = contributedQueryGroups.get(id); | ||
113 | if(queryGroupInMap != null) { | ||
114 | IMemoryView<String> contributorPlugins = contributingPluginOfGroupMap.lookupOrEmpty(id); | ||
115 | throw new IllegalStateException(String.format(DUPLICATE_QUERY_GROUP_MESSAGE, id, contributorName, contributorPlugins.distinctValues())); | ||
116 | } | ||
117 | |||
118 | contributedQueryGroups.put(id, provider); | ||
119 | contributingPluginOfGroupMap.addPair(id, contributorName); | ||
120 | } catch (Exception e) { | ||
121 | // If there are serious compilation errors in the file loaded by the query registry, an error is thrown | ||
122 | if (id == null) { | ||
123 | id = "undefined in plugin.xml"; | ||
124 | } | ||
125 | ViatraQueryLoggingUtil.getLogger(ExtensionBasedQuerySpecificationLoader.class).error( | ||
126 | "[ExtensionBasedQuerySpecificationLoader] Exception during query specification registry initialization when preparing group: " | ||
127 | + id + "! " + e.getMessage(), e); | ||
128 | } | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * @author Abel Hegedus | ||
133 | * | ||
134 | */ | ||
135 | private final class ExtensionBasedSourceConnector implements IRegistrySourceConnector { | ||
136 | |||
137 | private Set<IConnectorListener> listeners; | ||
138 | |||
139 | public ExtensionBasedSourceConnector() { | ||
140 | this.listeners = new HashSet<>(); | ||
141 | } | ||
142 | |||
143 | @Override | ||
144 | public String getIdentifier() { | ||
145 | return ExtensionBasedQuerySpecificationLoader.CONNECTOR_ID; | ||
146 | } | ||
147 | |||
148 | @Override | ||
149 | public void addListener(IConnectorListener listener) { | ||
150 | Objects.requireNonNull(listener, "Listener must not be null!"); | ||
151 | boolean added = listeners.add(listener); | ||
152 | if(added) { | ||
153 | for (QueryGroupProvider queryGroupProvider : getRegisteredQueryGroups().values()) { | ||
154 | for (IQuerySpecificationProvider specificationProvider : queryGroupProvider.getQuerySpecificationProviders()) { | ||
155 | listener.querySpecificationAdded(this, specificationProvider); | ||
156 | } | ||
157 | } | ||
158 | } | ||
159 | } | ||
160 | |||
161 | @Override | ||
162 | public void removeListener(IConnectorListener listener) { | ||
163 | Objects.requireNonNull(listener, "Listener must not be null!"); | ||
164 | listeners.remove(listener); | ||
165 | } | ||
166 | |||
167 | @Override | ||
168 | public boolean includeSpecificationsInDefaultViews() { | ||
169 | return true; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | /** | ||
174 | * Provider implementation that uses the group extension to load the query group on-demand. | ||
175 | * It also provides the set of query FQNs that are part of the group without class loading. | ||
176 | * Once loaded, the query group is cached for future use. | ||
177 | * | ||
178 | * @author Abel Hegedus | ||
179 | */ | ||
180 | private static final class QueryGroupProvider implements IQueryGroupProvider { | ||
181 | |||
182 | private static final String DUPLICATE_FQN_MESSAGE = "Duplicate FQN %s in query group extension point (plug-in %s)"; | ||
183 | private final IConfigurationElement element; | ||
184 | private IQueryGroup queryGroup; | ||
185 | private Set<String> querySpecificationFQNs; | ||
186 | private Map<String, IQuerySpecificationProvider> querySpecificationMap; | ||
187 | |||
188 | public QueryGroupProvider(IConfigurationElement element) { | ||
189 | this.element = element; | ||
190 | this.queryGroup = null; | ||
191 | this.querySpecificationFQNs = null; | ||
192 | this.querySpecificationMap = null; | ||
193 | } | ||
194 | |||
195 | @Override | ||
196 | public IQueryGroup get() { | ||
197 | try{ | ||
198 | if(queryGroup == null) { | ||
199 | queryGroup = (IQueryGroup) element.createExecutableExtension("group"); | ||
200 | } | ||
201 | return queryGroup; | ||
202 | } catch (CoreException e) { | ||
203 | throw new IllegalStateException(e.getMessage(), e); | ||
204 | } | ||
205 | } | ||
206 | |||
207 | @Override | ||
208 | public Set<String> getQuerySpecificationFQNs() { | ||
209 | if(querySpecificationFQNs == null) { | ||
210 | Set<String> fqns = new HashSet<>(); | ||
211 | for (IConfigurationElement e : element.getChildren("query-specification")) { | ||
212 | if (e.isValid()) { | ||
213 | String fqn = e.getAttribute("fqn"); | ||
214 | boolean added = fqns.add(fqn); | ||
215 | if(!added) { | ||
216 | String contributorName = e.getContributor().getName(); | ||
217 | throw new IllegalArgumentException(String.format(DUPLICATE_FQN_MESSAGE,fqn, contributorName)); | ||
218 | } | ||
219 | } | ||
220 | } | ||
221 | if(fqns.isEmpty()) { | ||
222 | // we must load the class and get the specifications | ||
223 | IQueryGroup loadedQueryGroup = get(); | ||
224 | for (IQuerySpecification<?> specification : loadedQueryGroup.getSpecifications()) { | ||
225 | String fullyQualifiedName = specification.getFullyQualifiedName(); | ||
226 | boolean added = fqns.add(fullyQualifiedName); | ||
227 | if(!added) { | ||
228 | String contributorName = element.getContributor().getName(); | ||
229 | throw new IllegalArgumentException(String.format(DUPLICATE_FQN_MESSAGE, fullyQualifiedName, contributorName)); | ||
230 | } | ||
231 | } | ||
232 | } | ||
233 | // we will never change the set after initialization | ||
234 | querySpecificationFQNs = new HashSet<>(fqns); | ||
235 | } | ||
236 | return querySpecificationFQNs; | ||
237 | } | ||
238 | |||
239 | @Override | ||
240 | public Set<IQuerySpecificationProvider> getQuerySpecificationProviders() { | ||
241 | return new HashSet<>(getQuerySpecificationMap().values()); | ||
242 | } | ||
243 | |||
244 | private Map<String, IQuerySpecificationProvider> getQuerySpecificationMap() { | ||
245 | if(querySpecificationMap == null){ | ||
246 | querySpecificationMap = new HashMap<>(); | ||
247 | Set<String> fqns = getQuerySpecificationFQNs(); | ||
248 | for (String fqn : fqns) { | ||
249 | querySpecificationMap.put(fqn, new GroupBasedQuerySpecificationProvider(fqn, this)); | ||
250 | } | ||
251 | } | ||
252 | return querySpecificationMap; | ||
253 | } | ||
254 | |||
255 | } | ||
256 | |||
257 | /** | ||
258 | * Provider implementation that uses the query group extension to load a query specification by its FQN. Note that | ||
259 | * the FQN of the provided query specification is set with the constructor and can be requested without loading the | ||
260 | * class. Once loaded, the query specification is cached for future use. | ||
261 | * | ||
262 | * @author Abel Hegedus | ||
263 | * | ||
264 | */ | ||
265 | private static final class GroupBasedQuerySpecificationProvider implements IQuerySpecificationProvider { | ||
266 | |||
267 | private String queryFQN; | ||
268 | private QueryGroupProvider queryGroupProvider; | ||
269 | private IQuerySpecification<?> specification; | ||
270 | |||
271 | public GroupBasedQuerySpecificationProvider(String queryFQN, QueryGroupProvider queryGroupProvider) { | ||
272 | this.queryFQN = queryFQN; | ||
273 | this.queryGroupProvider = queryGroupProvider; | ||
274 | this.specification = null; | ||
275 | } | ||
276 | |||
277 | @Override | ||
278 | public IQuerySpecification<?> get() { | ||
279 | if(specification == null) { | ||
280 | if(queryGroupProvider.getQuerySpecificationFQNs().contains(queryFQN)) { | ||
281 | for (IQuerySpecification<?> spec : queryGroupProvider.get().getSpecifications()) { | ||
282 | if(spec.getFullyQualifiedName().equals(queryFQN)){ | ||
283 | this.specification = spec; | ||
284 | } | ||
285 | } | ||
286 | } else { | ||
287 | throw new IllegalStateException(String.format("Could not find query specifition %s in group (plug-in %s)", queryFQN, queryGroupProvider.element.getContributor().getName())); | ||
288 | } | ||
289 | } | ||
290 | return specification; | ||
291 | } | ||
292 | |||
293 | @Override | ||
294 | public String getFullyQualifiedName() { | ||
295 | return queryFQN; | ||
296 | } | ||
297 | |||
298 | @Override | ||
299 | public String getSourceProjectName() { | ||
300 | return queryGroupProvider.element.getContributor().getName(); | ||
301 | } | ||
302 | } | ||
303 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IConnectorListener.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IConnectorListener.java deleted file mode 100644 index 318415cc..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IConnectorListener.java +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.registry; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.extensibility.IQuerySpecificationProvider; | ||
12 | |||
13 | /** | ||
14 | * Connector listeners are used to receive notifications on addition and removal of query specifications. | ||
15 | * The connector itself is also passed in the methods to allow the usage of the same listener on multiple connectors. | ||
16 | * | ||
17 | * @author Abel Hegedus | ||
18 | * @since 1.3 | ||
19 | * | ||
20 | */ | ||
21 | public interface IConnectorListener { | ||
22 | |||
23 | /** | ||
24 | * Called when a new query specification is added to the given connector. | ||
25 | * The provider interface is used to avoid class loading as long as possible. | ||
26 | * | ||
27 | * @param connector that has a new specification | ||
28 | * @param specificationProvider that wraps the new specification | ||
29 | */ | ||
30 | void querySpecificationAdded(IRegistrySourceConnector connector, IQuerySpecificationProvider specificationProvider); | ||
31 | |||
32 | /** | ||
33 | * Called when a query specification is removed from the given connector. | ||
34 | * The provider interface is used to avoid class loading as long as possible. | ||
35 | * | ||
36 | * @param connector that has a removed specification | ||
37 | * @param specificationProvider that wraps the removed specification | ||
38 | */ | ||
39 | void querySpecificationRemoved(IRegistrySourceConnector connector, IQuerySpecificationProvider specificationProvider); | ||
40 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IDefaultRegistryView.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IDefaultRegistryView.java deleted file mode 100644 index 9e3e0394..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IDefaultRegistryView.java +++ /dev/null | |||
@@ -1,37 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.registry; | ||
10 | |||
11 | import java.util.NoSuchElementException; | ||
12 | |||
13 | import tools.refinery.viatra.runtime.api.IQueryGroup; | ||
14 | |||
15 | /** | ||
16 | * The default registry view ensures that the fully qualified name of entries are unique and provides an additional | ||
17 | * method for retrieving the query group of entries for easy initialization. | ||
18 | * | ||
19 | * @author Abel Hegedus | ||
20 | * @since 1.3 | ||
21 | * | ||
22 | */ | ||
23 | public interface IDefaultRegistryView extends IRegistryView { | ||
24 | |||
25 | /** | ||
26 | * @return a query group containing all query specifications | ||
27 | */ | ||
28 | IQueryGroup getQueryGroup(); | ||
29 | |||
30 | /** | ||
31 | * @param fullyQualifiedName | ||
32 | * of the entry that is requested | ||
33 | * @return the entry with the given FQN | ||
34 | * @throws NoSuchElementException if there is no such entry in the default view | ||
35 | */ | ||
36 | IQuerySpecificationRegistryEntry getEntry(String fullyQualifiedName); | ||
37 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IQuerySpecificationRegistry.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IQuerySpecificationRegistry.java deleted file mode 100644 index 97a17f0e..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IQuerySpecificationRegistry.java +++ /dev/null | |||
@@ -1,74 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.registry; | ||
10 | |||
11 | /** | ||
12 | * The query specification registry is used to manage query specifications provided by multiple connectors which can | ||
13 | * dynamically add and remove specifications. Users can read the contents of the registry through views that are also | ||
14 | * dynamically updated when the registry is changed by the connectors. | ||
15 | * | ||
16 | * @author Abel Hegedus | ||
17 | * @since 1.3 | ||
18 | * | ||
19 | */ | ||
20 | public interface IQuerySpecificationRegistry { | ||
21 | |||
22 | /** | ||
23 | * Cannot register connectors with the same identifier twice. No change occurs if the identifier is already used. | ||
24 | * | ||
25 | * @param connector | ||
26 | * cannot be null | ||
27 | * @return false if a connector with the given identifier has already been added, true otherwise | ||
28 | */ | ||
29 | boolean addSource(IRegistrySourceConnector connector); | ||
30 | |||
31 | /** | ||
32 | * Removes the connector if it was registered. No change occurs if the identifier of the connector was not used | ||
33 | * before. | ||
34 | * | ||
35 | * @param connector | ||
36 | * cannot be null | ||
37 | * @return false if a registered connector with the given identifier was not found, true if it was successfully | ||
38 | * removed | ||
39 | */ | ||
40 | boolean removeSource(IRegistrySourceConnector connector); | ||
41 | |||
42 | /** | ||
43 | * Returns a default view instance that contains query specification entries that indicate their inclusion in | ||
44 | * default views. If there are entries with the same FQN, only the last added will be included in the view to avoid | ||
45 | * duplicate FQNs. | ||
46 | * | ||
47 | * @return the default view instance | ||
48 | */ | ||
49 | IDefaultRegistryView getDefaultView(); | ||
50 | |||
51 | /** | ||
52 | * Creates a view which contains query specification entries that indicate their inclusion in default views. This | ||
53 | * view will also be incrementally updated on registry changes and accepts listeners to notify on changes. | ||
54 | * | ||
55 | * @return a new view instance | ||
56 | */ | ||
57 | IRegistryView createView(); | ||
58 | |||
59 | /** | ||
60 | * Creates a view which contains registered query specifications that are considered relevant by the passed filter. | ||
61 | * This view will also be incrementally updated on registry changes and accepts listeners to notify on changes. | ||
62 | * | ||
63 | * @return a new filtered view instance | ||
64 | */ | ||
65 | IRegistryView createView(IRegistryViewFilter filter); | ||
66 | |||
67 | /** | ||
68 | * Creates a view which is instantiated by the factory and is connected to the registry. This | ||
69 | * view will also be incrementally updated on registry changes and accepts listeners to notify on changes. | ||
70 | * | ||
71 | * @return a new view instance | ||
72 | */ | ||
73 | IRegistryView createView(IRegistryViewFactory factory); | ||
74 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IQuerySpecificationRegistryChangeListener.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IQuerySpecificationRegistryChangeListener.java deleted file mode 100644 index defdd2ab..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IQuerySpecificationRegistryChangeListener.java +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.registry; | ||
10 | |||
11 | /** | ||
12 | * Listener interface for providing update notifications of views to users. It is used for propagating changes from the | ||
13 | * query specification registry to the views and from the views to users. | ||
14 | * | ||
15 | * @author Abel Hegedus | ||
16 | * @since 1.3 | ||
17 | * | ||
18 | */ | ||
19 | public interface IQuerySpecificationRegistryChangeListener { | ||
20 | |||
21 | /** | ||
22 | * Called when a new entry is added to the registry. | ||
23 | * | ||
24 | * @param entry that is added | ||
25 | */ | ||
26 | void entryAdded(IQuerySpecificationRegistryEntry entry); | ||
27 | |||
28 | /** | ||
29 | * Called when an existing entry is removed from the registry. | ||
30 | * | ||
31 | * @param entry that is removed | ||
32 | */ | ||
33 | void entryRemoved(IQuerySpecificationRegistryEntry entry); | ||
34 | |||
35 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IQuerySpecificationRegistryEntry.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IQuerySpecificationRegistryEntry.java deleted file mode 100644 index 5009d74b..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IQuerySpecificationRegistryEntry.java +++ /dev/null | |||
@@ -1,48 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.registry; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.extensibility.IQuerySpecificationProvider; | ||
12 | |||
13 | /** | ||
14 | * The query specification registry entry interface can return the identifier of the source that added it to the | ||
15 | * registry. It is provider based and can delay class loading of the wrapped {@link IQuerySpecification} until needed. | ||
16 | * | ||
17 | * @author Abel Hegedus | ||
18 | * @since 1.3 | ||
19 | * | ||
20 | */ | ||
21 | public interface IQuerySpecificationRegistryEntry extends IQuerySpecificationProvider { | ||
22 | |||
23 | /** | ||
24 | * @return the identifier of the registry source that contributed the specification | ||
25 | */ | ||
26 | String getSourceIdentifier(); | ||
27 | |||
28 | /** | ||
29 | * Returns whether the query specification was provided by an identifiable project. | ||
30 | */ | ||
31 | boolean isFromProject(); | ||
32 | |||
33 | /** | ||
34 | * Collects the name of the project that is registered this specification to the registry. | ||
35 | * If {@link #getSourceIdentifier()} is false, it returns null. | ||
36 | */ | ||
37 | String getSourceProjectName(); | ||
38 | |||
39 | /** | ||
40 | * @return true if the entry should be included in default views (created without any filters) | ||
41 | */ | ||
42 | boolean includeInDefaultViews(); | ||
43 | |||
44 | /** | ||
45 | * @return the wrapped {@link IQuerySpecificationProvider} or itself | ||
46 | */ | ||
47 | IQuerySpecificationProvider getProvider(); | ||
48 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IRegistrySourceConnector.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IRegistrySourceConnector.java deleted file mode 100644 index 94c68d1b..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IRegistrySourceConnector.java +++ /dev/null | |||
@@ -1,50 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.registry; | ||
10 | |||
11 | /** | ||
12 | * A registry source connector can provide query specifications to listeners (e.g. {@link IQuerySpecificationRegistry}). | ||
13 | * The connector interface does not support direct access to query specifications, instead it sends existing specifications | ||
14 | * to listeners on addition and sends notifications to listeners when a change occurs in the set of specifications. | ||
15 | * | ||
16 | * @author Abel Hegedus | ||
17 | * @since 1.3 | ||
18 | * | ||
19 | */ | ||
20 | public interface IRegistrySourceConnector { | ||
21 | |||
22 | /** | ||
23 | * The connector must return the same identifier every time it is invoked! | ||
24 | * | ||
25 | * @return unique identifier of the connector | ||
26 | */ | ||
27 | String getIdentifier(); | ||
28 | |||
29 | /** | ||
30 | * | ||
31 | * @return true if the specifications of the connector should be included in default views | ||
32 | */ | ||
33 | boolean includeSpecificationsInDefaultViews(); | ||
34 | |||
35 | /** | ||
36 | * Add a listener to get updates on changes in the query specifications available from the connector. When the | ||
37 | * listener is added, the connector is expected to call the listener with each existing query specification. | ||
38 | * | ||
39 | * @param listener that should be added | ||
40 | */ | ||
41 | void addListener(IConnectorListener listener); | ||
42 | |||
43 | /** | ||
44 | * Removes an already registered listener and stops sending updates. The connector is not required to send any | ||
45 | * updates before returning from this method, but should not send any events after this method returns. | ||
46 | * | ||
47 | * @param listener that should be removed | ||
48 | */ | ||
49 | void removeListener(IConnectorListener listener); | ||
50 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IRegistryView.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IRegistryView.java deleted file mode 100644 index acf49b76..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IRegistryView.java +++ /dev/null | |||
@@ -1,72 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.registry; | ||
10 | |||
11 | import java.util.Set; | ||
12 | |||
13 | /** | ||
14 | * The registry view is the primary interface for users to interact with the query specifications in an | ||
15 | * {@link IQuerySpecificationRegistry}. Views are created using the createView methods of registry and their content is | ||
16 | * also dynamically updated by the registry. | ||
17 | * | ||
18 | * The view contains a set of {@link IQuerySpecificationRegistryEntry} objects that can be used to access the query | ||
19 | * specifications themselves through the get() method. | ||
20 | * | ||
21 | * Users can check the contents of the view and add listeners to get notifications on view changes (added or removed | ||
22 | * entries). | ||
23 | * | ||
24 | * @author Abel Hegedus | ||
25 | * @since 1.3 | ||
26 | * | ||
27 | */ | ||
28 | public interface IRegistryView extends IQuerySpecificationRegistryChangeListener { | ||
29 | |||
30 | /** | ||
31 | * @return an immutable copy of all entries found in the view | ||
32 | */ | ||
33 | Iterable<IQuerySpecificationRegistryEntry> getEntries(); | ||
34 | |||
35 | /** | ||
36 | * @return the set of FQNs for the query specifications in the view | ||
37 | */ | ||
38 | Set<String> getQuerySpecificationFQNs(); | ||
39 | |||
40 | /** | ||
41 | * @param fullyQualifiedName | ||
42 | * that is looked up in the view | ||
43 | * @return true if the view contains an entry with given FQN, false otherwise | ||
44 | */ | ||
45 | boolean hasQuerySpecificationFQN(String fullyQualifiedName); | ||
46 | |||
47 | /** | ||
48 | * @param fullyQualifiedName | ||
49 | * of the entries that are requested | ||
50 | * @return the possible empty set of entries with the given FQN | ||
51 | */ | ||
52 | Set<IQuerySpecificationRegistryEntry> getEntries(String fullyQualifiedName); | ||
53 | |||
54 | /** | ||
55 | * Adds a listener to the view that will be notified when an entry is added to or removed from the view. | ||
56 | * | ||
57 | * @param listener that is added | ||
58 | */ | ||
59 | void addViewListener(IQuerySpecificationRegistryChangeListener listener); | ||
60 | |||
61 | /** | ||
62 | * Removes a listener that was previously added to the view. | ||
63 | * | ||
64 | * @param listener that is removed | ||
65 | */ | ||
66 | void removeViewListener(IQuerySpecificationRegistryChangeListener listener); | ||
67 | |||
68 | /** | ||
69 | * @return the registry underlying the view | ||
70 | */ | ||
71 | IQuerySpecificationRegistry getRegistry(); | ||
72 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IRegistryViewFactory.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IRegistryViewFactory.java deleted file mode 100644 index 990902d3..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IRegistryViewFactory.java +++ /dev/null | |||
@@ -1,34 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.registry; | ||
10 | |||
11 | /** | ||
12 | * This interface can be used to ask the registry to construct specific view instances. The factory is responsible for | ||
13 | * instantiating the view, but the registry is responsible for establishing the connection with the internal data store | ||
14 | * and to fill up the view with entries. Instances of the factory are intended to be passed to | ||
15 | * {@link IQuerySpecificationRegistry#createView(IRegistryViewFactory)} and only the view instance returned by that | ||
16 | * method can be considered initialized. | ||
17 | * | ||
18 | * @author Abel Hegedus | ||
19 | * @since 1.3 | ||
20 | * | ||
21 | */ | ||
22 | public interface IRegistryViewFactory { | ||
23 | |||
24 | /** | ||
25 | * Instantiate a new view object and store the reference to the registry. | ||
26 | * This method should only be called by an {@link IQuerySpecificationRegistry}. | ||
27 | * | ||
28 | * @param registry that will be connected to the view | ||
29 | * @return the new instance of the view | ||
30 | * @noreference This method is not intended to be referenced by clients. | ||
31 | */ | ||
32 | IRegistryView createView(IQuerySpecificationRegistry registry); | ||
33 | |||
34 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IRegistryViewFilter.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IRegistryViewFilter.java deleted file mode 100644 index fa13327f..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/IRegistryViewFilter.java +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.registry; | ||
10 | |||
11 | /** | ||
12 | * The registry view filter can control which entries are added and removed from an {@link IRegistryView}. | ||
13 | * | ||
14 | * @author Abel Hegedus | ||
15 | * @since 1.3 | ||
16 | * | ||
17 | */ | ||
18 | public interface IRegistryViewFilter { | ||
19 | |||
20 | /** | ||
21 | * This method controls whether a registry entry is added to the view or not. The filtering is called before | ||
22 | * checking the uniqueness of fully qualified names, and relevant entries can overwrite existing entries with the | ||
23 | * same FQN. | ||
24 | * | ||
25 | * Note that filters should usually return the same value for the same entry on multiple invocations. | ||
26 | * | ||
27 | * @param entry | ||
28 | * that is checked | ||
29 | * @return true, if the entry is relevant for the view, false otherwise | ||
30 | */ | ||
31 | boolean isEntryRelevant(IQuerySpecificationRegistryEntry entry); | ||
32 | |||
33 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/QuerySpecificationRegistry.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/QuerySpecificationRegistry.java deleted file mode 100644 index 139dde1c..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/QuerySpecificationRegistry.java +++ /dev/null | |||
@@ -1,112 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.registry; | ||
10 | |||
11 | import java.util.HashSet; | ||
12 | import java.util.Iterator; | ||
13 | import java.util.Set; | ||
14 | |||
15 | import tools.refinery.viatra.runtime.registry.impl.QuerySpecificationRegistryImpl; | ||
16 | |||
17 | /** | ||
18 | * Registry for query specifications that can be accessed using fully qualified names through views. | ||
19 | * Additional query specifications can be added using {@link IRegistrySourceConnector}s. | ||
20 | * | ||
21 | * <p> | ||
22 | * When running as an OSGi plug-in, the generated query specifications registered through extensions are automatically loaded | ||
23 | * into the registry by the {@link ExtensionBasedQuerySpecificationLoader} class. | ||
24 | * | ||
25 | * @author Abel Hegedus | ||
26 | * @since 1.3 | ||
27 | * | ||
28 | */ | ||
29 | public class QuerySpecificationRegistry implements IQuerySpecificationRegistry { | ||
30 | |||
31 | private static final QuerySpecificationRegistry INSTANCE = new QuerySpecificationRegistry(); | ||
32 | |||
33 | /** | ||
34 | * @return the singleton query specification registry instance | ||
35 | */ | ||
36 | public static IQuerySpecificationRegistry getInstance() { | ||
37 | return INSTANCE; | ||
38 | } | ||
39 | |||
40 | private final QuerySpecificationRegistryImpl internalRegistry; | ||
41 | /** | ||
42 | * Connectors that should not be immediately loaded into the registry. | ||
43 | */ | ||
44 | private final Set<IRegistrySourceConnector> delayedConnectors; | ||
45 | |||
46 | /** | ||
47 | * Hidden constructor for singleton instance | ||
48 | */ | ||
49 | protected QuerySpecificationRegistry() { | ||
50 | this.internalRegistry = new QuerySpecificationRegistryImpl(); | ||
51 | this.delayedConnectors = new HashSet<>(); | ||
52 | |||
53 | } | ||
54 | |||
55 | /** | ||
56 | * @return the internal registry after adding delayed source connectors | ||
57 | */ | ||
58 | protected IQuerySpecificationRegistry getInternalRegistry() { | ||
59 | if(!delayedConnectors.isEmpty()) { | ||
60 | final Iterator<IRegistrySourceConnector> it = delayedConnectors.iterator(); | ||
61 | while (it.hasNext()) { | ||
62 | final IRegistrySourceConnector connector = it.next(); | ||
63 | internalRegistry.addSource(connector); | ||
64 | it.remove(); | ||
65 | } | ||
66 | } | ||
67 | return internalRegistry; | ||
68 | } | ||
69 | |||
70 | /** | ||
71 | * When the registry adds itself as a listener to connectors, it must send all specification providers | ||
72 | * to the registry. However, when {@link ExtensionBasedQuerySpecificationLoader} is triggered during the | ||
73 | * activation of the plugin, the individual query specification classes cannot be loaded yet. To avoid this, | ||
74 | * the connector of the loader is delayed until needed. | ||
75 | * | ||
76 | * @param connector that should be delayed before adding to the registry | ||
77 | */ | ||
78 | protected void addDelayedSourceConnector(IRegistrySourceConnector connector) { | ||
79 | delayedConnectors.add(connector); | ||
80 | } | ||
81 | |||
82 | @Override | ||
83 | public boolean addSource(IRegistrySourceConnector connector) { | ||
84 | return getInternalRegistry().addSource(connector); | ||
85 | } | ||
86 | |||
87 | @Override | ||
88 | public boolean removeSource(IRegistrySourceConnector connector) { | ||
89 | return getInternalRegistry().removeSource(connector); | ||
90 | } | ||
91 | |||
92 | @Override | ||
93 | public IDefaultRegistryView getDefaultView() { | ||
94 | return getInternalRegistry().getDefaultView(); | ||
95 | } | ||
96 | |||
97 | @Override | ||
98 | public IRegistryView createView() { | ||
99 | return getInternalRegistry().createView(); | ||
100 | } | ||
101 | |||
102 | @Override | ||
103 | public IRegistryView createView(IRegistryViewFilter filter) { | ||
104 | return getInternalRegistry().createView(filter); | ||
105 | } | ||
106 | |||
107 | @Override | ||
108 | public IRegistryView createView(IRegistryViewFactory factory) { | ||
109 | return getInternalRegistry().createView(factory); | ||
110 | } | ||
111 | |||
112 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/connector/AbstractRegistrySourceConnector.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/connector/AbstractRegistrySourceConnector.java deleted file mode 100644 index 0e2ef273..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/connector/AbstractRegistrySourceConnector.java +++ /dev/null | |||
@@ -1,81 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.registry.connector; | ||
10 | |||
11 | import java.util.HashSet; | ||
12 | import java.util.Objects; | ||
13 | import java.util.Set; | ||
14 | |||
15 | import tools.refinery.viatra.runtime.registry.IConnectorListener; | ||
16 | import tools.refinery.viatra.runtime.registry.IRegistrySourceConnector; | ||
17 | |||
18 | /** | ||
19 | * Abstract registry source connector implementation that stores the identifier and listener set. | ||
20 | * | ||
21 | * | ||
22 | * @author Abel Hegedus | ||
23 | * @since 1.3 | ||
24 | * | ||
25 | */ | ||
26 | public abstract class AbstractRegistrySourceConnector implements IRegistrySourceConnector { | ||
27 | |||
28 | protected Set<IConnectorListener> listeners; | ||
29 | private String identifier; | ||
30 | private boolean includeInDefaultViews; | ||
31 | |||
32 | /** | ||
33 | * Creates an instance of the connector with the given identifier. The identifier should be unique if you want to | ||
34 | * add it to a registry as a source. | ||
35 | * | ||
36 | * @param identifier | ||
37 | * of the newly created connector | ||
38 | * @param includeInDefaultViews | ||
39 | * true if the specifications in the connector should be included in default views | ||
40 | */ | ||
41 | public AbstractRegistrySourceConnector(String identifier, boolean includeInDefaultViews) { | ||
42 | super(); | ||
43 | Objects.requireNonNull(identifier, "Identifier must not be null!"); | ||
44 | this.identifier = identifier; | ||
45 | this.includeInDefaultViews = includeInDefaultViews; | ||
46 | this.listeners = new HashSet<>(); | ||
47 | } | ||
48 | |||
49 | @Override | ||
50 | public String getIdentifier() { | ||
51 | return identifier; | ||
52 | } | ||
53 | |||
54 | @Override | ||
55 | public boolean includeSpecificationsInDefaultViews() { | ||
56 | return includeInDefaultViews; | ||
57 | } | ||
58 | |||
59 | @Override | ||
60 | public void addListener(IConnectorListener listener) { | ||
61 | Objects.requireNonNull(listener, "Listener must not be null!"); | ||
62 | boolean added = listeners.add(listener); | ||
63 | if (added) { | ||
64 | sendQuerySpecificationsToListener(listener); | ||
65 | } | ||
66 | } | ||
67 | |||
68 | @Override | ||
69 | public void removeListener(IConnectorListener listener) { | ||
70 | Objects.requireNonNull(listener, "Listener must not be null!"); | ||
71 | listeners.remove(listener); | ||
72 | } | ||
73 | |||
74 | /** | ||
75 | * Subclasses should send add notifications for each specification in the connector to the given listener. | ||
76 | * | ||
77 | * @param listener that should receive the notifications | ||
78 | */ | ||
79 | protected abstract void sendQuerySpecificationsToListener(IConnectorListener listener); | ||
80 | |||
81 | } \ No newline at end of file | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/connector/QueryGroupProviderSourceConnector.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/connector/QueryGroupProviderSourceConnector.java deleted file mode 100644 index e6f0adf0..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/connector/QueryGroupProviderSourceConnector.java +++ /dev/null | |||
@@ -1,80 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.registry.connector; | ||
10 | |||
11 | import java.util.Objects; | ||
12 | |||
13 | import tools.refinery.viatra.runtime.extensibility.IQueryGroupProvider; | ||
14 | import tools.refinery.viatra.runtime.extensibility.IQuerySpecificationProvider; | ||
15 | import tools.refinery.viatra.runtime.registry.IConnectorListener; | ||
16 | |||
17 | /** | ||
18 | * Source connector implementation that uses a {@link IQueryGroupProvider} to provide a query specifications into the | ||
19 | * registry. The query group can be later updated which triggers the removal of all specifications of the old group and | ||
20 | * the addition of all specifications from the new group. | ||
21 | * | ||
22 | * @author Abel Hegedus | ||
23 | * @since 1.3 | ||
24 | * | ||
25 | */ | ||
26 | public class QueryGroupProviderSourceConnector extends AbstractRegistrySourceConnector { | ||
27 | |||
28 | IQueryGroupProvider queryGroupProvider; | ||
29 | |||
30 | /** | ||
31 | * Creates an instance of the connector with the given identifier and the query group provider. The identifier | ||
32 | * should be unique if you want to add it to a registry as a source. | ||
33 | * | ||
34 | * @param identifier | ||
35 | * of the newly created connector | ||
36 | * @param provider | ||
37 | * that contains the query specifications handled by the connector | ||
38 | * @param includeInDefaultViews | ||
39 | * true if the specifications in the connector should be included in default views | ||
40 | */ | ||
41 | public QueryGroupProviderSourceConnector(String identifier, IQueryGroupProvider provider, boolean includeInDefaultViews) { | ||
42 | super(identifier, includeInDefaultViews); | ||
43 | this.queryGroupProvider = provider; | ||
44 | } | ||
45 | |||
46 | /** | ||
47 | * Update the query group of the connector, which triggers the removal of all specifications on the old group and | ||
48 | * addition of all specifications in the given group. | ||
49 | * | ||
50 | * @param queryGroupProvider | ||
51 | * the queryGroupProvider to set | ||
52 | * @param includeInDefaultViews | ||
53 | * true if the specifications in the connector should be included in default views | ||
54 | */ | ||
55 | public void setQueryGroupProvider(IQueryGroupProvider queryGroupProvider) { | ||
56 | Objects.requireNonNull(queryGroupProvider, "Query group provider must not be null!"); | ||
57 | IQueryGroupProvider oldProvider = this.queryGroupProvider; | ||
58 | |||
59 | for (IQuerySpecificationProvider specificationProvider : oldProvider.getQuerySpecificationProviders()) { | ||
60 | for (IConnectorListener iConnectorListener : listeners) { | ||
61 | iConnectorListener.querySpecificationRemoved(this, specificationProvider); | ||
62 | } | ||
63 | } | ||
64 | for (IQuerySpecificationProvider specificationProvider : queryGroupProvider.getQuerySpecificationProviders()) { | ||
65 | for (IConnectorListener iConnectorListener : listeners) { | ||
66 | iConnectorListener.querySpecificationAdded(this, specificationProvider); | ||
67 | } | ||
68 | } | ||
69 | |||
70 | this.queryGroupProvider = queryGroupProvider; | ||
71 | } | ||
72 | |||
73 | @Override | ||
74 | protected void sendQuerySpecificationsToListener(IConnectorListener listener) { | ||
75 | for (IQuerySpecificationProvider specificationProvider : queryGroupProvider.getQuerySpecificationProviders()) { | ||
76 | listener.querySpecificationAdded(this, specificationProvider); | ||
77 | } | ||
78 | } | ||
79 | |||
80 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/connector/SpecificationMapSourceConnector.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/connector/SpecificationMapSourceConnector.java deleted file mode 100644 index e5778950..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/connector/SpecificationMapSourceConnector.java +++ /dev/null | |||
@@ -1,147 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.registry.connector; | ||
10 | |||
11 | import java.util.Collections; | ||
12 | import java.util.HashMap; | ||
13 | import java.util.HashSet; | ||
14 | import java.util.Map; | ||
15 | import java.util.NoSuchElementException; | ||
16 | import java.util.Objects; | ||
17 | import java.util.Set; | ||
18 | |||
19 | import tools.refinery.viatra.runtime.extensibility.IQuerySpecificationProvider; | ||
20 | import tools.refinery.viatra.runtime.extensibility.SingletonQuerySpecificationProvider; | ||
21 | import tools.refinery.viatra.runtime.registry.IConnectorListener; | ||
22 | |||
23 | /** | ||
24 | * A simple connector implementation that allows users to simply add and remove specifications. These changes are | ||
25 | * propagated to listeners (e.g. the registry). Note that duplicate FQNs are not allowed in a given connector. | ||
26 | * | ||
27 | * @author Abel Hegedus | ||
28 | * @since 1.3 | ||
29 | * | ||
30 | */ | ||
31 | public class SpecificationMapSourceConnector extends AbstractRegistrySourceConnector { | ||
32 | |||
33 | private static final String DUPLICATE_MESSAGE = "Duplicate FQN %s cannot be added to connector"; | ||
34 | private Map<String, IQuerySpecificationProvider> specificationProviderMap; | ||
35 | |||
36 | /** | ||
37 | * Creates an instance of the connector with the given identifier. The identifier should be unique if you want to | ||
38 | * add it to a registry as a source. | ||
39 | * | ||
40 | * @param identifier | ||
41 | * of the newly created connector | ||
42 | * @param includeInDefaultViews | ||
43 | * true if the specifications in the connector should be included in default views | ||
44 | */ | ||
45 | public SpecificationMapSourceConnector(String identifier, boolean includeInDefaultViews) { | ||
46 | super(identifier, includeInDefaultViews); | ||
47 | this.specificationProviderMap = new HashMap<>(); | ||
48 | } | ||
49 | |||
50 | /** | ||
51 | * Creates an instance of the connector with the given identifier and fills it up with the given specification | ||
52 | * providers. The identifier should be unique if you want to add it to a registry as a source. | ||
53 | * | ||
54 | * @param identifier | ||
55 | * of the newly created connector | ||
56 | * @param specificationProviders | ||
57 | * the initial set of specifications in the connector | ||
58 | * @param includeInDefaultViews | ||
59 | * true if the specifications in the connector should be included in default views | ||
60 | */ | ||
61 | public SpecificationMapSourceConnector(String identifier, Set<IQuerySpecificationProvider> specificationProviders, boolean includeInDefaultViews) { | ||
62 | this(identifier, includeInDefaultViews); | ||
63 | for (IQuerySpecificationProvider provider : specificationProviders) { | ||
64 | addQuerySpecificationProvider(provider); | ||
65 | } | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * Creates an instance of the connector with the given identifier and fills it up with the specification providers | ||
70 | * from the given {@link SpecificationMapSourceConnector}. The identifier should be unique if you want to add it to | ||
71 | * a registry as a source. | ||
72 | * | ||
73 | * @param identifier | ||
74 | * of the newly created connector | ||
75 | * @param connector | ||
76 | * that contains the specifications to copy into the new instance | ||
77 | * @param includeInDefaultViews | ||
78 | * true if the specifications in the connector should be included in default views | ||
79 | */ | ||
80 | public SpecificationMapSourceConnector(String identifier, SpecificationMapSourceConnector connector, boolean includeInDefaultViews) { | ||
81 | this(identifier, includeInDefaultViews); | ||
82 | this.specificationProviderMap.putAll(connector.specificationProviderMap); | ||
83 | } | ||
84 | |||
85 | /** | ||
86 | * Adds a query specification to the connector. | ||
87 | * If you have an {@link IQuerySpecification} object, use {@link SingletonQuerySpecificationProvider}. | ||
88 | * | ||
89 | * @param provider to add to the connector | ||
90 | * @throws IllegalArgumentException if the connector already contains a specification with the same FQN | ||
91 | */ | ||
92 | public void addQuerySpecificationProvider(IQuerySpecificationProvider provider) { | ||
93 | Objects.requireNonNull(provider, "Provider must not be null!"); | ||
94 | String fullyQualifiedName = provider.getFullyQualifiedName(); | ||
95 | if (!specificationProviderMap.containsKey(fullyQualifiedName)) { | ||
96 | specificationProviderMap.put(fullyQualifiedName, provider); | ||
97 | for (IConnectorListener listener : listeners) { | ||
98 | listener.querySpecificationAdded(this, provider); | ||
99 | } | ||
100 | } else { | ||
101 | throw new IllegalArgumentException(String.format(DUPLICATE_MESSAGE, fullyQualifiedName)); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | /** | ||
106 | * Remove a specification that has been added with the given FQN. | ||
107 | * | ||
108 | * @param fullyQualifiedName | ||
109 | * @throws NoSuchElementException if the connector does not contain a specification with the given FQN | ||
110 | */ | ||
111 | public void removeQuerySpecificationProvider(String fullyQualifiedName) { | ||
112 | Objects.requireNonNull(fullyQualifiedName, "Fully qualified name must not be null!"); | ||
113 | IQuerySpecificationProvider provider = specificationProviderMap.remove(fullyQualifiedName); | ||
114 | if (provider == null) { | ||
115 | throw new NoSuchElementException( | ||
116 | String.format("Connector does not contain specification with FQN %s", fullyQualifiedName)); | ||
117 | } | ||
118 | for (IConnectorListener listener : listeners) { | ||
119 | listener.querySpecificationRemoved(this, provider); | ||
120 | } | ||
121 | } | ||
122 | |||
123 | /** | ||
124 | * @return the immutable copy of the set of FQNs for the added query specifications | ||
125 | */ | ||
126 | public Set<String> getQuerySpecificationFQNs() { | ||
127 | return Collections.unmodifiableSet(new HashSet<>(specificationProviderMap.keySet())); | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * | ||
132 | * @param fullyQualifiedName that is checked | ||
133 | * @return true if a specification with the given FQN exists in the connector, false otherwise | ||
134 | */ | ||
135 | public boolean hasQuerySpecificationFQN(String fullyQualifiedName) { | ||
136 | Objects.requireNonNull(fullyQualifiedName, "FQN must not be null!"); | ||
137 | return specificationProviderMap.containsKey(fullyQualifiedName); | ||
138 | } | ||
139 | |||
140 | @Override | ||
141 | protected void sendQuerySpecificationsToListener(IConnectorListener listener) { | ||
142 | for (IQuerySpecificationProvider provider : specificationProviderMap.values()) { | ||
143 | listener.querySpecificationAdded(this, provider); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/data/QuerySpecificationStore.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/data/QuerySpecificationStore.java deleted file mode 100644 index 649527b6..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/data/QuerySpecificationStore.java +++ /dev/null | |||
@@ -1,38 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.registry.data; | ||
10 | |||
11 | import java.util.Map; | ||
12 | import java.util.TreeMap; | ||
13 | |||
14 | /** | ||
15 | * Internal data storage object that represents a query specification registry with a set of sources driven by | ||
16 | * connectors. The sources must have unique identifiers. | ||
17 | * | ||
18 | * @author Abel Hegedus | ||
19 | * | ||
20 | */ | ||
21 | public class QuerySpecificationStore { | ||
22 | |||
23 | private Map<String, RegistrySourceImpl> sources; | ||
24 | |||
25 | /** | ||
26 | * Creates a new instance with an empty identifier to source map. | ||
27 | */ | ||
28 | public QuerySpecificationStore() { | ||
29 | this.sources = new TreeMap<>(); | ||
30 | } | ||
31 | |||
32 | /** | ||
33 | * @return the live, modifiable identifier to source map | ||
34 | */ | ||
35 | public Map<String, RegistrySourceImpl> getSources() { | ||
36 | return sources; | ||
37 | } | ||
38 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/data/RegistryEntryImpl.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/data/RegistryEntryImpl.java deleted file mode 100644 index 758885e2..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/data/RegistryEntryImpl.java +++ /dev/null | |||
@@ -1,81 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.registry.data; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.api.IQuerySpecification; | ||
12 | import tools.refinery.viatra.runtime.extensibility.IQuerySpecificationProvider; | ||
13 | import tools.refinery.viatra.runtime.registry.IQuerySpecificationRegistryEntry; | ||
14 | |||
15 | /** | ||
16 | * Internal data storage object that represents a query specification entry. The entry contains an | ||
17 | * {@link IQuerySpecificationProvider} and has a reference to the source that contains it. | ||
18 | * | ||
19 | * @author Abel Hegedus | ||
20 | * | ||
21 | */ | ||
22 | public class RegistryEntryImpl implements IQuerySpecificationRegistryEntry { | ||
23 | |||
24 | private IQuerySpecificationProvider provider; | ||
25 | private RegistrySourceImpl source; | ||
26 | |||
27 | /** | ||
28 | * Creates a new instance with the given source and the given provider. | ||
29 | * | ||
30 | * @param source | ||
31 | * that contains the new entry | ||
32 | * @param provider | ||
33 | * that wraps the specification represented by the entry | ||
34 | */ | ||
35 | public RegistryEntryImpl(RegistrySourceImpl source, IQuerySpecificationProvider provider) { | ||
36 | this.source = source; | ||
37 | this.provider = provider; | ||
38 | } | ||
39 | |||
40 | /** | ||
41 | * @return the source that contains this entry | ||
42 | */ | ||
43 | public RegistrySourceImpl getSource() { | ||
44 | return source; | ||
45 | } | ||
46 | |||
47 | @Override | ||
48 | public String getSourceIdentifier() { | ||
49 | return source.getIdentifier(); | ||
50 | } | ||
51 | |||
52 | @Override | ||
53 | public boolean includeInDefaultViews() { | ||
54 | return getSource().includeEntriesInDefaultViews(); | ||
55 | } | ||
56 | |||
57 | @Override | ||
58 | public String getFullyQualifiedName() { | ||
59 | return provider.getFullyQualifiedName(); | ||
60 | } | ||
61 | |||
62 | @Override | ||
63 | public IQuerySpecification<?> get() { | ||
64 | return provider.get(); | ||
65 | } | ||
66 | |||
67 | @Override | ||
68 | public IQuerySpecificationProvider getProvider() { | ||
69 | return provider; | ||
70 | } | ||
71 | |||
72 | @Override | ||
73 | public boolean isFromProject() { | ||
74 | return provider.getSourceProjectName() != null; | ||
75 | } | ||
76 | |||
77 | @Override | ||
78 | public String getSourceProjectName() { | ||
79 | return provider.getSourceProjectName(); | ||
80 | } | ||
81 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/data/RegistrySourceImpl.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/data/RegistrySourceImpl.java deleted file mode 100644 index 83c3b920..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/data/RegistrySourceImpl.java +++ /dev/null | |||
@@ -1,73 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.registry.data; | ||
10 | |||
11 | import java.util.Map; | ||
12 | import java.util.TreeMap; | ||
13 | |||
14 | /** | ||
15 | * Internal data storage object that represents a query specification source driven by a connector. The source must have | ||
16 | * unique identifier that is copied from the connector. The source uses a FQN to entry map to manage registry entries. | ||
17 | * | ||
18 | * @author Abel Hegedus | ||
19 | * | ||
20 | */ | ||
21 | public class RegistrySourceImpl { | ||
22 | |||
23 | private String identifier; | ||
24 | private boolean includeInDefaultViews; | ||
25 | private QuerySpecificationStore querySpecificationStore; | ||
26 | private Map<String, RegistryEntryImpl> fqnToEntryMap; | ||
27 | |||
28 | /** | ||
29 | * Creates a new source with the given identifier and an empty entry map. | ||
30 | * | ||
31 | * @param identifier | ||
32 | * for the source | ||
33 | * @param querySpecificationStore | ||
34 | * that contains this source | ||
35 | * @param includeInDefaultViews | ||
36 | * true if the entries of the source should be included in default views | ||
37 | */ | ||
38 | public RegistrySourceImpl(String identifier, QuerySpecificationStore querySpecificationStore, boolean includeInDefaultViews) { | ||
39 | this.identifier = identifier; | ||
40 | this.includeInDefaultViews = includeInDefaultViews; | ||
41 | this.querySpecificationStore = querySpecificationStore; | ||
42 | this.fqnToEntryMap = new TreeMap<>(); | ||
43 | } | ||
44 | |||
45 | /** | ||
46 | * @return the identifier of the source | ||
47 | */ | ||
48 | public String getIdentifier() { | ||
49 | return identifier; | ||
50 | } | ||
51 | |||
52 | /** | ||
53 | * @return true if the entries in the source should be included in default views | ||
54 | */ | ||
55 | public boolean includeEntriesInDefaultViews() { | ||
56 | return includeInDefaultViews; | ||
57 | } | ||
58 | |||
59 | /** | ||
60 | * @return the store that contains the source | ||
61 | */ | ||
62 | public QuerySpecificationStore getStore() { | ||
63 | return querySpecificationStore; | ||
64 | } | ||
65 | |||
66 | /** | ||
67 | * @return the live, modifiable FQN to entry map | ||
68 | */ | ||
69 | public Map<String, RegistryEntryImpl> getFqnToEntryMap() { | ||
70 | return fqnToEntryMap; | ||
71 | } | ||
72 | |||
73 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/impl/FilteringRegistryView.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/impl/FilteringRegistryView.java deleted file mode 100644 index 164a30d3..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/impl/FilteringRegistryView.java +++ /dev/null | |||
@@ -1,43 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.registry.impl; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.registry.IQuerySpecificationRegistry; | ||
12 | import tools.refinery.viatra.runtime.registry.IRegistryViewFilter; | ||
13 | import tools.refinery.viatra.runtime.registry.view.AbstractRegistryView; | ||
14 | import tools.refinery.viatra.runtime.registry.IQuerySpecificationRegistryEntry; | ||
15 | |||
16 | /** | ||
17 | * Registry view implementation that uses a filter to delegate the decision on whether | ||
18 | * a given specification is relevant to the view. | ||
19 | * | ||
20 | * @author Abel Hegedus | ||
21 | * | ||
22 | */ | ||
23 | public class FilteringRegistryView extends AbstractRegistryView { | ||
24 | |||
25 | private IRegistryViewFilter filter; | ||
26 | |||
27 | /** | ||
28 | * Creates a new filtering view instance. | ||
29 | * | ||
30 | * @param registry that defines the view | ||
31 | * @param filter that is used for deciding relevancy | ||
32 | */ | ||
33 | public FilteringRegistryView(IQuerySpecificationRegistry registry, IRegistryViewFilter filter, boolean allowDuplicateFQNs) { | ||
34 | super(registry, allowDuplicateFQNs); | ||
35 | this.filter = filter; | ||
36 | } | ||
37 | |||
38 | @Override | ||
39 | protected boolean isEntryRelevant(IQuerySpecificationRegistryEntry entry) { | ||
40 | return filter.isEntryRelevant(entry); | ||
41 | } | ||
42 | |||
43 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/impl/GlobalRegistryView.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/impl/GlobalRegistryView.java deleted file mode 100644 index 75d730b6..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/impl/GlobalRegistryView.java +++ /dev/null | |||
@@ -1,65 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.registry.impl; | ||
10 | |||
11 | import java.util.NoSuchElementException; | ||
12 | import java.util.Set; | ||
13 | import java.util.stream.Collectors; | ||
14 | |||
15 | import tools.refinery.viatra.runtime.api.IQueryGroup; | ||
16 | import tools.refinery.viatra.runtime.api.LazyLoadingQueryGroup; | ||
17 | import tools.refinery.viatra.runtime.registry.IDefaultRegistryView; | ||
18 | import tools.refinery.viatra.runtime.registry.IQuerySpecificationRegistry; | ||
19 | import tools.refinery.viatra.runtime.registry.IQuerySpecificationRegistryEntry; | ||
20 | import tools.refinery.viatra.runtime.registry.view.AbstractRegistryView; | ||
21 | |||
22 | /** | ||
23 | * Registry view implementation that considers specifications relevant if they are included in default views. | ||
24 | * | ||
25 | * @author Abel Hegedus | ||
26 | * | ||
27 | */ | ||
28 | public class GlobalRegistryView extends AbstractRegistryView implements IDefaultRegistryView { | ||
29 | |||
30 | /** | ||
31 | * Creates a new instance of the global view. | ||
32 | * | ||
33 | * @param registry that defines the view | ||
34 | */ | ||
35 | public GlobalRegistryView(IQuerySpecificationRegistry registry) { | ||
36 | super(registry, false); | ||
37 | } | ||
38 | |||
39 | @Override | ||
40 | protected boolean isEntryRelevant(IQuerySpecificationRegistryEntry entry) { | ||
41 | return entry.includeInDefaultViews(); | ||
42 | } | ||
43 | |||
44 | @Override | ||
45 | public IQueryGroup getQueryGroup() { | ||
46 | Set<IQuerySpecificationRegistryEntry> allQueries = | ||
47 | fqnToEntryMap.distinctValuesStream().collect(Collectors.toSet()); | ||
48 | IQueryGroup queryGroup = LazyLoadingQueryGroup.of(allQueries); | ||
49 | return queryGroup; | ||
50 | } | ||
51 | |||
52 | @Override | ||
53 | public IQuerySpecificationRegistryEntry getEntry(String fullyQualifiedName) { | ||
54 | Set<IQuerySpecificationRegistryEntry> entries = getEntries(fullyQualifiedName); | ||
55 | if(entries.isEmpty()){ | ||
56 | throw new NoSuchElementException("Cannot find entry with FQN " + fullyQualifiedName); | ||
57 | } | ||
58 | if(entries.size() > 1) { | ||
59 | throw new IllegalStateException("Global view must never contain duplicated FQNs!"); | ||
60 | } | ||
61 | IQuerySpecificationRegistryEntry entry = entries.iterator().next(); | ||
62 | return entry; | ||
63 | } | ||
64 | |||
65 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/impl/QuerySpecificationRegistryImpl.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/impl/QuerySpecificationRegistryImpl.java deleted file mode 100644 index 63306e93..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/impl/QuerySpecificationRegistryImpl.java +++ /dev/null | |||
@@ -1,177 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.registry.impl; | ||
10 | |||
11 | import static tools.refinery.viatra.runtime.matchers.util.Preconditions.checkArgument; | ||
12 | |||
13 | import java.util.Map; | ||
14 | |||
15 | import org.apache.log4j.Logger; | ||
16 | import tools.refinery.viatra.runtime.extensibility.IQuerySpecificationProvider; | ||
17 | import tools.refinery.viatra.runtime.registry.IConnectorListener; | ||
18 | import tools.refinery.viatra.runtime.registry.IDefaultRegistryView; | ||
19 | import tools.refinery.viatra.runtime.registry.IQuerySpecificationRegistry; | ||
20 | import tools.refinery.viatra.runtime.registry.IRegistryView; | ||
21 | import tools.refinery.viatra.runtime.registry.IRegistryViewFactory; | ||
22 | import tools.refinery.viatra.runtime.registry.IRegistryViewFilter; | ||
23 | import tools.refinery.viatra.runtime.registry.IQuerySpecificationRegistryChangeListener; | ||
24 | import tools.refinery.viatra.runtime.registry.IRegistrySourceConnector; | ||
25 | import tools.refinery.viatra.runtime.registry.data.QuerySpecificationStore; | ||
26 | import tools.refinery.viatra.runtime.registry.data.RegistryEntryImpl; | ||
27 | import tools.refinery.viatra.runtime.registry.data.RegistrySourceImpl; | ||
28 | import tools.refinery.viatra.runtime.util.ViatraQueryLoggingUtil; | ||
29 | |||
30 | /** | ||
31 | * This is the default implementation of the {@link IQuerySpecificationRegistry} interface. | ||
32 | * It uses a {@link QuerySpecificationStore} to keep track of sources and entries. | ||
33 | * It uses a {@link RegistryChangeMultiplexer} to update all views and a single {@link IConnectorListener} | ||
34 | * to subscribe to sources added to the registry. | ||
35 | * | ||
36 | * @author Abel Hegedus | ||
37 | * | ||
38 | */ | ||
39 | public class QuerySpecificationRegistryImpl implements IQuerySpecificationRegistry { | ||
40 | |||
41 | private static final String CONNECTOR_NULL_MSG = "Connector cannot be null"; | ||
42 | private final QuerySpecificationStore querySpecificationStore; | ||
43 | private final IConnectorListener connectorListener; | ||
44 | private final RegistryChangeMultiplexer multiplexer; | ||
45 | private final Logger logger; | ||
46 | private IDefaultRegistryView defaultView = null; | ||
47 | |||
48 | /** | ||
49 | * Creates a new instance of the registry | ||
50 | */ | ||
51 | public QuerySpecificationRegistryImpl() { | ||
52 | this.querySpecificationStore = new QuerySpecificationStore(); | ||
53 | this.connectorListener = new RegistryUpdaterConnectorListener(); | ||
54 | this.multiplexer = new RegistryChangeMultiplexer(); | ||
55 | this.logger = ViatraQueryLoggingUtil.getLogger(IQuerySpecificationRegistry.class); | ||
56 | } | ||
57 | |||
58 | @Override | ||
59 | public boolean addSource(IRegistrySourceConnector connector) { | ||
60 | checkArgument(connector != null, CONNECTOR_NULL_MSG); | ||
61 | String identifier = connector.getIdentifier(); | ||
62 | Map<String, RegistrySourceImpl> sources = querySpecificationStore.getSources(); | ||
63 | if(sources.containsKey(identifier)){ | ||
64 | return false; | ||
65 | } | ||
66 | RegistrySourceImpl source = new RegistrySourceImpl(identifier, querySpecificationStore, connector.includeSpecificationsInDefaultViews()); | ||
67 | sources.put(identifier, source); | ||
68 | connector.addListener(connectorListener); | ||
69 | logger.debug("Source added: " + source.getIdentifier()); | ||
70 | return true; | ||
71 | } | ||
72 | |||
73 | @Override | ||
74 | public boolean removeSource(IRegistrySourceConnector connector) { | ||
75 | checkArgument(connector != null, CONNECTOR_NULL_MSG); | ||
76 | String identifier = connector.getIdentifier(); | ||
77 | Map<String, RegistrySourceImpl> sources = querySpecificationStore.getSources(); | ||
78 | if(!sources.containsKey(identifier)){ | ||
79 | return false; | ||
80 | } | ||
81 | connector.removeListener(connectorListener); | ||
82 | RegistrySourceImpl source = sources.remove(identifier); | ||
83 | for (RegistryEntryImpl entry : source.getFqnToEntryMap().values()) { | ||
84 | multiplexer.entryRemoved(entry); | ||
85 | } | ||
86 | logger.debug("Source removed: " + source.getIdentifier()); | ||
87 | return true; | ||
88 | } | ||
89 | |||
90 | /** | ||
91 | * @return the internal store of the registry | ||
92 | */ | ||
93 | protected QuerySpecificationStore getStore() { | ||
94 | return querySpecificationStore; | ||
95 | } | ||
96 | |||
97 | @Override | ||
98 | public IRegistryView createView() { | ||
99 | return createGlobalView(); | ||
100 | } | ||
101 | |||
102 | private GlobalRegistryView createGlobalView() { | ||
103 | GlobalRegistryView registryView = new GlobalRegistryView(this); | ||
104 | initializeChangeListener(registryView); | ||
105 | return registryView; | ||
106 | } | ||
107 | |||
108 | protected void initializeChangeListener(IQuerySpecificationRegistryChangeListener listener) { | ||
109 | // send existing entries to aspect | ||
110 | for (RegistrySourceImpl source : querySpecificationStore.getSources().values()) { | ||
111 | Map<String, RegistryEntryImpl> entryMap = source.getFqnToEntryMap(); | ||
112 | for (RegistryEntryImpl entry : entryMap.values()) { | ||
113 | listener.entryAdded(entry); | ||
114 | } | ||
115 | } | ||
116 | multiplexer.addListener(listener); | ||
117 | } | ||
118 | |||
119 | @Override | ||
120 | public IRegistryView createView(IRegistryViewFilter filter) { | ||
121 | checkArgument(filter != null, "Filter cannot be null"); | ||
122 | FilteringRegistryView registryView = new FilteringRegistryView(this, filter, false); | ||
123 | initializeChangeListener(registryView); | ||
124 | return registryView; | ||
125 | } | ||
126 | |||
127 | /** | ||
128 | * Internal connector listener implementation for updating internal store and propagating changes to views. | ||
129 | * | ||
130 | * @author Abel Hegedus | ||
131 | * | ||
132 | */ | ||
133 | private final class RegistryUpdaterConnectorListener implements IConnectorListener { | ||
134 | @Override | ||
135 | public void querySpecificationAdded(IRegistrySourceConnector connector, IQuerySpecificationProvider specification) { | ||
136 | String identifier = connector.getIdentifier(); | ||
137 | RegistrySourceImpl source = querySpecificationStore.getSources().get(identifier); | ||
138 | String fullyQualifiedName = specification.getFullyQualifiedName(); | ||
139 | RegistryEntryImpl registryEntry = new RegistryEntryImpl(source, specification); | ||
140 | RegistryEntryImpl oldEntry = source.getFqnToEntryMap().put(fullyQualifiedName, registryEntry); | ||
141 | if(oldEntry != null) { | ||
142 | logger.warn(String.format("Specification added with existing FQN %s in source %s", fullyQualifiedName, identifier)); | ||
143 | multiplexer.entryRemoved(oldEntry); | ||
144 | } | ||
145 | multiplexer.entryAdded(registryEntry); | ||
146 | |||
147 | } | ||
148 | |||
149 | @Override | ||
150 | public void querySpecificationRemoved(IRegistrySourceConnector connector, IQuerySpecificationProvider specification) { | ||
151 | String identifier = connector.getIdentifier(); | ||
152 | RegistrySourceImpl source = querySpecificationStore.getSources().get(identifier); | ||
153 | String fullyQualifiedName = specification.getFullyQualifiedName(); | ||
154 | RegistryEntryImpl registryEntry = source.getFqnToEntryMap().remove(fullyQualifiedName); | ||
155 | if(registryEntry != null) { | ||
156 | multiplexer.entryRemoved(registryEntry); | ||
157 | } | ||
158 | } | ||
159 | } | ||
160 | |||
161 | @Override | ||
162 | public IDefaultRegistryView getDefaultView() { | ||
163 | if(this.defaultView == null){ | ||
164 | this.defaultView = createGlobalView(); | ||
165 | } | ||
166 | return this.defaultView; | ||
167 | } | ||
168 | |||
169 | @Override | ||
170 | public IRegistryView createView(IRegistryViewFactory factory) { | ||
171 | IRegistryView registryView = factory.createView(this); | ||
172 | initializeChangeListener(registryView); | ||
173 | return registryView; | ||
174 | } | ||
175 | |||
176 | |||
177 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/impl/RegistryChangeMultiplexer.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/impl/RegistryChangeMultiplexer.java deleted file mode 100644 index 450f36b8..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/impl/RegistryChangeMultiplexer.java +++ /dev/null | |||
@@ -1,58 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.registry.impl; | ||
10 | |||
11 | import java.util.Collections; | ||
12 | import java.util.Set; | ||
13 | import java.util.WeakHashMap; | ||
14 | |||
15 | import tools.refinery.viatra.runtime.registry.IQuerySpecificationRegistryChangeListener; | ||
16 | import tools.refinery.viatra.runtime.registry.IQuerySpecificationRegistryEntry; | ||
17 | |||
18 | /** | ||
19 | * Listener implementation that propagates all changes to a set of listeners. | ||
20 | * The listeners are stored with weak references to avoid a need for disposal. | ||
21 | * | ||
22 | * @author Abel Hegedus | ||
23 | * | ||
24 | */ | ||
25 | public class RegistryChangeMultiplexer implements IQuerySpecificationRegistryChangeListener { | ||
26 | |||
27 | private Set<IQuerySpecificationRegistryChangeListener> listeners; | ||
28 | |||
29 | /** | ||
30 | * Creates a new instance of the multiplexer. | ||
31 | */ | ||
32 | public RegistryChangeMultiplexer() { | ||
33 | this.listeners = Collections.newSetFromMap(new WeakHashMap<IQuerySpecificationRegistryChangeListener, Boolean>()); | ||
34 | } | ||
35 | |||
36 | /** | ||
37 | * Adds a weak reference on the listener to the multiplexer. The listener will receive all further notifications and | ||
38 | * does not have to be removed, since the multiplexer will not keep it in memory when it can be collected. | ||
39 | */ | ||
40 | public boolean addListener(IQuerySpecificationRegistryChangeListener listener) { | ||
41 | return listeners.add(listener); | ||
42 | } | ||
43 | |||
44 | @Override | ||
45 | public void entryAdded(IQuerySpecificationRegistryEntry entry) { | ||
46 | for (IQuerySpecificationRegistryChangeListener listener : listeners) { | ||
47 | listener.entryAdded(entry); | ||
48 | } | ||
49 | } | ||
50 | |||
51 | @Override | ||
52 | public void entryRemoved(IQuerySpecificationRegistryEntry entry) { | ||
53 | for (IQuerySpecificationRegistryChangeListener listener : listeners) { | ||
54 | listener.entryRemoved(entry); | ||
55 | } | ||
56 | } | ||
57 | |||
58 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/view/AbstractRegistryView.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/view/AbstractRegistryView.java deleted file mode 100644 index 7b3c34ba..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/registry/view/AbstractRegistryView.java +++ /dev/null | |||
@@ -1,150 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Abel Hegedus, 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.registry.view; | ||
10 | |||
11 | import java.util.Collections; | ||
12 | import java.util.HashSet; | ||
13 | import java.util.Set; | ||
14 | import java.util.stream.Collectors; | ||
15 | |||
16 | import org.apache.log4j.Logger; | ||
17 | import tools.refinery.viatra.runtime.matchers.util.CollectionsFactory; | ||
18 | import tools.refinery.viatra.runtime.matchers.util.CollectionsFactory.MemoryType; | ||
19 | import tools.refinery.viatra.runtime.matchers.util.IMemoryView; | ||
20 | import tools.refinery.viatra.runtime.matchers.util.IMultiLookup; | ||
21 | import tools.refinery.viatra.runtime.matchers.util.Preconditions; | ||
22 | import tools.refinery.viatra.runtime.registry.IQuerySpecificationRegistry; | ||
23 | import tools.refinery.viatra.runtime.registry.IQuerySpecificationRegistryChangeListener; | ||
24 | import tools.refinery.viatra.runtime.registry.IQuerySpecificationRegistryEntry; | ||
25 | import tools.refinery.viatra.runtime.registry.IRegistryView; | ||
26 | import tools.refinery.viatra.runtime.util.ViatraQueryLoggingUtil; | ||
27 | |||
28 | /** | ||
29 | * An abstract {@link IRegistryView} implementation that stores the registry, the set of listeners added to the view and | ||
30 | * the FQN to entry map of the view itself. The only responsibility of subclasses is to decide whether an entry received | ||
31 | * as an addition or removal notification is relevant to the view. | ||
32 | * | ||
33 | * @author Abel Hegedus | ||
34 | * @since 1.3 | ||
35 | */ | ||
36 | public abstract class AbstractRegistryView implements IRegistryView { | ||
37 | |||
38 | private static final String LISTENER_EXCEPTION_REMOVE = "Exception occurred while notifying view listener %s about entry removal"; | ||
39 | private static final String LISTENER_EXCEPTION_ADD = "Exception occurred while notifying view listener %s about entry addition"; | ||
40 | protected final IQuerySpecificationRegistry registry; | ||
41 | protected final IMultiLookup<String, IQuerySpecificationRegistryEntry> fqnToEntryMap; | ||
42 | protected final Set<IQuerySpecificationRegistryChangeListener> listeners; | ||
43 | protected final boolean allowDuplicateFQNs; | ||
44 | |||
45 | /** | ||
46 | * This method is called both when an addition or removal notification is received from the registry. Subclasses can | ||
47 | * implement view filtering by returning false for those specifications that are not relevant for this view. | ||
48 | * | ||
49 | * @param entry | ||
50 | * that is added or removed in the registry | ||
51 | * @return true if the entry should be added to or removed from the view, false otherwise | ||
52 | */ | ||
53 | protected abstract boolean isEntryRelevant(IQuerySpecificationRegistryEntry entry); | ||
54 | |||
55 | /** | ||
56 | * Creates a new view instance for the given registry. Note that views are created by the registry and the view | ||
57 | * update mechanisms are also set up by the registry. | ||
58 | * | ||
59 | * @param registry | ||
60 | */ | ||
61 | public AbstractRegistryView(IQuerySpecificationRegistry registry, boolean allowDuplicateFQNs) { | ||
62 | this.registry = registry; | ||
63 | this.allowDuplicateFQNs = allowDuplicateFQNs; | ||
64 | this.fqnToEntryMap = CollectionsFactory.createMultiLookup(Object.class, MemoryType.SETS, Object.class); | ||
65 | this.listeners = new HashSet<>(); | ||
66 | } | ||
67 | |||
68 | @Override | ||
69 | public IQuerySpecificationRegistry getRegistry() { | ||
70 | return registry; | ||
71 | } | ||
72 | |||
73 | @Override | ||
74 | public Iterable<IQuerySpecificationRegistryEntry> getEntries() { | ||
75 | return fqnToEntryMap.distinctValuesStream().collect(Collectors.toSet()); | ||
76 | } | ||
77 | |||
78 | @Override | ||
79 | public Set<String> getQuerySpecificationFQNs() { | ||
80 | return fqnToEntryMap.distinctKeysStream().collect(Collectors.toSet()); | ||
81 | } | ||
82 | |||
83 | @Override | ||
84 | public boolean hasQuerySpecificationFQN(String fullyQualifiedName) { | ||
85 | Preconditions.checkArgument(fullyQualifiedName != null, "FQN must not be null!"); | ||
86 | return fqnToEntryMap.lookupExists(fullyQualifiedName); | ||
87 | } | ||
88 | |||
89 | @Override | ||
90 | public Set<IQuerySpecificationRegistryEntry> getEntries(String fullyQualifiedName) { | ||
91 | Preconditions.checkArgument(fullyQualifiedName != null, "FQN must not be null!"); | ||
92 | IMemoryView<IQuerySpecificationRegistryEntry> entries = fqnToEntryMap.lookupOrEmpty(fullyQualifiedName); | ||
93 | return Collections.unmodifiableSet(entries.distinctValues()); | ||
94 | } | ||
95 | |||
96 | @Override | ||
97 | public void addViewListener(IQuerySpecificationRegistryChangeListener listener) { | ||
98 | Preconditions.checkArgument(listener != null, "Null listener not supported"); | ||
99 | listeners.add(listener); | ||
100 | } | ||
101 | |||
102 | @Override | ||
103 | public void removeViewListener(IQuerySpecificationRegistryChangeListener listener) { | ||
104 | Preconditions.checkArgument(listener != null, "Null listener not supported"); | ||
105 | listeners.remove(listener); | ||
106 | } | ||
107 | |||
108 | @Override | ||
109 | public void entryAdded(IQuerySpecificationRegistryEntry entry) { | ||
110 | if (isEntryRelevant(entry)) { | ||
111 | String fullyQualifiedName = entry.getFullyQualifiedName(); | ||
112 | IMemoryView<IQuerySpecificationRegistryEntry> duplicates = fqnToEntryMap.lookup(fullyQualifiedName); | ||
113 | if(!allowDuplicateFQNs && duplicates != null) { | ||
114 | Set<IQuerySpecificationRegistryEntry> removed = new HashSet<>(duplicates.distinctValues()); | ||
115 | for (IQuerySpecificationRegistryEntry e : removed) { | ||
116 | fqnToEntryMap.removePair(fullyQualifiedName, e); | ||
117 | notifyListeners(e, false); | ||
118 | } | ||
119 | } | ||
120 | fqnToEntryMap.addPair(fullyQualifiedName, entry); | ||
121 | notifyListeners(entry, true); | ||
122 | } | ||
123 | } | ||
124 | |||
125 | @Override | ||
126 | public void entryRemoved(IQuerySpecificationRegistryEntry entry) { | ||
127 | if (isEntryRelevant(entry)) { | ||
128 | String fullyQualifiedName = entry.getFullyQualifiedName(); | ||
129 | fqnToEntryMap.removePair(fullyQualifiedName, entry); | ||
130 | notifyListeners(entry, false); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | private void notifyListeners(IQuerySpecificationRegistryEntry entry, boolean addition) { | ||
135 | for (IQuerySpecificationRegistryChangeListener listener : listeners) { | ||
136 | try { | ||
137 | if(addition){ | ||
138 | listener.entryAdded(entry); | ||
139 | } else { | ||
140 | listener.entryRemoved(entry); | ||
141 | } | ||
142 | } catch (Exception ex) { | ||
143 | Logger logger = ViatraQueryLoggingUtil.getLogger(AbstractRegistryView.class); | ||
144 | String formatString = addition ? LISTENER_EXCEPTION_ADD : LISTENER_EXCEPTION_REMOVE; | ||
145 | logger.error(String.format(formatString, listener), ex); | ||
146 | } | ||
147 | } | ||
148 | } | ||
149 | |||
150 | } \ No newline at end of file | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/tabular/EcoreIndexHost.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/tabular/EcoreIndexHost.java deleted file mode 100644 index e87a726a..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/tabular/EcoreIndexHost.java +++ /dev/null | |||
@@ -1,166 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2018, Gabor Bergmann, 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 | |||
10 | package tools.refinery.viatra.runtime.tabular; | ||
11 | |||
12 | import java.util.Collections; | ||
13 | import java.util.Map; | ||
14 | import java.util.Map.Entry; | ||
15 | import java.util.Set; | ||
16 | |||
17 | import org.eclipse.emf.ecore.EClass; | ||
18 | import org.eclipse.emf.ecore.EClassifier; | ||
19 | import org.eclipse.emf.ecore.EDataType; | ||
20 | import org.eclipse.emf.ecore.EPackage; | ||
21 | import org.eclipse.emf.ecore.EStructuralFeature; | ||
22 | import org.eclipse.emf.ecore.EcorePackage; | ||
23 | import tools.refinery.viatra.runtime.api.scope.QueryScope; | ||
24 | import tools.refinery.viatra.runtime.emf.EMFQueryMetaContext; | ||
25 | import tools.refinery.viatra.runtime.emf.EMFScope; | ||
26 | import tools.refinery.viatra.runtime.emf.types.EClassExactInstancesKey; | ||
27 | import tools.refinery.viatra.runtime.emf.types.EClassTransitiveInstancesKey; | ||
28 | import tools.refinery.viatra.runtime.emf.types.EDataTypeInSlotsKey; | ||
29 | import tools.refinery.viatra.runtime.emf.types.EStructuralFeatureInstancesKey; | ||
30 | import tools.refinery.viatra.runtime.matchers.context.IInputKey; | ||
31 | import tools.refinery.viatra.runtime.matchers.scopes.IStorageBackend; | ||
32 | import tools.refinery.viatra.runtime.matchers.scopes.SimpleRuntimeContext; | ||
33 | import tools.refinery.viatra.runtime.matchers.scopes.tables.DisjointUnionTable; | ||
34 | import tools.refinery.viatra.runtime.matchers.scopes.tables.ITableWriterBinary; | ||
35 | import tools.refinery.viatra.runtime.matchers.scopes.tables.ITableWriterUnary; | ||
36 | import tools.refinery.viatra.runtime.matchers.util.CollectionsFactory; | ||
37 | |||
38 | /** | ||
39 | * Simple EMF-specific demo tabular index host. | ||
40 | * | ||
41 | * <p> Usage: <ul> | ||
42 | * <li> First, instantiate index host with given Ecore metamodel packages | ||
43 | * <li> To emulate an EMF instance model, write arbitrary content into the tables using {@link #getTableDirectInstances(EClassifier)} and {@link #getTableFeatureSlots(EStructuralFeature)}. | ||
44 | * <li> Initialize and evaluate regular EMF-based Viatra queries on the scope provided by {@link #getScope()}, as you would on an {@link EMFScope}. | ||
45 | * <ul> | ||
46 | * | ||
47 | * <p> | ||
48 | * <strong>EXPERIMENTAL</strong>. This class or interface has been added as | ||
49 | * part of a work in progress. There is no guarantee that this API will | ||
50 | * work or that it will remain the same. | ||
51 | * | ||
52 | * @author Gabor Bergmann | ||
53 | * @since 2.1 | ||
54 | */ | ||
55 | public class EcoreIndexHost extends TabularIndexHost { | ||
56 | |||
57 | public EcoreIndexHost(IStorageBackend storage, EPackage... packages) { | ||
58 | super(storage, new SimpleRuntimeContext(EMFQueryMetaContext.DEFAULT_SURROGATE)); | ||
59 | |||
60 | initTables(packages); | ||
61 | } | ||
62 | |||
63 | @Override | ||
64 | protected boolean isQueryScopeEmulated(Class<? extends QueryScope> queryScopeClass) { | ||
65 | return EMFScope.class.equals(queryScopeClass); | ||
66 | } | ||
67 | |||
68 | |||
69 | private Map<EClassifier, ITableWriterUnary.Table<Object>> tableDirectInstances = CollectionsFactory.createMap(); | ||
70 | private Map<EClass, DisjointUnionTable> tableTransitiveInstances = CollectionsFactory.createMap(); | ||
71 | private Map<EStructuralFeature, ITableWriterBinary.Table<Object, Object>> tableFeatures = CollectionsFactory.createMap(); | ||
72 | |||
73 | private void initTables(EPackage[] packages) { | ||
74 | |||
75 | // create instance tables first | ||
76 | for (EPackage ePackage : packages) { | ||
77 | for (EClassifier eClassifier : ePackage.getEClassifiers()) { | ||
78 | boolean unique; | ||
79 | IInputKey classifierKey; | ||
80 | if (eClassifier instanceof EClass) { | ||
81 | EClass eClass = (EClass) eClassifier; | ||
82 | |||
83 | // create transitive instances table | ||
84 | IInputKey transitiveKey = new EClassTransitiveInstancesKey(eClass); | ||
85 | DisjointUnionTable transitiveTable = registerNewTable(new DisjointUnionTable(transitiveKey, runtimeContext)); | ||
86 | tableTransitiveInstances.put(eClass, transitiveTable); | ||
87 | |||
88 | // process feature tables | ||
89 | for (EStructuralFeature feature : eClass.getEStructuralFeatures()) { | ||
90 | IInputKey featureKey = new EStructuralFeatureInstancesKey(feature); | ||
91 | ITableWriterBinary.Table<Object, Object> featureTable = newBinaryInputTable(featureKey, feature.isUnique()); | ||
92 | tableFeatures.put(feature, featureTable); | ||
93 | } | ||
94 | |||
95 | // direct instance table | ||
96 | unique = true; | ||
97 | classifierKey = new EClassExactInstancesKey(eClass); | ||
98 | } else { // datatype | ||
99 | unique = false; | ||
100 | classifierKey = new EDataTypeInSlotsKey((EDataType) eClassifier); | ||
101 | } | ||
102 | ITableWriterUnary.Table<Object> directTable = newUnaryInputTable(classifierKey, unique); | ||
103 | tableDirectInstances.put(eClassifier, directTable); | ||
104 | } | ||
105 | } | ||
106 | |||
107 | // global implicit supertype EObject is always available as a transitive table | ||
108 | EClass eObjectClass = EcorePackage.eINSTANCE.getEObject(); | ||
109 | DisjointUnionTable eObjectAllInstancesTable = tableTransitiveInstances.get(eObjectClass); | ||
110 | if (eObjectAllInstancesTable == null) { // is it already added? | ||
111 | IInputKey transitiveKey = new EClassTransitiveInstancesKey(eObjectClass); | ||
112 | eObjectAllInstancesTable = registerNewTable(new DisjointUnionTable(transitiveKey, runtimeContext)); | ||
113 | tableTransitiveInstances.put(eObjectClass, eObjectAllInstancesTable); | ||
114 | |||
115 | boolean unique = true; | ||
116 | IInputKey classifierKey = new EClassExactInstancesKey(eObjectClass); | ||
117 | ITableWriterUnary.Table<Object> directTable = newUnaryInputTable(classifierKey, unique); | ||
118 | tableDirectInstances.put(eObjectClass, directTable); | ||
119 | } | ||
120 | |||
121 | // set up disjoint unoin tables | ||
122 | for (Entry<EClass, DisjointUnionTable> entry : tableTransitiveInstances.entrySet()) { | ||
123 | EClass eClass = entry.getKey(); | ||
124 | ITableWriterUnary.Table<Object> directTable = tableDirectInstances.get(eClass); | ||
125 | |||
126 | // the direct type itself is a child | ||
127 | entry.getValue().addChildTable(directTable); | ||
128 | |||
129 | // connect supertypes | ||
130 | for (EClass superClass : eClass.getEAllSuperTypes()) { | ||
131 | DisjointUnionTable transitiveTable = tableTransitiveInstances.get(superClass); | ||
132 | if (transitiveTable == null) { | ||
133 | throw new IllegalStateException( | ||
134 | String.format("No index table found for EClass %s, supertype of %s", | ||
135 | superClass.getName(), eClass.getName()) | ||
136 | ); | ||
137 | } | ||
138 | transitiveTable.addChildTable(directTable); | ||
139 | } | ||
140 | // global implicit supertype | ||
141 | if (!eClass.equals(eObjectClass)) { | ||
142 | eObjectAllInstancesTable.addChildTable(directTable); | ||
143 | } | ||
144 | |||
145 | } | ||
146 | |||
147 | } | ||
148 | |||
149 | public ITableWriterUnary.Table<Object> getTableDirectInstances(EClassifier classifier) { | ||
150 | return tableDirectInstances.get(classifier); | ||
151 | } | ||
152 | public ITableWriterBinary.Table<Object, Object> getTableFeatureSlots(EStructuralFeature feature) { | ||
153 | return tableFeatures.get(feature); | ||
154 | } | ||
155 | |||
156 | |||
157 | |||
158 | public Set<Entry<EClassifier, ITableWriterUnary.Table<Object>>> getAllCurrentTablesDirectInstances() { | ||
159 | return Collections.unmodifiableSet(tableDirectInstances.entrySet()); | ||
160 | } | ||
161 | public Set<Entry<EStructuralFeature, ITableWriterBinary.Table<Object, Object>>> getAllCurrentTablesFeatures() { | ||
162 | return Collections.unmodifiableSet(tableFeatures.entrySet()); | ||
163 | } | ||
164 | |||
165 | |||
166 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/tabular/TabularEngineContext.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/tabular/TabularEngineContext.java deleted file mode 100644 index ee33d3bc..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/tabular/TabularEngineContext.java +++ /dev/null | |||
@@ -1,107 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2018, Gabor Bergmann, 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 | |||
10 | package tools.refinery.viatra.runtime.tabular; | ||
11 | |||
12 | import org.apache.log4j.Logger; | ||
13 | import tools.refinery.viatra.runtime.api.ViatraQueryEngine; | ||
14 | import tools.refinery.viatra.runtime.api.scope.*; | ||
15 | import tools.refinery.viatra.runtime.matchers.context.IQueryRuntimeContext; | ||
16 | import tools.refinery.viatra.runtime.matchers.util.CollectionsFactory; | ||
17 | |||
18 | import java.lang.reflect.InvocationTargetException; | ||
19 | import java.util.List; | ||
20 | import java.util.concurrent.Callable; | ||
21 | |||
22 | /** | ||
23 | * @author Gabor Bergmann | ||
24 | * | ||
25 | * @since 2.1 | ||
26 | */ | ||
27 | class TabularEngineContext implements IEngineContext, IBaseIndex { | ||
28 | |||
29 | private TabularIndexHost indexHost; | ||
30 | private ViatraQueryEngine engine; | ||
31 | private Logger logger; | ||
32 | |||
33 | private List<IIndexingErrorListener> errorListeners = CollectionsFactory.createObserverList(); | ||
34 | |||
35 | public TabularEngineContext(TabularIndexHost server, ViatraQueryEngine engine, | ||
36 | IIndexingErrorListener errorListener, Logger logger) { | ||
37 | this.indexHost = server; | ||
38 | this.engine = engine; | ||
39 | this.logger = logger; | ||
40 | |||
41 | this.addIndexingErrorListener(errorListener); | ||
42 | } | ||
43 | |||
44 | @Override | ||
45 | public IBaseIndex getBaseIndex() { | ||
46 | return this; | ||
47 | } | ||
48 | |||
49 | @Override | ||
50 | public void dispose() { | ||
51 | // NOP, server lifecycle not controlled by engine | ||
52 | } | ||
53 | |||
54 | @Override | ||
55 | public IQueryRuntimeContext getQueryRuntimeContext() { | ||
56 | return indexHost.getRuntimeContext(); | ||
57 | } | ||
58 | |||
59 | @Override | ||
60 | public <V> V coalesceTraversals(Callable<V> callable) throws InvocationTargetException { | ||
61 | try { | ||
62 | return callable.call(); | ||
63 | } catch (Exception e) { | ||
64 | throw new InvocationTargetException(e); | ||
65 | } | ||
66 | } | ||
67 | |||
68 | @Override | ||
69 | public void addBaseIndexChangeListener(ViatraBaseIndexChangeListener listener) { | ||
70 | // TODO no notifications yet | ||
71 | } | ||
72 | |||
73 | @Override | ||
74 | public void removeBaseIndexChangeListener(ViatraBaseIndexChangeListener listener) { | ||
75 | // TODO no notifications yet | ||
76 | } | ||
77 | |||
78 | @Override | ||
79 | public boolean addInstanceObserver(IInstanceObserver observer, Object observedObject) { | ||
80 | // TODO no notifications yet | ||
81 | return true; | ||
82 | } | ||
83 | |||
84 | @Override | ||
85 | public boolean removeInstanceObserver(IInstanceObserver observer, Object observedObject) { | ||
86 | // TODO no notifications yet | ||
87 | return true; | ||
88 | } | ||
89 | |||
90 | @Override | ||
91 | public void resampleDerivedFeatures() { | ||
92 | throw new UnsupportedOperationException(); | ||
93 | } | ||
94 | |||
95 | @Override | ||
96 | public boolean addIndexingErrorListener(IIndexingErrorListener listener) { | ||
97 | return errorListeners.add(listener); | ||
98 | } | ||
99 | |||
100 | @Override | ||
101 | public boolean removeIndexingErrorListener(IIndexingErrorListener listener) { | ||
102 | return errorListeners.remove(listener); | ||
103 | } | ||
104 | |||
105 | |||
106 | |||
107 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/tabular/TabularIndexHost.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/tabular/TabularIndexHost.java deleted file mode 100644 index 6f2a1f5f..00000000 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/tabular/TabularIndexHost.java +++ /dev/null | |||
@@ -1,145 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2018, Gabor Bergmann, 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.tabular; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.api.ViatraQueryEngine; | ||
12 | import tools.refinery.viatra.runtime.api.scope.IEngineContext; | ||
13 | import tools.refinery.viatra.runtime.api.scope.IIndexingErrorListener; | ||
14 | import tools.refinery.viatra.runtime.api.scope.QueryScope; | ||
15 | import tools.refinery.viatra.runtime.matchers.context.IInputKey; | ||
16 | import tools.refinery.viatra.runtime.matchers.scopes.IStorageBackend; | ||
17 | import tools.refinery.viatra.runtime.matchers.scopes.TabularRuntimeContext; | ||
18 | import tools.refinery.viatra.runtime.matchers.scopes.tables.IIndexTable; | ||
19 | import tools.refinery.viatra.runtime.matchers.scopes.tables.ITableWriterBinary; | ||
20 | import tools.refinery.viatra.runtime.matchers.scopes.tables.ITableWriterUnary; | ||
21 | |||
22 | /** | ||
23 | * Simple tabular index host. | ||
24 | * | ||
25 | * Unlike traditional Viatra instances initialized on a model, | ||
26 | * this index host can be initialized and then queried, | ||
27 | * while its queriable "contents" (base relations) can be separately written using table writer API. | ||
28 | * | ||
29 | * <p> Deriving classes are responsible for setting up the tables of this index and providing the writer API to clients. | ||
30 | * For the former, use {@link #newUnaryInputTable(IInputKey, boolean)}, | ||
31 | * {@link #newBinaryInputTable(IInputKey, boolean)} to create input tables, | ||
32 | * or {@link #registerNewTable(IIndexTable)} to register manually created derived tables. | ||
33 | * Instantiate such tables with {@link #runtimeContext} as their table context. | ||
34 | * | ||
35 | * | ||
36 | * <p> | ||
37 | * <strong>EXPERIMENTAL</strong>. This class or interface has been added as | ||
38 | * part of a work in progress. There is no guarantee that this API will | ||
39 | * work or that it will remain the same. | ||
40 | * | ||
41 | * @see EcoreIndexHost EcoreIndexHost for EMF-specific example usage. | ||
42 | * | ||
43 | * @author Gabor Bergmann | ||
44 | * @since 2.1 | ||
45 | */ | ||
46 | public abstract class TabularIndexHost { | ||
47 | |||
48 | private final IStorageBackend storage; | ||
49 | protected final TabularRuntimeContext runtimeContext; | ||
50 | protected final TabularIndexScope scope = new TabularIndexScope(); | ||
51 | |||
52 | public TabularIndexHost(IStorageBackend storage, TabularRuntimeContext runtimeContext) { | ||
53 | this.storage = storage; | ||
54 | this.runtimeContext = runtimeContext; | ||
55 | } | ||
56 | |||
57 | |||
58 | public TabularRuntimeContext getRuntimeContext() { | ||
59 | return runtimeContext; | ||
60 | } | ||
61 | |||
62 | public TabularIndexScope getScope() { | ||
63 | return scope; | ||
64 | } | ||
65 | |||
66 | /** | ||
67 | * @return true if this index host aims to serve queries that have a scope of the given type | ||
68 | */ | ||
69 | protected abstract boolean isQueryScopeEmulated(Class<? extends QueryScope> queryScopeClass); | ||
70 | |||
71 | |||
72 | |||
73 | /** | ||
74 | * Marks the beginning of an update transaction. | ||
75 | * In transaction mode, index table updates may be temporarily delayed for better performance. | ||
76 | * Stateful query backends will not update their results during the index update transaction. (TODO actually achieve this) | ||
77 | */ | ||
78 | public void startUpdateTransaction() { | ||
79 | storage.startTransaction(); | ||
80 | } | ||
81 | /** | ||
82 | * Marks the end of an update transaction. | ||
83 | * Any updates to index tables that were delayed during the transaction must now be flushed. | ||
84 | * Afterwards, stateful query backends will update their results. (TODO actually achieve this) | ||
85 | */ | ||
86 | public void finishUpdateTransaction() { | ||
87 | storage.finishTransaction(); | ||
88 | } | ||
89 | |||
90 | /** | ||
91 | * To be called by deriving class. Creates and registers a new unary input table. | ||
92 | */ | ||
93 | protected ITableWriterUnary.Table<Object> newUnaryInputTable(IInputKey key, boolean unique) { | ||
94 | return registerNewTable(storage.createUnaryTable(key, runtimeContext, unique)); | ||
95 | } | ||
96 | /** | ||
97 | * To be called by deriving class. Creates and registers a new binary input table. | ||
98 | */ | ||
99 | protected ITableWriterBinary.Table<Object,Object> newBinaryInputTable(IInputKey key, boolean unique) { | ||
100 | return registerNewTable(storage.createBinaryTable(key, runtimeContext, unique)); | ||
101 | } | ||
102 | /** | ||
103 | * To be called by deriving class. Registers the given freshly created table and also returns it for convenience. | ||
104 | */ | ||
105 | protected <Table extends IIndexTable> Table registerNewTable(Table newTable) { | ||
106 | runtimeContext.registerIndexTable(newTable); | ||
107 | return newTable; | ||
108 | } | ||
109 | |||
110 | |||
111 | /** | ||
112 | * A scope describing queries evaluated against tzhis index host. | ||
113 | * @author Gabor Bergmann | ||
114 | * | ||
115 | */ | ||
116 | public class TabularIndexScope extends QueryScope { | ||
117 | |||
118 | public TabularIndexHost getIndexHost() { | ||
119 | return TabularIndexHost.this; | ||
120 | } | ||
121 | |||
122 | @Override | ||
123 | public int hashCode() { | ||
124 | return getIndexHost().hashCode(); | ||
125 | } | ||
126 | |||
127 | @Override | ||
128 | public boolean equals(Object obj) { | ||
129 | if (obj instanceof TabularIndexScope) | ||
130 | return getIndexHost().equals(((TabularIndexScope) obj).getIndexHost()); | ||
131 | return false; | ||
132 | } | ||
133 | |||
134 | @Override | ||
135 | public boolean isCompatibleWithQueryScope(Class<? extends QueryScope> queryScopeClass) { | ||
136 | return isQueryScopeEmulated(queryScopeClass) || super.isCompatibleWithQueryScope(queryScopeClass); | ||
137 | } | ||
138 | |||
139 | @Override | ||
140 | protected IEngineContext createEngineContext(ViatraQueryEngine engine, IIndexingErrorListener errorListener, org.apache.log4j.Logger logger) { | ||
141 | return new TabularEngineContext(getIndexHost(), engine, errorListener, logger); | ||
142 | } | ||
143 | |||
144 | } | ||
145 | } | ||