diff options
author | 2023-09-16 13:19:31 +0200 | |
---|---|---|
committer | 2023-09-16 16:53:01 +0200 | |
commit | 97b0c4c1192fe5580a7957c844acc8092b56c604 (patch) | |
tree | bea3cdf9aaeb5da2864fcf87780d356661af8f63 /subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher | |
parent | build: fix Sonar quality gate issues (diff) | |
download | refinery-97b0c4c1192fe5580a7957c844acc8092b56c604.tar.gz refinery-97b0c4c1192fe5580a7957c844acc8092b56c604.tar.zst refinery-97b0c4c1192fe5580a7957c844acc8092b56c604.zip |
chore: remove VIATRA branding
Rename VIATRA subprojects to Refinery Interpreter to avoid interfering with
Eclipse Foundation trademarks.
Uses refering to a specific (historical) version of VIATRA were kept to avoid
ambiguity.
Diffstat (limited to 'subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher')
18 files changed, 0 insertions, 2250 deletions
diff --git a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/CallWithAdornment.java b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/CallWithAdornment.java deleted file mode 100644 index 0cabeb97..00000000 --- a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/CallWithAdornment.java +++ /dev/null | |||
@@ -1,55 +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.localsearch.matcher; | ||
10 | |||
11 | import java.util.HashSet; | ||
12 | import java.util.Set; | ||
13 | |||
14 | import tools.refinery.viatra.runtime.matchers.psystem.IQueryReference; | ||
15 | import tools.refinery.viatra.runtime.matchers.psystem.PConstraint; | ||
16 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PParameter; | ||
17 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
18 | |||
19 | /** | ||
20 | * Immutable data that represents the role of a pattern call within an LS query plan. | ||
21 | * | ||
22 | * <p> The call is expressed as the {@link PConstraint} {@link #call} (implementing {@link IQueryReference}), | ||
23 | * while the stored {@link #adornment} records the way it will be used within a search plan (specifically, | ||
24 | * pattern parameters within the adornment will have their values known at the point of evaluating the constraint). | ||
25 | * | ||
26 | * | ||
27 | * @author Gabor Bergmann | ||
28 | * @since 2.1 | ||
29 | */ | ||
30 | public class CallWithAdornment { | ||
31 | private final IQueryReference call; | ||
32 | private final Set<PParameter> adornment; | ||
33 | |||
34 | public CallWithAdornment(IQueryReference call, Set<PParameter> adornment) { | ||
35 | this.call = call; | ||
36 | this.adornment = new HashSet<>(adornment); | ||
37 | } | ||
38 | |||
39 | public IQueryReference getCall() { | ||
40 | return call; | ||
41 | } | ||
42 | |||
43 | public Set<PParameter> getAdornment() { | ||
44 | return adornment; | ||
45 | } | ||
46 | |||
47 | |||
48 | public PQuery getReferredQuery() { | ||
49 | return call.getReferredQuery(); | ||
50 | } | ||
51 | |||
52 | public MatcherReference getMatcherReference() { | ||
53 | return new MatcherReference(getReferredQuery(), adornment); | ||
54 | } | ||
55 | } | ||
diff --git a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/ILocalSearchAdaptable.java b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/ILocalSearchAdaptable.java deleted file mode 100644 index f4b28ed0..00000000 --- a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/ILocalSearchAdaptable.java +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Peter Lunk, 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.localsearch.matcher; | ||
10 | |||
11 | import java.util.List; | ||
12 | |||
13 | /** | ||
14 | * @author Zoltan Ujhelyi | ||
15 | * | ||
16 | */ | ||
17 | public interface ILocalSearchAdaptable { | ||
18 | |||
19 | List<ILocalSearchAdapter> getAdapters(); | ||
20 | |||
21 | void addAdapter(ILocalSearchAdapter adapter); | ||
22 | |||
23 | void removeAdapter(ILocalSearchAdapter adapter); | ||
24 | |||
25 | void removeAdapters(List<ILocalSearchAdapter> adapter); | ||
26 | |||
27 | void addAdapters(List<ILocalSearchAdapter> adapter); | ||
28 | |||
29 | } \ No newline at end of file | ||
diff --git a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/ILocalSearchAdapter.java b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/ILocalSearchAdapter.java deleted file mode 100644 index df64b5f1..00000000 --- a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/ILocalSearchAdapter.java +++ /dev/null | |||
@@ -1,120 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Marton Bur, Akos Horvath, 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.localsearch.matcher; | ||
10 | |||
11 | import java.util.Optional; | ||
12 | |||
13 | import tools.refinery.viatra.runtime.localsearch.ExecutionLoggerAdapter; | ||
14 | import tools.refinery.viatra.runtime.localsearch.MatchingFrame; | ||
15 | import tools.refinery.viatra.runtime.localsearch.operations.ISearchOperation; | ||
16 | import tools.refinery.viatra.runtime.localsearch.plan.SearchPlan; | ||
17 | import tools.refinery.viatra.runtime.localsearch.profiler.LocalSearchProfilerAdapter; | ||
18 | |||
19 | |||
20 | /** | ||
21 | * A local search adapter allows external code to follow the internal executions of the local search matcher. Possible | ||
22 | * implementations of the interface include profilers and debuggers. | ||
23 | * <p> | ||
24 | * <strong>EXPERIMENTAL</strong>. A few shortcomings have been found for this interface late during the development | ||
25 | * lifecycle of version 2.0 whose solution might need breaking possible future implementors. Because of this, right now | ||
26 | * it is not recommended to provide implementations outside of VIATRA. If necessary, have a look at the built-in | ||
27 | * adapters that should fulfill most cases in the meantime. See bugs https://bugs.eclipse.org/bugs/show_bug.cgi?id=535101 | ||
28 | * and https://bugs.eclipse.org/bugs/show_bug.cgi?id=535102 for details. | ||
29 | * | ||
30 | * @author Marton Bur | ||
31 | * @see ExecutionLoggerAdapter | ||
32 | * @see LocalSearchProfilerAdapter | ||
33 | * | ||
34 | */ | ||
35 | public interface ILocalSearchAdapter { | ||
36 | |||
37 | /** | ||
38 | * | ||
39 | * @since 1.2 | ||
40 | */ | ||
41 | default void adapterRegistered(ILocalSearchAdaptable adaptable) {}; | ||
42 | /** | ||
43 | * | ||
44 | * @since 1.2 | ||
45 | */ | ||
46 | default void adapterUnregistered(ILocalSearchAdaptable adaptable) {}; | ||
47 | |||
48 | /** | ||
49 | * Callback method to indicate the start of a matching process | ||
50 | * | ||
51 | * @param lsMatcher the local search matcher that starts the matching | ||
52 | */ | ||
53 | default void patternMatchingStarted(LocalSearchMatcher lsMatcher) {}; | ||
54 | |||
55 | /** | ||
56 | * Callback method to indicate the end of a matching process | ||
57 | * </p> | ||
58 | * <strong>WARNING</strong>: It is not guaranteed that this method will be called; | ||
59 | * it is possible that a match process will end after a match is found and no other matches are accessed. | ||
60 | * | ||
61 | * @param lsMatcher the local search matcher that finished | ||
62 | * @since 2.0 | ||
63 | */ | ||
64 | default void noMoreMatchesAvailable(LocalSearchMatcher lsMatcher) {}; | ||
65 | |||
66 | /** | ||
67 | * Callback method to indicate switching to a new plan during the execution of a pattern matching | ||
68 | * | ||
69 | * @param oldPlan the plan that is finished. Value is null when the first plan is starting. | ||
70 | * @param newPlan the plan that will begin execution | ||
71 | * @since 2.0 | ||
72 | */ | ||
73 | default void planChanged(Optional<SearchPlan> oldPlan, Optional<SearchPlan> newPlan) {}; | ||
74 | |||
75 | /** | ||
76 | * Callback method to indicate the selection of an operation to execute | ||
77 | * | ||
78 | * @param plan the current plan executor | ||
79 | * @param frame the current matching frame | ||
80 | * @param isBacktrack if true, the selected operation was reached via backtracking | ||
81 | * @since 2.0 | ||
82 | */ | ||
83 | default void operationSelected(SearchPlan plan, ISearchOperation operation, MatchingFrame frame, boolean isBacktrack) {}; | ||
84 | |||
85 | /** | ||
86 | * Callback method to indicate that an operation is executed | ||
87 | * | ||
88 | * @param plan the current plan | ||
89 | * @param frame the current matching frame | ||
90 | * @param isSuccessful if true, the operation executed successfully, or false if the execution failed and backtracking will happen | ||
91 | * @since 2.0 | ||
92 | */ | ||
93 | default void operationExecuted(SearchPlan plan, ISearchOperation operation, MatchingFrame frame, boolean isSuccessful) {}; | ||
94 | |||
95 | /** | ||
96 | * Callback that is used to indicate that a match has been found | ||
97 | * | ||
98 | * @param plan the search plan executor that found the match | ||
99 | * @param frame the frame that holds the substitutions of the variables that match | ||
100 | * @since 2.0 | ||
101 | */ | ||
102 | default void matchFound(SearchPlan plan, MatchingFrame frame) {}; | ||
103 | /** | ||
104 | * Callback that is used to indicate that the previously reported match has been found as a duplicate, thus will be ignored from the match results. | ||
105 | * | ||
106 | * @param plan the search plan executor that found the match | ||
107 | * @param frame the frame that holds the substitutions of the variables that match | ||
108 | * @since 2.0 | ||
109 | */ | ||
110 | default void duplicateMatchFound(MatchingFrame frame) {}; | ||
111 | |||
112 | /** | ||
113 | * Callback method to indicate that a search plan is initialized in an executor with the given frame and starting operation | ||
114 | * | ||
115 | * @param searchPlan | ||
116 | * @param frame | ||
117 | * @since 2.0 | ||
118 | */ | ||
119 | default void executorInitializing(SearchPlan searchPlan, MatchingFrame frame) {}; | ||
120 | } | ||
diff --git a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/ISearchContext.java b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/ISearchContext.java deleted file mode 100644 index 71aa4aac..00000000 --- a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/ISearchContext.java +++ /dev/null | |||
@@ -1,120 +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.localsearch.matcher; | ||
10 | |||
11 | import org.apache.log4j.Logger; | ||
12 | import tools.refinery.viatra.runtime.localsearch.matcher.integration.IAdornmentProvider; | ||
13 | import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException; | ||
14 | import tools.refinery.viatra.runtime.matchers.backend.IQueryResultProvider; | ||
15 | import tools.refinery.viatra.runtime.matchers.backend.ResultProviderRequestor; | ||
16 | import tools.refinery.viatra.runtime.matchers.context.IQueryBackendContext; | ||
17 | import tools.refinery.viatra.runtime.matchers.context.IQueryRuntimeContext; | ||
18 | import tools.refinery.viatra.runtime.matchers.util.ICache; | ||
19 | import tools.refinery.viatra.runtime.matchers.util.IProvider; | ||
20 | |||
21 | import java.util.Collections; | ||
22 | |||
23 | /** | ||
24 | * The {@link ISearchContext} interface allows search operations to reuse platform services such as the indexer. | ||
25 | * | ||
26 | * @author Zoltan Ujhelyi | ||
27 | * @noreference This interface is not intended to be referenced by clients. | ||
28 | * @noimplement This interface is not intended to be implemented by clients. | ||
29 | * @noextend This interface is not intended to be extended by clients. | ||
30 | * | ||
31 | */ | ||
32 | public interface ISearchContext { | ||
33 | |||
34 | /** | ||
35 | * Provides access to the generic query runtime context of the current engine | ||
36 | * @since 1.7 | ||
37 | */ | ||
38 | IQueryRuntimeContext getRuntimeContext(); | ||
39 | |||
40 | /** | ||
41 | * Returns a matcher for a selected query specification. | ||
42 | * | ||
43 | * @throws ViatraQueryRuntimeException | ||
44 | * @since 1.5 | ||
45 | */ | ||
46 | IQueryResultProvider getMatcher(CallWithAdornment dependency); | ||
47 | |||
48 | /** | ||
49 | * Allows search operations to cache values through the entire lifecycle of the local search backend. The values are | ||
50 | * calculated if not cached before using the given provider, or returned from the cache accordingly. | ||
51 | * | ||
52 | * @since 1.7 | ||
53 | */ | ||
54 | <T> T accessBackendLevelCache(Object key, Class<? extends T> clazz, IProvider<T> valueProvider); | ||
55 | |||
56 | /** | ||
57 | * Returns the engine-specific logger | ||
58 | * | ||
59 | * @since 2.0 | ||
60 | */ | ||
61 | Logger getLogger(); | ||
62 | |||
63 | /** | ||
64 | * @noreference This class is not intended to be referenced by clients. | ||
65 | * @noimplement This interface is not intended to be implemented by clients. | ||
66 | * @noextend This interface is not intended to be extended by clients. | ||
67 | */ | ||
68 | public class SearchContext implements ISearchContext { | ||
69 | |||
70 | private final IQueryRuntimeContext runtimeContext; | ||
71 | |||
72 | private final ICache backendLevelCache; | ||
73 | private final Logger logger; | ||
74 | private final ResultProviderRequestor resultProviderRequestor; | ||
75 | |||
76 | /** | ||
77 | * Initializes a search context using an arbitrary backend context | ||
78 | */ | ||
79 | public SearchContext(IQueryBackendContext backendContext, ICache backendLevelCache, | ||
80 | ResultProviderRequestor resultProviderRequestor) { | ||
81 | this.resultProviderRequestor = resultProviderRequestor; | ||
82 | this.runtimeContext = backendContext.getRuntimeContext(); | ||
83 | this.logger = backendContext.getLogger(); | ||
84 | |||
85 | this.backendLevelCache = backendLevelCache; | ||
86 | } | ||
87 | |||
88 | /** | ||
89 | * @throws ViatraQueryRuntimeException | ||
90 | * @since 2.1 | ||
91 | */ | ||
92 | @Override | ||
93 | public IQueryResultProvider getMatcher(CallWithAdornment dependency) { | ||
94 | // Inject adornment for referenced pattern | ||
95 | IAdornmentProvider adornmentProvider = query -> { | ||
96 | if (query.equals(dependency.getReferredQuery())){ | ||
97 | return Collections.singleton(dependency.getAdornment()); | ||
98 | } | ||
99 | return Collections.emptySet(); | ||
100 | }; | ||
101 | return resultProviderRequestor.requestResultProvider(dependency.getCall(), | ||
102 | IAdornmentProvider.toHint(adornmentProvider)); | ||
103 | } | ||
104 | |||
105 | @Override | ||
106 | public <T> T accessBackendLevelCache(Object key, Class<? extends T> clazz, IProvider<T> valueProvider) { | ||
107 | return backendLevelCache.getValue(key, clazz, valueProvider); | ||
108 | } | ||
109 | |||
110 | public IQueryRuntimeContext getRuntimeContext() { | ||
111 | return runtimeContext; | ||
112 | } | ||
113 | |||
114 | @Override | ||
115 | public Logger getLogger() { | ||
116 | return logger; | ||
117 | } | ||
118 | |||
119 | } | ||
120 | } | ||
diff --git a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/LocalSearchMatcher.java b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/LocalSearchMatcher.java deleted file mode 100644 index e31d7b5c..00000000 --- a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/LocalSearchMatcher.java +++ /dev/null | |||
@@ -1,301 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2013, Zoltan Ujhelyi, Marton Bur, 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.localsearch.matcher; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.HashSet; | ||
13 | import java.util.Iterator; | ||
14 | import java.util.LinkedList; | ||
15 | import java.util.List; | ||
16 | import java.util.NoSuchElementException; | ||
17 | import java.util.Objects; | ||
18 | import java.util.Optional; | ||
19 | import java.util.Set; | ||
20 | import java.util.Spliterator; | ||
21 | import java.util.Spliterators; | ||
22 | import java.util.stream.Collectors; | ||
23 | import java.util.stream.Stream; | ||
24 | import java.util.stream.StreamSupport; | ||
25 | |||
26 | import tools.refinery.viatra.runtime.localsearch.MatchingFrame; | ||
27 | import tools.refinery.viatra.runtime.localsearch.plan.IPlanDescriptor; | ||
28 | import tools.refinery.viatra.runtime.localsearch.plan.SearchPlan; | ||
29 | import tools.refinery.viatra.runtime.localsearch.plan.SearchPlanExecutor; | ||
30 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
31 | import tools.refinery.viatra.runtime.matchers.tuple.ITuple; | ||
32 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
33 | import tools.refinery.viatra.runtime.matchers.tuple.TupleMask; | ||
34 | import tools.refinery.viatra.runtime.matchers.tuple.VolatileModifiableMaskedTuple; | ||
35 | import tools.refinery.viatra.runtime.matchers.util.Preconditions; | ||
36 | |||
37 | /** | ||
38 | * @author Zoltan Ujhelyi | ||
39 | * @noinstantiate This class is not intended to be instantiated by clients. | ||
40 | */ | ||
41 | public final class LocalSearchMatcher implements ILocalSearchAdaptable { | ||
42 | |||
43 | private final List<SearchPlanExecutor> plan; | ||
44 | private final IPlanDescriptor planDescriptor; | ||
45 | private final List<ILocalSearchAdapter> adapters; | ||
46 | |||
47 | /** | ||
48 | * @since 2.0 | ||
49 | */ | ||
50 | public List<SearchPlanExecutor> getPlan() { | ||
51 | return plan; | ||
52 | } | ||
53 | |||
54 | @Override | ||
55 | public List<ILocalSearchAdapter> getAdapters() { | ||
56 | return new ArrayList<>(adapters); | ||
57 | } | ||
58 | |||
59 | private abstract class PlanExecutionIterator implements Iterator<Tuple> { | ||
60 | |||
61 | protected final Iterator<SearchPlanExecutor> planIterator; | ||
62 | |||
63 | protected SearchPlanExecutor currentPlan; | ||
64 | protected MatchingFrame frame; | ||
65 | protected final Set<ITuple> matchSet; | ||
66 | protected VolatileModifiableMaskedTuple parametersOfFrameView; | ||
67 | private boolean isNextMatchCalculated; | ||
68 | |||
69 | public PlanExecutionIterator(final Iterator<SearchPlanExecutor> planIterator) { | ||
70 | this.planIterator = planIterator; | ||
71 | isNextMatchCalculated = false; | ||
72 | matchSet = new HashSet<>(); | ||
73 | } | ||
74 | |||
75 | protected boolean selectNextPlan() { | ||
76 | if(currentPlan != null) { | ||
77 | currentPlan.removeAdapters(adapters); | ||
78 | } | ||
79 | boolean validPlanSelected = false; | ||
80 | |||
81 | SearchPlanExecutor nextPlan = null; | ||
82 | |||
83 | while (!validPlanSelected && planIterator.hasNext()) { | ||
84 | nextPlan = planIterator.next(); | ||
85 | nextPlan.addAdapters(adapters); | ||
86 | nextPlan.resetPlan(); | ||
87 | |||
88 | validPlanSelected = initializeMatchingFrame(nextPlan); | ||
89 | } | ||
90 | |||
91 | if (validPlanSelected) { | ||
92 | for (ILocalSearchAdapter adapter : adapters) { | ||
93 | adapter.planChanged(Optional.ofNullable(currentPlan).map(SearchPlanExecutor::getSearchPlan), | ||
94 | Optional.ofNullable(nextPlan).map(SearchPlanExecutor::getSearchPlan)); | ||
95 | } | ||
96 | currentPlan = nextPlan; | ||
97 | return true; | ||
98 | } else { | ||
99 | currentPlan = null; | ||
100 | return false; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | protected abstract boolean initializeMatchingFrame(SearchPlanExecutor nextPlan); | ||
105 | |||
106 | private boolean findNextNewMatchInCurrentPlan() { | ||
107 | boolean foundMatch = currentPlan.execute(frame); | ||
108 | while (foundMatch && matchSet.contains(parametersOfFrameView)) { | ||
109 | for (ILocalSearchAdapter adapter : adapters) { | ||
110 | adapter.duplicateMatchFound(frame); | ||
111 | } | ||
112 | foundMatch = currentPlan.execute(frame); | ||
113 | } | ||
114 | return foundMatch; | ||
115 | } | ||
116 | |||
117 | @Override | ||
118 | public boolean hasNext() { | ||
119 | if (isNextMatchCalculated) { | ||
120 | return true; | ||
121 | } | ||
122 | if (currentPlan == null) { | ||
123 | return false; | ||
124 | } | ||
125 | boolean foundMatch = findNextNewMatchInCurrentPlan(); | ||
126 | |||
127 | while (!foundMatch && planIterator.hasNext()) { | ||
128 | foundMatch = selectNextPlan() && findNextNewMatchInCurrentPlan(); | ||
129 | } | ||
130 | if (!foundMatch) { | ||
131 | for (ILocalSearchAdapter adapter : adapters) { | ||
132 | adapter.noMoreMatchesAvailable(LocalSearchMatcher.this); | ||
133 | } | ||
134 | } | ||
135 | isNextMatchCalculated = foundMatch; | ||
136 | return foundMatch; | ||
137 | } | ||
138 | |||
139 | @Override | ||
140 | public Tuple next() { | ||
141 | if (!hasNext()) { | ||
142 | throw new NoSuchElementException("No more matches available."); | ||
143 | } | ||
144 | isNextMatchCalculated = false; | ||
145 | final Tuple match = parametersOfFrameView.toImmutable(); | ||
146 | matchSet.add(match); | ||
147 | return match; | ||
148 | } | ||
149 | } | ||
150 | |||
151 | private class PlanExecutionIteratorWithArrayParameters extends PlanExecutionIterator { | ||
152 | |||
153 | private final Object[] parameterValues; | ||
154 | |||
155 | public PlanExecutionIteratorWithArrayParameters(Iterator<SearchPlanExecutor> planIterator, final Object[] parameterValues) { | ||
156 | super(planIterator); | ||
157 | this.parameterValues = parameterValues; | ||
158 | selectNextPlan(); | ||
159 | } | ||
160 | |||
161 | protected boolean initializeMatchingFrame(SearchPlanExecutor nextPlan) { | ||
162 | frame = new MatchingFrame(nextPlan.getVariableMapping().size()); | ||
163 | parametersOfFrameView = new VolatileModifiableMaskedTuple(frame, nextPlan.getParameterMask()); | ||
164 | for (int i = 0; i < parameterValues.length; i++) { | ||
165 | Object valueToSet = parameterValues[i]; | ||
166 | if (valueToSet != null) { | ||
167 | Object oldValue = parametersOfFrameView.get(i); | ||
168 | if (oldValue == null) { | ||
169 | parametersOfFrameView.set(i, valueToSet); | ||
170 | } else if (!Objects.equals(valueToSet, oldValue)) { | ||
171 | // Initial value setting resulted in contradictory values. This can happen because two parameter | ||
172 | // variables have been unified but the call provides different values for the parameters. | ||
173 | return false; | ||
174 | } | ||
175 | // If oldValue is not null but equal to newValue, the setting can be ignored | ||
176 | } | ||
177 | } | ||
178 | |||
179 | return true; | ||
180 | } | ||
181 | } | ||
182 | private class PlanExecutionIteratorWithTupleParameters extends PlanExecutionIterator { | ||
183 | |||
184 | private final ITuple parameterValues; | ||
185 | private final TupleMask parameterSeedMask; | ||
186 | |||
187 | public PlanExecutionIteratorWithTupleParameters(Iterator<SearchPlanExecutor> planIterator, final TupleMask parameterSeedMask, final ITuple parameterValues) { | ||
188 | super(planIterator); | ||
189 | this.parameterSeedMask = parameterSeedMask; | ||
190 | this.parameterValues = parameterValues; | ||
191 | selectNextPlan(); | ||
192 | } | ||
193 | |||
194 | protected boolean initializeMatchingFrame(SearchPlanExecutor nextPlan) { | ||
195 | frame = new MatchingFrame(nextPlan.getVariableMapping().size()); | ||
196 | parametersOfFrameView = new VolatileModifiableMaskedTuple(frame, nextPlan.getParameterMask()); | ||
197 | for (int i = 0; i < parameterSeedMask.getSize(); i++) { | ||
198 | int index = parameterSeedMask.indices[i]; | ||
199 | Object valueToSet = parameterValues.get(i); | ||
200 | if (valueToSet != null) { | ||
201 | Object oldValue = parametersOfFrameView.get(index); | ||
202 | if (oldValue == null) { | ||
203 | parametersOfFrameView.set(index, valueToSet); | ||
204 | } else if (!Objects.equals(valueToSet, oldValue)) { | ||
205 | // Initial value setting resulted in contradictory values. This can happen because two parameter | ||
206 | // variables have been unified but the call provides different values for the parameters. | ||
207 | return false; | ||
208 | } | ||
209 | // If oldValue is not null but equal to newValue, the setting can be ignored | ||
210 | } | ||
211 | } | ||
212 | |||
213 | return true; | ||
214 | } | ||
215 | } | ||
216 | |||
217 | /** | ||
218 | * @since 2.0 | ||
219 | */ | ||
220 | public LocalSearchMatcher(ISearchContext searchContext, IPlanDescriptor planDescriptor, List<SearchPlan> plan) { | ||
221 | Preconditions.checkArgument(planDescriptor != null, "Cannot initialize matcher with null query."); | ||
222 | this.planDescriptor = planDescriptor; | ||
223 | this.plan = plan.stream().map(p -> new SearchPlanExecutor(p, searchContext)).collect(Collectors.toList()); | ||
224 | this.adapters = new LinkedList<>(); | ||
225 | } | ||
226 | |||
227 | @Override | ||
228 | public void addAdapter(ILocalSearchAdapter adapter) { | ||
229 | this.adapters.add(adapter); | ||
230 | adapter.adapterRegistered(this); | ||
231 | } | ||
232 | |||
233 | @Override | ||
234 | public void removeAdapter(ILocalSearchAdapter adapter) { | ||
235 | this.adapters.remove(adapter); | ||
236 | adapter.adapterUnregistered(this); | ||
237 | } | ||
238 | |||
239 | @Override | ||
240 | public void addAdapters(List<ILocalSearchAdapter> adapters) { | ||
241 | this.adapters.addAll(adapters); | ||
242 | for (ILocalSearchAdapter adapter : adapters) { | ||
243 | adapter.adapterRegistered(this); | ||
244 | } | ||
245 | } | ||
246 | |||
247 | @Override | ||
248 | public void removeAdapters(List<ILocalSearchAdapter> adapters) { | ||
249 | this.adapters.removeAll(adapters); | ||
250 | for (ILocalSearchAdapter adapter : adapters) { | ||
251 | adapter.adapterUnregistered(this); | ||
252 | } | ||
253 | } | ||
254 | |||
255 | public int getParameterCount() { | ||
256 | return planDescriptor.getQuery().getParameters().size(); | ||
257 | } | ||
258 | |||
259 | private void matchingStarted() { | ||
260 | for (ILocalSearchAdapter adapter : adapters) { | ||
261 | adapter.patternMatchingStarted(this); | ||
262 | } | ||
263 | } | ||
264 | |||
265 | /** | ||
266 | * @since 2.0 | ||
267 | */ | ||
268 | public Stream<Tuple> streamMatches(final Object[] parameterValues) { | ||
269 | matchingStarted(); | ||
270 | PlanExecutionIterator it = new PlanExecutionIteratorWithArrayParameters(plan.iterator(), parameterValues); | ||
271 | return StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, | ||
272 | Spliterator.IMMUTABLE | Spliterator.NONNULL | Spliterator.DISTINCT), false); | ||
273 | } | ||
274 | |||
275 | /** | ||
276 | * @since 2.0 | ||
277 | */ | ||
278 | public Stream<Tuple> streamMatches(TupleMask parameterSeedMask, final ITuple parameterValues) { | ||
279 | matchingStarted(); | ||
280 | PlanExecutionIterator it = new PlanExecutionIteratorWithTupleParameters( | ||
281 | plan.iterator(), parameterSeedMask, parameterValues); | ||
282 | return StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, | ||
283 | Spliterator.IMMUTABLE | Spliterator.NONNULL | Spliterator.DISTINCT), false); | ||
284 | } | ||
285 | |||
286 | /** | ||
287 | * Returns the query specification this matcher used as source for the implementation | ||
288 | * @return never null | ||
289 | */ | ||
290 | public PQuery getQuerySpecification() { | ||
291 | return planDescriptor.getQuery(); | ||
292 | } | ||
293 | |||
294 | |||
295 | /** | ||
296 | * @since 1.5 | ||
297 | */ | ||
298 | public IPlanDescriptor getPlanDescriptor() { | ||
299 | return planDescriptor; | ||
300 | } | ||
301 | } | ||
diff --git a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/MatcherReference.java b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/MatcherReference.java deleted file mode 100644 index 6bf25192..00000000 --- a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/MatcherReference.java +++ /dev/null | |||
@@ -1,97 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Zoltan Ujhelyi, Marton Bur, 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.localsearch.matcher; | ||
10 | |||
11 | import java.util.Set; | ||
12 | |||
13 | import tools.refinery.viatra.runtime.matchers.backend.QueryEvaluationHint; | ||
14 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PParameter; | ||
15 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
16 | |||
17 | public class MatcherReference { | ||
18 | final PQuery query; | ||
19 | final Set<PParameter> adornment; | ||
20 | |||
21 | /** | ||
22 | * Hints that can override the callee's own hints. This field is intentionally left out from hashCode and equals | ||
23 | */ | ||
24 | final QueryEvaluationHint hints; | ||
25 | |||
26 | /** | ||
27 | * @since 1.4 | ||
28 | */ | ||
29 | public MatcherReference(PQuery query, Set<PParameter> adornment, QueryEvaluationHint hints) { | ||
30 | super(); | ||
31 | this.query = query; | ||
32 | this.adornment = adornment; | ||
33 | this.hints = hints; | ||
34 | } | ||
35 | |||
36 | public MatcherReference(PQuery query, Set<PParameter> adornment){ | ||
37 | this(query, adornment, null); | ||
38 | } | ||
39 | |||
40 | public PQuery getQuery() { | ||
41 | return query; | ||
42 | } | ||
43 | public Set<PParameter> getAdornment() { | ||
44 | return adornment; | ||
45 | } | ||
46 | @Override | ||
47 | public int hashCode() { | ||
48 | final int prime = 31; | ||
49 | int result = 1; | ||
50 | |||
51 | result = prime * result + ((adornment == null) ? 0 : adornment.hashCode()); | ||
52 | result = prime * result + ((query == null) ? 0 : query.hashCode()); | ||
53 | return result; | ||
54 | } | ||
55 | @Override | ||
56 | public boolean equals(Object obj) { | ||
57 | if (this == obj) | ||
58 | return true; | ||
59 | if (obj == null) | ||
60 | return false; | ||
61 | if (getClass() != obj.getClass()) | ||
62 | return false; | ||
63 | MatcherReference other = (MatcherReference) obj; | ||
64 | if (adornment == null) { | ||
65 | if (other.adornment != null) | ||
66 | return false; | ||
67 | } else if (!adornment.equals(other.adornment)) | ||
68 | return false; | ||
69 | if (query == null) { | ||
70 | if (other.query != null) | ||
71 | return false; | ||
72 | } else if (!query.equals(other.query)) | ||
73 | return false; | ||
74 | return true; | ||
75 | } | ||
76 | |||
77 | /** | ||
78 | * @return the hints to override the called reference's own hints with. Can be null. | ||
79 | * @since 1.4 | ||
80 | */ | ||
81 | public QueryEvaluationHint getHints() { | ||
82 | return hints; | ||
83 | } | ||
84 | |||
85 | @Override | ||
86 | public String toString() { | ||
87 | StringBuilder sb = new StringBuilder(); | ||
88 | sb.append(query.getFullyQualifiedName()); | ||
89 | sb.append("("); | ||
90 | for(PParameter p : query.getParameters()){ | ||
91 | sb.append(adornment.contains(p) ? "b" : "f"); | ||
92 | } | ||
93 | sb.append(")"); | ||
94 | return sb.toString(); | ||
95 | } | ||
96 | |||
97 | } \ No newline at end of file | ||
diff --git a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/AbstractLocalSearchResultProvider.java b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/AbstractLocalSearchResultProvider.java deleted file mode 100644 index 1ae24d2d..00000000 --- a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/AbstractLocalSearchResultProvider.java +++ /dev/null | |||
@@ -1,532 +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.localsearch.matcher.integration; | ||
10 | |||
11 | import java.lang.reflect.InvocationTargetException; | ||
12 | import java.util.ArrayList; | ||
13 | import java.util.Collection; | ||
14 | import java.util.Collections; | ||
15 | import java.util.HashMap; | ||
16 | import java.util.HashSet; | ||
17 | import java.util.LinkedHashSet; | ||
18 | import java.util.LinkedList; | ||
19 | import java.util.List; | ||
20 | import java.util.Map; | ||
21 | import java.util.Objects; | ||
22 | import java.util.Optional; | ||
23 | import java.util.Queue; | ||
24 | import java.util.Set; | ||
25 | import java.util.concurrent.Callable; | ||
26 | import java.util.stream.Collectors; | ||
27 | import java.util.stream.IntStream; | ||
28 | import java.util.stream.Stream; | ||
29 | |||
30 | import tools.refinery.viatra.runtime.localsearch.exceptions.LocalSearchException; | ||
31 | import tools.refinery.viatra.runtime.localsearch.matcher.CallWithAdornment; | ||
32 | import tools.refinery.viatra.runtime.localsearch.matcher.ISearchContext; | ||
33 | import tools.refinery.viatra.runtime.localsearch.matcher.LocalSearchMatcher; | ||
34 | import tools.refinery.viatra.runtime.localsearch.matcher.MatcherReference; | ||
35 | import tools.refinery.viatra.runtime.localsearch.plan.IPlanDescriptor; | ||
36 | import tools.refinery.viatra.runtime.localsearch.plan.IPlanProvider; | ||
37 | import tools.refinery.viatra.runtime.localsearch.plan.SearchPlan; | ||
38 | import tools.refinery.viatra.runtime.localsearch.plan.SearchPlanForBody; | ||
39 | import tools.refinery.viatra.runtime.localsearch.planner.compiler.IOperationCompiler; | ||
40 | import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException; | ||
41 | import tools.refinery.viatra.runtime.matchers.backend.IMatcherCapability; | ||
42 | import tools.refinery.viatra.runtime.matchers.backend.IQueryBackend; | ||
43 | import tools.refinery.viatra.runtime.matchers.backend.IQueryResultProvider; | ||
44 | import tools.refinery.viatra.runtime.matchers.backend.IUpdateable; | ||
45 | import tools.refinery.viatra.runtime.matchers.backend.QueryEvaluationHint; | ||
46 | import tools.refinery.viatra.runtime.matchers.backend.QueryHintOption; | ||
47 | import tools.refinery.viatra.runtime.matchers.backend.ResultProviderRequestor; | ||
48 | import tools.refinery.viatra.runtime.matchers.context.IInputKey; | ||
49 | import tools.refinery.viatra.runtime.matchers.context.IQueryBackendContext; | ||
50 | import tools.refinery.viatra.runtime.matchers.context.IQueryRuntimeContext; | ||
51 | import tools.refinery.viatra.runtime.matchers.context.IndexingService; | ||
52 | import tools.refinery.viatra.runtime.matchers.planning.QueryProcessingException; | ||
53 | import tools.refinery.viatra.runtime.matchers.planning.helpers.FunctionalDependencyHelper; | ||
54 | import tools.refinery.viatra.runtime.matchers.psystem.IQueryReference; | ||
55 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
56 | import tools.refinery.viatra.runtime.matchers.psystem.basicenumerables.PositivePatternCall; | ||
57 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PParameter; | ||
58 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQueries; | ||
59 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
60 | import tools.refinery.viatra.runtime.matchers.psystem.rewriters.IFlattenCallPredicate; | ||
61 | import tools.refinery.viatra.runtime.matchers.tuple.ITuple; | ||
62 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
63 | import tools.refinery.viatra.runtime.matchers.tuple.TupleMask; | ||
64 | import tools.refinery.viatra.runtime.matchers.util.Accuracy; | ||
65 | |||
66 | /** | ||
67 | * @author Zoltan Ujhelyi | ||
68 | * @since 1.7 | ||
69 | * | ||
70 | */ | ||
71 | public abstract class AbstractLocalSearchResultProvider implements IQueryResultProvider { | ||
72 | |||
73 | protected final LocalSearchBackend backend; | ||
74 | protected final IQueryBackendContext backendContext; | ||
75 | protected final IQueryRuntimeContext runtimeContext; | ||
76 | protected final PQuery query; | ||
77 | protected final QueryEvaluationHint userHints; | ||
78 | protected final Map<PQuery, LocalSearchHints> hintCache = new HashMap<>(); | ||
79 | protected final IPlanProvider planProvider; | ||
80 | private static final String PLAN_CACHE_KEY = AbstractLocalSearchResultProvider.class.getName() + "#planCache"; | ||
81 | private final Map<MatcherReference, IPlanDescriptor> planCache; | ||
82 | protected final ISearchContext searchContext; | ||
83 | /** | ||
84 | * @since 2.1 | ||
85 | */ | ||
86 | protected ResultProviderRequestor resultProviderRequestor; | ||
87 | |||
88 | /** | ||
89 | * @since 1.5 | ||
90 | */ | ||
91 | @SuppressWarnings({ "unchecked"}) | ||
92 | public AbstractLocalSearchResultProvider(LocalSearchBackend backend, IQueryBackendContext context, PQuery query, | ||
93 | IPlanProvider planProvider, QueryEvaluationHint userHints) { | ||
94 | this.backend = backend; | ||
95 | this.backendContext = context; | ||
96 | this.query = query; | ||
97 | |||
98 | this.planProvider = planProvider; | ||
99 | this.userHints = userHints; | ||
100 | this.runtimeContext = context.getRuntimeContext(); | ||
101 | this.resultProviderRequestor = backend.getResultProviderRequestor(query, userHints); | ||
102 | this.searchContext = new ISearchContext.SearchContext(backendContext, backend.getCache(), resultProviderRequestor); | ||
103 | this.planCache = backend.getCache().getValue(PLAN_CACHE_KEY, Map.class, HashMap::new); | ||
104 | } | ||
105 | |||
106 | protected abstract IOperationCompiler getOperationCompiler(IQueryBackendContext backendContext, LocalSearchHints configuration); | ||
107 | |||
108 | private IQueryRuntimeContext getRuntimeContext() { | ||
109 | return backend.getRuntimeContext(); | ||
110 | } | ||
111 | |||
112 | private LocalSearchMatcher createMatcher(IPlanDescriptor plan, final ISearchContext searchContext) { | ||
113 | List<SearchPlan> executors = plan.getPlan().stream() | ||
114 | .map(input -> new SearchPlan(input.getBody(), input.getCompiledOperations(), input.calculateParameterMask(), | ||
115 | input.getVariableKeys())) | ||
116 | .collect(Collectors.toList()); | ||
117 | return new LocalSearchMatcher(searchContext, plan, executors); | ||
118 | } | ||
119 | |||
120 | private IPlanDescriptor getOrCreatePlan(MatcherReference key, IQueryBackendContext backendContext, IOperationCompiler compiler, LocalSearchHints configuration, IPlanProvider planProvider) { | ||
121 | if (planCache.containsKey(key)){ | ||
122 | return planCache.get(key); | ||
123 | } else { | ||
124 | IPlanDescriptor plan = planProvider.getPlan(backendContext, compiler, | ||
125 | resultProviderRequestor, configuration, key); | ||
126 | planCache.put(key, plan); | ||
127 | return plan; | ||
128 | } | ||
129 | } | ||
130 | |||
131 | private IPlanDescriptor getOrCreatePlan(MatcherReference key, IPlanProvider planProvider) { | ||
132 | if (planCache.containsKey(key)){ | ||
133 | return planCache.get(key); | ||
134 | } else { | ||
135 | LocalSearchHints configuration = overrideDefaultHints(key.getQuery()); | ||
136 | IOperationCompiler compiler = getOperationCompiler(backendContext, configuration); | ||
137 | IPlanDescriptor plan = planProvider.getPlan(backendContext, compiler, | ||
138 | resultProviderRequestor, configuration, key); | ||
139 | planCache.put(key, plan); | ||
140 | return plan; | ||
141 | } | ||
142 | } | ||
143 | |||
144 | private LocalSearchHints overrideDefaultHints(PQuery pQuery) { | ||
145 | if (hintCache.containsKey(pQuery)) { | ||
146 | return hintCache.get(pQuery); | ||
147 | } else { | ||
148 | LocalSearchHints hint = LocalSearchHints.getDefaultOverriddenBy( | ||
149 | computeOverridingHints(pQuery)); | ||
150 | hintCache.put(pQuery, hint); | ||
151 | return hint; | ||
152 | } | ||
153 | } | ||
154 | |||
155 | /** | ||
156 | * Combine with {@link QueryHintOption#getValueOrDefault(QueryEvaluationHint)} to access | ||
157 | * hint settings not covered by {@link LocalSearchHints} | ||
158 | */ | ||
159 | private QueryEvaluationHint computeOverridingHints(PQuery pQuery) { | ||
160 | return backendContext.getHintProvider().getQueryEvaluationHint(pQuery).overrideBy(userHints); | ||
161 | } | ||
162 | |||
163 | /** | ||
164 | * Prepare this result provider. This phase is separated from the constructor to allow the backend to cache its instance before | ||
165 | * requesting preparation for its dependencies. | ||
166 | * @since 1.5 | ||
167 | */ | ||
168 | public void prepare() { | ||
169 | try { | ||
170 | runtimeContext.coalesceTraversals(() -> { | ||
171 | LocalSearchHints configuration = overrideDefaultHints(query); | ||
172 | if (configuration.isUseBase()) { | ||
173 | indexInitializationBeforePlanning(); | ||
174 | } | ||
175 | prepareDirectDependencies(); | ||
176 | runtimeContext.executeAfterTraversal(AbstractLocalSearchResultProvider.this::preparePlansForExpectedAdornments); | ||
177 | return null; | ||
178 | }); | ||
179 | } catch (InvocationTargetException e) { | ||
180 | throw new QueryProcessingException("Error while building required indexes: {1}", new String[]{e.getTargetException().getMessage()}, "Error while building required indexes.", query, e); | ||
181 | } | ||
182 | } | ||
183 | |||
184 | protected void preparePlansForExpectedAdornments() { | ||
185 | // Plan for possible adornments | ||
186 | for (Set<PParameter> adornment : overrideDefaultHints(query).getAdornmentProvider().getAdornments(query)) { | ||
187 | MatcherReference reference = new MatcherReference(query, adornment, userHints); | ||
188 | LocalSearchHints configuration = overrideDefaultHints(query); | ||
189 | IOperationCompiler compiler = getOperationCompiler(backendContext, configuration); | ||
190 | IPlanDescriptor plan = getOrCreatePlan(reference, backendContext, compiler, configuration, planProvider); | ||
191 | // Index keys | ||
192 | try { | ||
193 | if (configuration.isUseBase()) { | ||
194 | indexKeys(plan.getIteratedKeys()); | ||
195 | } | ||
196 | } catch (InvocationTargetException e) { | ||
197 | throw new QueryProcessingException(e.getMessage(), null, e.getMessage(), query, e); | ||
198 | } | ||
199 | //Prepare dependencies | ||
200 | for(SearchPlanForBody body: plan.getPlan()){ | ||
201 | for(CallWithAdornment dependency : body.getDependencies()){ | ||
202 | searchContext.getMatcher(dependency); | ||
203 | } | ||
204 | } | ||
205 | } | ||
206 | } | ||
207 | |||
208 | protected void prepareDirectDependencies() { | ||
209 | // Do not prepare for any adornment at this point | ||
210 | IAdornmentProvider adornmentProvider = input -> Collections.emptySet(); | ||
211 | QueryEvaluationHint adornmentHint = IAdornmentProvider.toHint(adornmentProvider); | ||
212 | |||
213 | for(IQueryReference call : getDirectDependencies()){ | ||
214 | resultProviderRequestor.requestResultProvider(call, adornmentHint); | ||
215 | } | ||
216 | } | ||
217 | |||
218 | /** | ||
219 | * This method is called before planning start to allow indexing. It is important to note that this method is called | ||
220 | * inside a coalesceTraversals block, meaning (1) it is safe to add multiple registration requests as necessary, but | ||
221 | * (2) no value or statistics is available from the index. | ||
222 | * | ||
223 | * @throws ViatraQueryRuntimeException | ||
224 | */ | ||
225 | protected void indexInitializationBeforePlanning() { | ||
226 | // By default, no indexing is necessary | ||
227 | } | ||
228 | |||
229 | /** | ||
230 | * Collects and indexes all types _directly_ referred by the PQuery {@link #query}. Types indirect | ||
231 | * @param requiredIndexingServices | ||
232 | */ | ||
233 | protected void indexReferredTypesOfQuery(PQuery query, IndexingService requiredIndexingServices) { | ||
234 | PQueries.directlyRequiredTypesOfQuery(query, true /*only enumerables are considered for indexing */).forEach( | ||
235 | inputKey -> runtimeContext.ensureIndexed(inputKey, requiredIndexingServices) | ||
236 | ); | ||
237 | } | ||
238 | |||
239 | private Set<IQueryReference> getDirectDependencies() { | ||
240 | IFlattenCallPredicate flattenPredicate = overrideDefaultHints(query).getFlattenCallPredicate(); | ||
241 | Queue<PQuery> queue = new LinkedList<>(); | ||
242 | Set<PQuery> visited = new HashSet<>(); | ||
243 | Set<IQueryReference> result = new HashSet<>(); | ||
244 | queue.add(query); | ||
245 | |||
246 | while(!queue.isEmpty()){ | ||
247 | PQuery next = queue.poll(); | ||
248 | visited.add(next); | ||
249 | for(PBody body : next.getDisjunctBodies().getBodies()){ | ||
250 | for (IQueryReference call : body.getConstraintsOfType(IQueryReference.class)) { | ||
251 | if (call instanceof PositivePatternCall && | ||
252 | flattenPredicate.shouldFlatten((PositivePatternCall) call)) | ||
253 | { | ||
254 | PQuery dep = ((PositivePatternCall) call).getReferredQuery(); | ||
255 | if (!visited.contains(dep)){ | ||
256 | queue.add(dep); | ||
257 | } | ||
258 | } else { | ||
259 | result.add(call); | ||
260 | } | ||
261 | } | ||
262 | } | ||
263 | } | ||
264 | return result; | ||
265 | } | ||
266 | |||
267 | private LocalSearchMatcher initializeMatcher(Object[] parameters) { | ||
268 | return newLocalSearchMatcher(parameters); | ||
269 | } | ||
270 | |||
271 | private LocalSearchMatcher initializeMatcher(TupleMask parameterSeedMask) { | ||
272 | return newLocalSearchMatcher(parameterSeedMask.transformUnique(query.getParameters())); | ||
273 | |||
274 | } | ||
275 | |||
276 | |||
277 | /** | ||
278 | * @throws ViatraQueryRuntimeException | ||
279 | */ | ||
280 | public LocalSearchMatcher newLocalSearchMatcher(ITuple parameters) { | ||
281 | final Set<PParameter> adornment = new HashSet<>(); | ||
282 | for (int i = 0; i < parameters.getSize(); i++) { | ||
283 | if (parameters.get(i) != null) { | ||
284 | adornment.add(query.getParameters().get(i)); | ||
285 | } | ||
286 | } | ||
287 | |||
288 | return newLocalSearchMatcher(adornment); | ||
289 | } | ||
290 | |||
291 | /** | ||
292 | * @throws ViatraQueryRuntimeException | ||
293 | */ | ||
294 | public LocalSearchMatcher newLocalSearchMatcher(Object[] parameters) { | ||
295 | final Set<PParameter> adornment = new HashSet<>(); | ||
296 | for (int i = 0; i < parameters.length; i++) { | ||
297 | if (parameters[i] != null) { | ||
298 | adornment.add(query.getParameters().get(i)); | ||
299 | } | ||
300 | } | ||
301 | |||
302 | return newLocalSearchMatcher(adornment); | ||
303 | } | ||
304 | |||
305 | private LocalSearchMatcher newLocalSearchMatcher(final Set<PParameter> adornment) { | ||
306 | final MatcherReference reference = new MatcherReference(query, adornment, userHints); | ||
307 | |||
308 | IPlanDescriptor plan = getOrCreatePlan(reference, planProvider); | ||
309 | if (overrideDefaultHints(reference.getQuery()).isUseBase()){ | ||
310 | try { | ||
311 | indexKeys(plan.getIteratedKeys()); | ||
312 | } catch (InvocationTargetException e) { | ||
313 | throw new LocalSearchException("Could not index keys", e); | ||
314 | } | ||
315 | } | ||
316 | |||
317 | LocalSearchMatcher matcher = createMatcher(plan, searchContext); | ||
318 | matcher.addAdapters(backend.getAdapters()); | ||
319 | return matcher; | ||
320 | } | ||
321 | |||
322 | private void indexKeys(final Iterable<IInputKey> keys) throws InvocationTargetException { | ||
323 | final IQueryRuntimeContext qrc = getRuntimeContext(); | ||
324 | qrc.coalesceTraversals(new Callable<Void>() { | ||
325 | |||
326 | @Override | ||
327 | public Void call() throws Exception { | ||
328 | for(IInputKey key : keys){ | ||
329 | if (key.isEnumerable()) { | ||
330 | qrc.ensureIndexed(key, IndexingService.INSTANCES); | ||
331 | } | ||
332 | } | ||
333 | return null; | ||
334 | } | ||
335 | }); | ||
336 | } | ||
337 | |||
338 | @Override | ||
339 | public boolean hasMatch(Object[] parameters) { | ||
340 | final LocalSearchMatcher matcher = initializeMatcher(parameters); | ||
341 | return matcher.streamMatches(parameters).findAny().isPresent(); | ||
342 | } | ||
343 | |||
344 | @Override | ||
345 | public boolean hasMatch(TupleMask parameterSeedMask, ITuple parameters) { | ||
346 | final LocalSearchMatcher matcher = initializeMatcher(parameterSeedMask); | ||
347 | return matcher.streamMatches(parameterSeedMask, parameters).findAny().isPresent(); | ||
348 | } | ||
349 | |||
350 | @Override | ||
351 | public Optional<Tuple> getOneArbitraryMatch(Object[] parameters) { | ||
352 | final LocalSearchMatcher matcher = initializeMatcher(parameters); | ||
353 | return matcher.streamMatches(parameters).findAny(); | ||
354 | } | ||
355 | |||
356 | @Override | ||
357 | public Optional<Tuple> getOneArbitraryMatch(TupleMask parameterSeedMask, ITuple parameters) { | ||
358 | final LocalSearchMatcher matcher = initializeMatcher(parameterSeedMask); | ||
359 | return matcher.streamMatches(parameterSeedMask, parameters).findAny(); | ||
360 | } | ||
361 | |||
362 | @Override | ||
363 | public int countMatches(Object[] parameters) { | ||
364 | final LocalSearchMatcher matcher = initializeMatcher(parameters); | ||
365 | // Count returns long; casting to int - in case of integer overflow casting will throw the exception | ||
366 | return (int) matcher.streamMatches(parameters).count(); | ||
367 | } | ||
368 | |||
369 | @Override | ||
370 | public int countMatches(TupleMask parameterSeedMask, ITuple parameters) { | ||
371 | final LocalSearchMatcher matcher = initializeMatcher(parameterSeedMask); | ||
372 | // Count returns long; casting to int - in case of integer overflow casting will throw the exception | ||
373 | return (int) matcher.streamMatches(parameterSeedMask, parameters).count(); | ||
374 | } | ||
375 | |||
376 | private static final double ESTIMATE_CEILING = Long.MAX_VALUE / 16.0; | ||
377 | |||
378 | @Override | ||
379 | public Optional<Long> estimateCardinality(TupleMask groupMask, Accuracy requiredAccuracy) { | ||
380 | if (Accuracy.BEST_UPPER_BOUND.atLeastAsPreciseAs(requiredAccuracy)) { // approximate using parameter types | ||
381 | final List<PParameter> parameters = query.getParameters(); | ||
382 | final Map<Set<Integer>, Set<Integer>> dependencies = backendContext.getQueryAnalyzer() | ||
383 | .getProjectedFunctionalDependencies(query, false); | ||
384 | |||
385 | List<Integer> projectionIndices = groupMask.getIndicesAsList(); | ||
386 | |||
387 | return estimateParameterCombinations(requiredAccuracy, parameters, dependencies, | ||
388 | projectionIndices, | ||
389 | Collections.emptySet() /* No parameters with fixed value */).map(Double::longValue); | ||
390 | } | ||
391 | else return Optional.empty(); | ||
392 | } | ||
393 | |||
394 | @Override | ||
395 | public Optional<Double> estimateAverageBucketSize(TupleMask groupMask, Accuracy requiredAccuracy) { | ||
396 | if (Accuracy.BEST_UPPER_BOUND.atLeastAsPreciseAs(requiredAccuracy)) { // approximate using parameter types | ||
397 | final List<PParameter> parameters = query.getParameters(); | ||
398 | final Map<Set<Integer>, Set<Integer>> dependencies = backendContext.getQueryAnalyzer() | ||
399 | .getProjectedFunctionalDependencies(query, false); | ||
400 | |||
401 | // all parameters used for the estimation - determinized order | ||
402 | final List<Integer> allParameterIndices = | ||
403 | IntStream.range(0, parameters.size()).boxed().collect(Collectors.toList()); | ||
404 | |||
405 | // some free parameters are functionally determined by bound parameters | ||
406 | final Set<Integer> boundOrImplied = FunctionalDependencyHelper.closureOf(groupMask.getIndicesAsList(), | ||
407 | dependencies); | ||
408 | |||
409 | return estimateParameterCombinations(requiredAccuracy, parameters, dependencies, | ||
410 | allParameterIndices, | ||
411 | boundOrImplied); | ||
412 | } | ||
413 | else return Optional.empty(); | ||
414 | } | ||
415 | |||
416 | /** | ||
417 | * @since 2.1 | ||
418 | * @noreference This method is not intended to be referenced by clients. | ||
419 | */ | ||
420 | public double estimateCost(TupleMask inputBindingMask) { | ||
421 | // TODO this is currently an abstract cost, not really a branching factor | ||
422 | |||
423 | HashSet<PParameter> adornment = new HashSet<>(inputBindingMask.transform(query.getParameters())); | ||
424 | final MatcherReference reference = new MatcherReference(query, adornment, userHints); | ||
425 | IPlanDescriptor plan = getOrCreatePlan(reference, planProvider); | ||
426 | |||
427 | return plan.getPlan().stream().mapToDouble(SearchPlanForBody::getCost).sum(); | ||
428 | } | ||
429 | |||
430 | /** | ||
431 | * Approximates using parameter types | ||
432 | */ | ||
433 | private Optional<Double> estimateParameterCombinations( | ||
434 | Accuracy requiredAccuracy, | ||
435 | final List<PParameter> parameters, | ||
436 | final Map<Set<Integer>, Set<Integer>> functionalDependencies, | ||
437 | final Collection<Integer> parameterIndicesToEstimate, | ||
438 | final Set<Integer> otherDeterminingIndices) | ||
439 | { | ||
440 | // keep order deterministic | ||
441 | LinkedHashSet<Integer> freeParameterIndices = new LinkedHashSet<>(parameterIndicesToEstimate); | ||
442 | |||
443 | // determining indices are bound | ||
444 | freeParameterIndices.removeAll(otherDeterminingIndices); | ||
445 | |||
446 | // some free parameters are functionally determined by other free parameters | ||
447 | for (Integer candidateForRemoval : new ArrayList<>(freeParameterIndices)) { | ||
448 | List<Integer> others = Stream.concat( | ||
449 | otherDeterminingIndices.stream(), | ||
450 | freeParameterIndices.stream().filter(index -> !Objects.equals(index, candidateForRemoval)) | ||
451 | ).collect(Collectors.toList()); | ||
452 | Set<Integer> othersClosure = FunctionalDependencyHelper.closureOf(others, functionalDependencies); | ||
453 | if (othersClosure.contains(candidateForRemoval)) { | ||
454 | // other parameters functionally determine this mone, does not count towards estimate | ||
455 | freeParameterIndices.remove(candidateForRemoval); | ||
456 | } | ||
457 | } | ||
458 | |||
459 | |||
460 | Optional<Double> result = Optional.of(1.0); | ||
461 | // TODO this is currently works with declared types only. For better results, information from | ||
462 | // the Type inferrer should be included in the PSystem | ||
463 | for (int i = 0; (i < parameters.size()); i++) { | ||
464 | final IInputKey type = parameters.get(i).getDeclaredUnaryType(); | ||
465 | if (freeParameterIndices.contains(i) && type != null) { | ||
466 | result = result.flatMap(accumulator -> | ||
467 | runtimeContext.estimateCardinality(type, TupleMask.identity(1), requiredAccuracy).map(multiplier -> | ||
468 | Math.min(accumulator * multiplier, ESTIMATE_CEILING /* avoid overflow */) | ||
469 | )); | ||
470 | } | ||
471 | } | ||
472 | // TODO better approximate cardinality based on plan, branching factors, etc. | ||
473 | return result; | ||
474 | } | ||
475 | |||
476 | |||
477 | @Override | ||
478 | public Stream<Tuple> getAllMatches(Object[] parameters) { | ||
479 | final LocalSearchMatcher matcher = initializeMatcher(parameters); | ||
480 | return matcher.streamMatches(parameters); | ||
481 | } | ||
482 | |||
483 | @Override | ||
484 | public Stream<Tuple> getAllMatches(TupleMask parameterSeedMask, ITuple parameters) { | ||
485 | final LocalSearchMatcher matcher = initializeMatcher(parameterSeedMask); | ||
486 | return matcher.streamMatches(parameterSeedMask, parameters); | ||
487 | } | ||
488 | |||
489 | @Override | ||
490 | public IQueryBackend getQueryBackend() { | ||
491 | return backend; | ||
492 | } | ||
493 | |||
494 | @Override | ||
495 | public void addUpdateListener(IUpdateable listener, Object listenerTag, boolean fireNow) { | ||
496 | // throw new UnsupportedOperationException(UPDATE_LISTENER_NOT_SUPPORTED); | ||
497 | } | ||
498 | |||
499 | @Override | ||
500 | public void removeUpdateListener(Object listenerTag) { | ||
501 | // throw new UnsupportedOperationException(UPDATE_LISTENER_NOT_SUPPORTED); | ||
502 | } | ||
503 | |||
504 | /** | ||
505 | * @since 1.4 | ||
506 | */ | ||
507 | public IMatcherCapability getCapabilites() { | ||
508 | LocalSearchHints configuration = overrideDefaultHints(query); | ||
509 | return configuration; | ||
510 | } | ||
511 | |||
512 | /** | ||
513 | * Forgets all stored plans in this result provider. If no plans are stored, nothing happens. | ||
514 | * | ||
515 | * @since 2.0 | ||
516 | * @noreference This method is not intended to be referenced by clients; it should only used by {@link LocalSearchBackend}. | ||
517 | */ | ||
518 | public void forgetAllPlans() { | ||
519 | planCache.clear(); | ||
520 | } | ||
521 | |||
522 | /** | ||
523 | * Returns a search plan for a given adornment if exists | ||
524 | * | ||
525 | * @return a search plan for the pattern with the given adornment, or null if none exists | ||
526 | * @since 2.0 | ||
527 | * @noreference This method is not intended to be referenced by clients; it should only used by {@link LocalSearchBackend}. | ||
528 | */ | ||
529 | public IPlanDescriptor getSearchPlan(Set<PParameter> adornment) { | ||
530 | return planCache.get(new MatcherReference(query, adornment)); | ||
531 | } | ||
532 | } \ No newline at end of file | ||
diff --git a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/AllValidAdornments.java b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/AllValidAdornments.java deleted file mode 100644 index f801163e..00000000 --- a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/AllValidAdornments.java +++ /dev/null | |||
@@ -1,37 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Grill Balázs, 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.localsearch.matcher.integration; | ||
10 | |||
11 | import java.util.Set; | ||
12 | import java.util.stream.Collectors; | ||
13 | |||
14 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PParameter; | ||
15 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PParameterDirection; | ||
16 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQueries; | ||
17 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
18 | import tools.refinery.viatra.runtime.matchers.util.Sets; | ||
19 | |||
20 | |||
21 | /** | ||
22 | * This implementation calculates all valid adornments for the given query, respecting the parameter direction constraints. | ||
23 | * | ||
24 | * @author Grill Balázs | ||
25 | * @since 1.5 | ||
26 | */ | ||
27 | public class AllValidAdornments implements IAdornmentProvider { | ||
28 | |||
29 | @Override | ||
30 | public Iterable<Set<PParameter>> getAdornments(PQuery query) { | ||
31 | final Set<PParameter> ins = query.getParameters().stream().filter(PQueries.parameterDirectionPredicate(PParameterDirection.IN)).collect(Collectors.toSet()); | ||
32 | Set<PParameter> inouts = query.getParameters().stream().filter(PQueries.parameterDirectionPredicate(PParameterDirection.INOUT)).collect(Collectors.toSet()); | ||
33 | Set<? extends Set<PParameter>> possibleInouts = Sets.powerSet(inouts); | ||
34 | return possibleInouts.stream().map(input -> Sets.union(ins, input)).collect(Collectors.toSet()); | ||
35 | } | ||
36 | |||
37 | } | ||
diff --git a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/DontFlattenDisjunctive.java b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/DontFlattenDisjunctive.java deleted file mode 100644 index bf1b61b5..00000000 --- a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/DontFlattenDisjunctive.java +++ /dev/null | |||
@@ -1,29 +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.localsearch.matcher.integration; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.matchers.psystem.basicenumerables.PositivePatternCall; | ||
12 | import tools.refinery.viatra.runtime.matchers.psystem.rewriters.IFlattenCallPredicate; | ||
13 | |||
14 | /** | ||
15 | * Forbids flattening of patterns that have more than one body. | ||
16 | * | ||
17 | * @since 2.1 | ||
18 | |||
19 | * @author Gabor Bergmann | ||
20 | * | ||
21 | */ | ||
22 | public class DontFlattenDisjunctive implements IFlattenCallPredicate { | ||
23 | |||
24 | @Override | ||
25 | public boolean shouldFlatten(PositivePatternCall positivePatternCall) { | ||
26 | return 1 >= positivePatternCall.getReferredQuery().getDisjunctBodies().getBodies().size(); | ||
27 | } | ||
28 | |||
29 | } | ||
diff --git a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/DontFlattenIncrementalPredicate.java b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/DontFlattenIncrementalPredicate.java deleted file mode 100644 index 1b918528..00000000 --- a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/DontFlattenIncrementalPredicate.java +++ /dev/null | |||
@@ -1,44 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Grill Balázs, 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.localsearch.matcher.integration; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.matchers.backend.QueryEvaluationHint; | ||
12 | import tools.refinery.viatra.runtime.matchers.backend.QueryEvaluationHint.BackendRequirement; | ||
13 | import tools.refinery.viatra.runtime.matchers.psystem.basicenumerables.PositivePatternCall; | ||
14 | import tools.refinery.viatra.runtime.matchers.psystem.rewriters.IFlattenCallPredicate; | ||
15 | |||
16 | /** | ||
17 | * This implementation forbids flattening of patterns marked to be executed with a caching / incremental backend. | ||
18 | * This makes is possible for the user to configure hybrid matching via using | ||
19 | * the 'search' and 'incremental keywords in the pattern definition file. | ||
20 | * | ||
21 | * @since 1.5 | ||
22 | * | ||
23 | */ | ||
24 | public class DontFlattenIncrementalPredicate implements IFlattenCallPredicate { | ||
25 | |||
26 | @Override | ||
27 | public boolean shouldFlatten(PositivePatternCall positivePatternCall) { | ||
28 | QueryEvaluationHint evaluationHints = positivePatternCall.getReferredQuery().getEvaluationHints(); | ||
29 | if (evaluationHints == null) return true; | ||
30 | |||
31 | BackendRequirement backendRequirementType = evaluationHints.getQueryBackendRequirementType(); | ||
32 | switch(backendRequirementType) { | ||
33 | case DEFAULT_CACHING: | ||
34 | return false; | ||
35 | case SPECIFIC: | ||
36 | return !evaluationHints.getQueryBackendFactory().isCaching(); | ||
37 | case UNSPECIFIED: | ||
38 | case DEFAULT_SEARCH: | ||
39 | default: | ||
40 | return true; | ||
41 | } | ||
42 | } | ||
43 | |||
44 | } | ||
diff --git a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/GenericLocalSearchResultProvider.java b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/GenericLocalSearchResultProvider.java deleted file mode 100644 index ed6c1e5f..00000000 --- a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/GenericLocalSearchResultProvider.java +++ /dev/null | |||
@@ -1,49 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Marton Bur, 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.localsearch.matcher.integration; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.localsearch.plan.IPlanProvider; | ||
12 | import tools.refinery.viatra.runtime.localsearch.planner.compiler.GenericOperationCompiler; | ||
13 | import tools.refinery.viatra.runtime.localsearch.planner.compiler.IOperationCompiler; | ||
14 | import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException; | ||
15 | import tools.refinery.viatra.runtime.matchers.backend.QueryEvaluationHint; | ||
16 | import tools.refinery.viatra.runtime.matchers.context.IQueryBackendContext; | ||
17 | import tools.refinery.viatra.runtime.matchers.context.IndexingService; | ||
18 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
19 | |||
20 | /** | ||
21 | * @author Zoltan Ujhelyi | ||
22 | * @since 1.7 | ||
23 | * | ||
24 | */ | ||
25 | public class GenericLocalSearchResultProvider extends AbstractLocalSearchResultProvider { | ||
26 | |||
27 | /** | ||
28 | * @throws ViatraQueryRuntimeException | ||
29 | */ | ||
30 | public GenericLocalSearchResultProvider(LocalSearchBackend backend, IQueryBackendContext context, PQuery query, | ||
31 | IPlanProvider planProvider, QueryEvaluationHint userHints) { | ||
32 | super(backend, context, query, planProvider, userHints); | ||
33 | } | ||
34 | |||
35 | @Override | ||
36 | protected void indexInitializationBeforePlanning() { | ||
37 | super.indexInitializationBeforePlanning(); | ||
38 | |||
39 | indexReferredTypesOfQuery(query, IndexingService.INSTANCES); | ||
40 | indexReferredTypesOfQuery(query, IndexingService.STATISTICS); | ||
41 | } | ||
42 | |||
43 | @Override | ||
44 | protected IOperationCompiler getOperationCompiler(IQueryBackendContext backendContext, | ||
45 | LocalSearchHints configuration) { | ||
46 | return new GenericOperationCompiler(runtimeContext); | ||
47 | } | ||
48 | |||
49 | } | ||
diff --git a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/IAdornmentProvider.java b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/IAdornmentProvider.java deleted file mode 100644 index 86058be0..00000000 --- a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/IAdornmentProvider.java +++ /dev/null | |||
@@ -1,72 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Grill Balázs, 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.localsearch.matcher.integration; | ||
10 | |||
11 | import java.util.Collections; | ||
12 | import java.util.Set; | ||
13 | |||
14 | import tools.refinery.viatra.runtime.matchers.backend.QueryEvaluationHint; | ||
15 | import tools.refinery.viatra.runtime.matchers.backend.QueryEvaluationHint.BackendRequirement; | ||
16 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PParameter; | ||
17 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
18 | |||
19 | /** | ||
20 | * An adornment provider is used to define the adornments the pattern matcher should prepare for. | ||
21 | * | ||
22 | * <p>A default implementation is available in {@link AllValidAdornments} that describes all | ||
23 | * adornments fulfilling the parameter direction declarations; | ||
24 | * another default option (with better performance but restricted applicability) is {@link LazyPlanningAdornments}. | ||
25 | * | ||
26 | * <br><br> | ||
27 | * | ||
28 | * Users may implement this interface to limit the number of prepared plans based on some runtime information: | ||
29 | * | ||
30 | * <pre> | ||
31 | * class SomeAdornments{ | ||
32 | * | ||
33 | * public Iterable<Set<{@link PParameter}>> getAdornments({@link PQuery} query){ | ||
34 | * if (SomeGeneratedQuerySpecification.instance().getInternalQueryRepresentation().equals(query)){ | ||
35 | * return Collections.singleton(Sets.filter(Sets.newHashSet(query.getParameters()), new Predicate<PParameter>() { | ||
36 | * | ||
37 | * @Override | ||
38 | * public boolean apply(PParameter input) { | ||
39 | * // Decide whether this particular parameter will be bound | ||
40 | * return false; | ||
41 | * } | ||
42 | * })); | ||
43 | * } | ||
44 | * // Returning an empty iterable is safe for unknown queries | ||
45 | * return Collections.emptySet(); | ||
46 | * } | ||
47 | * | ||
48 | * } | ||
49 | * </pre> | ||
50 | * | ||
51 | * @author Grill Balázs | ||
52 | * @since 1.5 | ||
53 | * | ||
54 | */ | ||
55 | public interface IAdornmentProvider { | ||
56 | |||
57 | /** | ||
58 | * The bound parameter sets | ||
59 | */ | ||
60 | public Iterable<Set<PParameter>> getAdornments(PQuery query); | ||
61 | |||
62 | /** | ||
63 | * @return a simple hint that only overrides the adornment provider | ||
64 | * @since 2.1 | ||
65 | */ | ||
66 | public static QueryEvaluationHint toHint(IAdornmentProvider adornmentProvider) { | ||
67 | return new QueryEvaluationHint( | ||
68 | Collections.singletonMap(LocalSearchHintOptions.ADORNMENT_PROVIDER, adornmentProvider), | ||
69 | BackendRequirement.UNSPECIFIED); | ||
70 | } | ||
71 | |||
72 | } | ||
diff --git a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/LazyPlanningAdornments.java b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/LazyPlanningAdornments.java deleted file mode 100644 index 30b3689f..00000000 --- a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/LazyPlanningAdornments.java +++ /dev/null | |||
@@ -1,41 +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.localsearch.matcher.integration; | ||
10 | |||
11 | import java.util.Collections; | ||
12 | import java.util.Set; | ||
13 | |||
14 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PParameter; | ||
15 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
16 | |||
17 | /** | ||
18 | * This adornment provider does not trigger the preparation of any plans. | ||
19 | * Actual query plans will be computed on demand, when the first actual match request is made with a given adornment. | ||
20 | * | ||
21 | * <p> Caution: this is a safe default adornment provider for {@link GenericLocalSearchResultProvider} only; | ||
22 | * do not use for the EMF-specific LS backend. | ||
23 | * | ||
24 | * <p> The benefits is in execution time: query planning costs for adornments are postponed until first usage | ||
25 | * or even entirely avoided (when adornment is never used in practice). | ||
26 | * However, query evaluation time may become less predictable, as the first matcher call (with a given adornment) | ||
27 | * will include the planning cost. | ||
28 | * For benchmarking or other purposes where this is not desirable, use an adornment provider that demands plan precomputation for all necessary adornments. | ||
29 | * | ||
30 | * @author Gabor Bergmann | ||
31 | * @since 2.1 | ||
32 | * | ||
33 | */ | ||
34 | public class LazyPlanningAdornments implements IAdornmentProvider { | ||
35 | |||
36 | @Override | ||
37 | public Iterable<Set<PParameter>> getAdornments(PQuery query) { | ||
38 | return Collections.emptySet(); | ||
39 | } | ||
40 | |||
41 | } | ||
diff --git a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/LocalSearchBackend.java b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/LocalSearchBackend.java deleted file mode 100644 index ae51e2b0..00000000 --- a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/LocalSearchBackend.java +++ /dev/null | |||
@@ -1,259 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Marton Bur, 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.localsearch.matcher.integration; | ||
10 | |||
11 | import java.lang.reflect.InvocationTargetException; | ||
12 | import java.util.ArrayList; | ||
13 | import java.util.Arrays; | ||
14 | import java.util.Collection; | ||
15 | import java.util.Collections; | ||
16 | import java.util.HashSet; | ||
17 | import java.util.List; | ||
18 | import java.util.Map; | ||
19 | import java.util.Set; | ||
20 | import java.util.stream.Stream; | ||
21 | |||
22 | import tools.refinery.viatra.runtime.localsearch.exceptions.LocalSearchException; | ||
23 | import tools.refinery.viatra.runtime.localsearch.matcher.ILocalSearchAdapter; | ||
24 | import tools.refinery.viatra.runtime.localsearch.plan.IPlanDescriptor; | ||
25 | import tools.refinery.viatra.runtime.localsearch.plan.IPlanProvider; | ||
26 | import tools.refinery.viatra.runtime.localsearch.plan.SimplePlanProvider; | ||
27 | import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException; | ||
28 | import tools.refinery.viatra.runtime.matchers.backend.IMatcherCapability; | ||
29 | import tools.refinery.viatra.runtime.matchers.backend.IQueryBackend; | ||
30 | import tools.refinery.viatra.runtime.matchers.backend.IQueryBackendHintProvider; | ||
31 | import tools.refinery.viatra.runtime.matchers.backend.IQueryResultProvider; | ||
32 | import tools.refinery.viatra.runtime.matchers.backend.QueryEvaluationHint; | ||
33 | import tools.refinery.viatra.runtime.matchers.backend.ResultProviderRequestor; | ||
34 | import tools.refinery.viatra.runtime.matchers.context.IQueryBackendContext; | ||
35 | import tools.refinery.viatra.runtime.matchers.context.IQueryRuntimeContext; | ||
36 | import tools.refinery.viatra.runtime.matchers.psystem.analysis.QueryAnalyzer; | ||
37 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PParameter; | ||
38 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
39 | import tools.refinery.viatra.runtime.matchers.util.CollectionsFactory; | ||
40 | import tools.refinery.viatra.runtime.matchers.util.ICache; | ||
41 | import tools.refinery.viatra.runtime.matchers.util.PurgableCache; | ||
42 | |||
43 | /** | ||
44 | * @author Marton Bur, Zoltan Ujhelyi | ||
45 | * @noextend This class is not intended to be subclassed by clients. | ||
46 | */ | ||
47 | public abstract class LocalSearchBackend implements IQueryBackend { | ||
48 | |||
49 | IQueryBackendContext context; | ||
50 | IPlanProvider planProvider; | ||
51 | private final Set<ILocalSearchAdapter> adapters = new HashSet<>(); | ||
52 | |||
53 | private final PurgableCache generalCache; | ||
54 | |||
55 | private final Map<PQuery, List<AbstractLocalSearchResultProvider>> resultProviderCache = CollectionsFactory.createMap(); | ||
56 | |||
57 | |||
58 | /** | ||
59 | * @since 1.5 | ||
60 | */ | ||
61 | public LocalSearchBackend(IQueryBackendContext context) { | ||
62 | super(); | ||
63 | this.context = context; | ||
64 | this.generalCache = new PurgableCache(); | ||
65 | this.planProvider = new SimplePlanProvider(context.getLogger()); | ||
66 | } | ||
67 | |||
68 | @Override | ||
69 | public void flushUpdates() { | ||
70 | |||
71 | } | ||
72 | |||
73 | @Override | ||
74 | public IQueryResultProvider getResultProvider(PQuery query) { | ||
75 | return getResultProvider(query, null); | ||
76 | } | ||
77 | |||
78 | /** | ||
79 | * @since 1.4 | ||
80 | */ | ||
81 | @Override | ||
82 | public IQueryResultProvider getResultProvider(PQuery query, QueryEvaluationHint hints) { | ||
83 | |||
84 | final QueryEvaluationHint callHints = getHintProvider().getQueryEvaluationHint(query).overrideBy(hints); | ||
85 | IMatcherCapability requestedCapability = context.getRequiredMatcherCapability(query, callHints); | ||
86 | for(AbstractLocalSearchResultProvider existingResultProvider : resultProviderCache.getOrDefault(query, Collections.emptyList())){ | ||
87 | if (requestedCapability.canBeSubstitute(existingResultProvider.getCapabilites())){ | ||
88 | return existingResultProvider; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | AbstractLocalSearchResultProvider resultProvider = initializeResultProvider(query, hints); | ||
93 | resultProviderCache.computeIfAbsent(query, k->new ArrayList<>()).add(resultProvider); | ||
94 | resultProvider.prepare(); | ||
95 | return resultProvider; | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * Returns a requestor that this backend uses while processing pattern calls <i>from</i> this query. | ||
100 | * @noreference This method is not intended to be referenced by clients. | ||
101 | * @since 2.1 | ||
102 | */ | ||
103 | public ResultProviderRequestor getResultProviderRequestor(PQuery query, QueryEvaluationHint userHints) { | ||
104 | QueryEvaluationHint hintOnQuery = | ||
105 | context.getHintProvider().getQueryEvaluationHint(query).overrideBy(userHints); | ||
106 | LocalSearchHints defaultsApplied = LocalSearchHints.getDefaultOverriddenBy(hintOnQuery); | ||
107 | |||
108 | return new ResultProviderRequestor(this, | ||
109 | context.getResultProviderAccess(), | ||
110 | context.getHintProvider(), | ||
111 | defaultsApplied.getCallDelegationStrategy(), | ||
112 | userHints, | ||
113 | /* no global overrides */ null); | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * @throws ViatraQueryRuntimeException | ||
118 | * @since 1.7 | ||
119 | */ | ||
120 | protected abstract AbstractLocalSearchResultProvider initializeResultProvider(PQuery query, QueryEvaluationHint hints); | ||
121 | |||
122 | @Override | ||
123 | public void dispose() { | ||
124 | resultProviderCache.clear(); | ||
125 | generalCache.purge(); | ||
126 | } | ||
127 | |||
128 | @Override | ||
129 | public boolean isCaching() { | ||
130 | return false; | ||
131 | } | ||
132 | |||
133 | /** | ||
134 | * @since 2.0 | ||
135 | */ | ||
136 | @Override | ||
137 | public AbstractLocalSearchResultProvider peekExistingResultProvider(PQuery query) { | ||
138 | return resultProviderCache.getOrDefault(query, Collections.emptyList()).stream().findAny().orElse(null); | ||
139 | } | ||
140 | |||
141 | /** | ||
142 | * @since 1.4 | ||
143 | */ | ||
144 | public IQueryRuntimeContext getRuntimeContext() { | ||
145 | return context.getRuntimeContext(); | ||
146 | } | ||
147 | |||
148 | |||
149 | /** | ||
150 | * @since 1.5 | ||
151 | */ | ||
152 | public QueryAnalyzer getQueryAnalyzer() { | ||
153 | return context.getQueryAnalyzer(); | ||
154 | } | ||
155 | |||
156 | |||
157 | /** | ||
158 | * @since 1.4 | ||
159 | */ | ||
160 | public IQueryBackendHintProvider getHintProvider() { | ||
161 | return context.getHintProvider(); | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * @since 1.5 | ||
166 | */ | ||
167 | public void addAdapter(ILocalSearchAdapter adapter){ | ||
168 | adapters.add(adapter); | ||
169 | } | ||
170 | |||
171 | /** | ||
172 | * @since 1.5 | ||
173 | */ | ||
174 | public void removeAdapter(ILocalSearchAdapter adapter){ | ||
175 | adapters.remove(adapter); | ||
176 | } | ||
177 | |||
178 | /** | ||
179 | * Return a copy of the current adapters | ||
180 | * @since 1.7 | ||
181 | */ | ||
182 | public List<ILocalSearchAdapter> getAdapters() { | ||
183 | return new ArrayList<>(adapters); | ||
184 | } | ||
185 | |||
186 | /** | ||
187 | * @since 1.5 | ||
188 | */ | ||
189 | public IQueryBackendContext getBackendContext() { | ||
190 | return context; | ||
191 | } | ||
192 | |||
193 | /** | ||
194 | * Returns the internal cache of the backend | ||
195 | * @since 1.7 | ||
196 | * @noreference This method is not intended to be referenced by clients. | ||
197 | */ | ||
198 | public ICache getCache() { | ||
199 | return generalCache; | ||
200 | } | ||
201 | |||
202 | /** | ||
203 | * Updates the previously stored search plans for one or more given queries, computing a new set of plans if | ||
204 | * necessary. The new plans created are the same that would be created by executing prepare on the given query | ||
205 | * definitions. | ||
206 | * | ||
207 | * @since 2.0 | ||
208 | */ | ||
209 | public void recomputePlans(PQuery... queries) { | ||
210 | recomputePlans(Arrays.stream(queries).flatMap(query -> resultProviderCache.getOrDefault(query, Collections.emptyList()).stream())); | ||
211 | } | ||
212 | |||
213 | /** | ||
214 | * Updates the previously stored search plans for one or more given queries, computing a new set of plans if | ||
215 | * necessary The new plans created are the same that would be created by executing prepare on the given query | ||
216 | * definitions. | ||
217 | * | ||
218 | * @since 2.0 | ||
219 | */ | ||
220 | public void recomputePlans(Collection<PQuery> queries) { | ||
221 | recomputePlans(queries.stream().flatMap(query -> resultProviderCache.getOrDefault(query, Collections.emptyList()).stream())); | ||
222 | } | ||
223 | |||
224 | /** | ||
225 | * Updates the previously stored search plans for one or more given queries, computing a new set of plans if | ||
226 | * necessary The new plans created are the same that would be created by executing prepare on the given query | ||
227 | * definitions. | ||
228 | * | ||
229 | * @since 2.0 | ||
230 | */ | ||
231 | public void recomputePlans() { | ||
232 | recomputePlans(resultProviderCache.values().stream().flatMap(List::stream)); | ||
233 | } | ||
234 | |||
235 | private void recomputePlans(Stream<AbstractLocalSearchResultProvider> resultProviders) { | ||
236 | try { | ||
237 | context.getRuntimeContext().coalesceTraversals(() -> { | ||
238 | resultProviders.forEach(resultProvider -> { | ||
239 | resultProvider.forgetAllPlans(); | ||
240 | resultProvider.prepare(); | ||
241 | }); | ||
242 | return null; | ||
243 | }); | ||
244 | } catch (InvocationTargetException e) { | ||
245 | throw new LocalSearchException("Error while rebuilding plans: " + e.getMessage(), e); | ||
246 | } | ||
247 | } | ||
248 | |||
249 | /** | ||
250 | * Returns a search plan for a given query and adornment if such plan is already calculated. | ||
251 | * | ||
252 | * @return a previously calculated search plan for the given query and adornment, or null if no such plan exists | ||
253 | * @since 2.0 | ||
254 | */ | ||
255 | public IPlanDescriptor getSearchPlan(PQuery query, Set<PParameter> adornment) { | ||
256 | final AbstractLocalSearchResultProvider resultProvider = peekExistingResultProvider(query); | ||
257 | return (resultProvider == null) ? null : resultProvider.getSearchPlan(adornment); | ||
258 | } | ||
259 | } | ||
diff --git a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/LocalSearchGenericBackendFactory.java b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/LocalSearchGenericBackendFactory.java deleted file mode 100644 index 1dd08f98..00000000 --- a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/LocalSearchGenericBackendFactory.java +++ /dev/null | |||
@@ -1,65 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Marton Bur, 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.localsearch.matcher.integration; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.matchers.backend.IMatcherCapability; | ||
12 | import tools.refinery.viatra.runtime.matchers.backend.IQueryBackend; | ||
13 | import tools.refinery.viatra.runtime.matchers.backend.IQueryBackendFactory; | ||
14 | import tools.refinery.viatra.runtime.matchers.backend.QueryEvaluationHint; | ||
15 | import tools.refinery.viatra.runtime.matchers.context.IQueryBackendContext; | ||
16 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
17 | |||
18 | /** | ||
19 | * @author Marton Bur, Zoltan Ujhelyi | ||
20 | * @since 1.7 | ||
21 | * | ||
22 | */ | ||
23 | public enum LocalSearchGenericBackendFactory implements IQueryBackendFactory { | ||
24 | |||
25 | INSTANCE; | ||
26 | |||
27 | /** | ||
28 | * @since 1.5 | ||
29 | */ | ||
30 | @Override | ||
31 | public IQueryBackend create(IQueryBackendContext context) { | ||
32 | return new LocalSearchBackend(context) { | ||
33 | |||
34 | @Override | ||
35 | protected AbstractLocalSearchResultProvider initializeResultProvider(PQuery query, QueryEvaluationHint hints) { | ||
36 | return new GenericLocalSearchResultProvider(this, context, query, planProvider, hints); | ||
37 | } | ||
38 | |||
39 | @Override | ||
40 | public IQueryBackendFactory getFactory() { | ||
41 | return INSTANCE; | ||
42 | } | ||
43 | |||
44 | }; | ||
45 | } | ||
46 | |||
47 | @Override | ||
48 | public Class<? extends IQueryBackend> getBackendClass() { | ||
49 | return LocalSearchBackend.class; | ||
50 | } | ||
51 | |||
52 | /** | ||
53 | * @since 1.4 | ||
54 | */ | ||
55 | @Override | ||
56 | public IMatcherCapability calculateRequiredCapability(PQuery query, QueryEvaluationHint hint) { | ||
57 | return LocalSearchHints.parse(hint); | ||
58 | } | ||
59 | |||
60 | @Override | ||
61 | public boolean isCaching() { | ||
62 | return false; | ||
63 | } | ||
64 | |||
65 | } | ||
diff --git a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/LocalSearchGenericBackendFactoryProvider.java b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/LocalSearchGenericBackendFactoryProvider.java deleted file mode 100644 index ea422d91..00000000 --- a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/LocalSearchGenericBackendFactoryProvider.java +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2018, 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.localsearch.matcher.integration; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.matchers.backend.IQueryBackendFactory; | ||
12 | import tools.refinery.viatra.runtime.matchers.backend.IQueryBackendFactoryProvider; | ||
13 | |||
14 | /** | ||
15 | * @since 2.0 | ||
16 | */ | ||
17 | public class LocalSearchGenericBackendFactoryProvider implements IQueryBackendFactoryProvider { | ||
18 | |||
19 | @Override | ||
20 | public IQueryBackendFactory getFactory() { | ||
21 | return LocalSearchGenericBackendFactory.INSTANCE; | ||
22 | } | ||
23 | |||
24 | } \ No newline at end of file | ||
diff --git a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/LocalSearchHintOptions.java b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/LocalSearchHintOptions.java deleted file mode 100644 index 43462204..00000000 --- a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/LocalSearchHintOptions.java +++ /dev/null | |||
@@ -1,70 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, 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.localsearch.matcher.integration; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.localsearch.planner.cost.ICostFunction; | ||
12 | import tools.refinery.viatra.runtime.localsearch.planner.cost.impl.IndexerBasedConstraintCostFunction; | ||
13 | import tools.refinery.viatra.runtime.matchers.backend.ICallDelegationStrategy; | ||
14 | import tools.refinery.viatra.runtime.matchers.backend.QueryHintOption; | ||
15 | import tools.refinery.viatra.runtime.matchers.psystem.rewriters.IFlattenCallPredicate; | ||
16 | |||
17 | /** | ||
18 | * | ||
19 | * @author Gabor Bergmann | ||
20 | * @since 1.5 | ||
21 | * @noinstantiate This class is not intended to be instantiated by clients. | ||
22 | */ | ||
23 | public final class LocalSearchHintOptions { | ||
24 | |||
25 | private LocalSearchHintOptions() { | ||
26 | // Private constructor for utility class | ||
27 | } | ||
28 | |||
29 | public static final QueryHintOption<Boolean> USE_BASE_INDEX = | ||
30 | hintOption("USE_BASE_INDEX", true); | ||
31 | |||
32 | // This key can be used to influence the core planner algorithm | ||
33 | public static final QueryHintOption<Integer> PLANNER_TABLE_ROW_COUNT = | ||
34 | hintOption("PLANNER_TABLE_ROW_COUNT", 4); | ||
35 | /** | ||
36 | * Cost function to be used by the planner. Must implement {@link ICostFunction} | ||
37 | * @since 1.4 | ||
38 | */ | ||
39 | public static final QueryHintOption<ICostFunction> PLANNER_COST_FUNCTION = | ||
40 | hintOption("PLANNER_COST_FUNCTION", new IndexerBasedConstraintCostFunction()); | ||
41 | /** | ||
42 | * Predicate to decide whether to flatten specific positive pattern calls {@link IFlattenCallPredicate} | ||
43 | * @since 1.4 | ||
44 | */ | ||
45 | public static final QueryHintOption<IFlattenCallPredicate> FLATTEN_CALL_PREDICATE = | ||
46 | hintOption("FLATTEN_CALL_PREDICATE", new DontFlattenDisjunctive()); | ||
47 | /** | ||
48 | * Strategy to decide how hints (most importantly, backend selection) propagate across pattern calls. | ||
49 | * Must implement {@link ICallDelegationStrategy}. | ||
50 | * @since 2.1 | ||
51 | */ | ||
52 | public static final QueryHintOption<ICallDelegationStrategy> CALL_DELEGATION_STRATEGY = | ||
53 | hintOption("CALL_DELEGATION_STRATEGY", ICallDelegationStrategy.FULL_BACKEND_ADHESION); | ||
54 | |||
55 | /** | ||
56 | * A provider of expected adornments {@link IAdornmentProvider}. | ||
57 | * | ||
58 | * The safe default is {@link AllValidAdornments}; | ||
59 | * however, the generic backend variant may safely use {@link LazyPlanningAdornments} instead. | ||
60 | * | ||
61 | * @since 1.5 | ||
62 | */ | ||
63 | public static final QueryHintOption<IAdornmentProvider> ADORNMENT_PROVIDER = | ||
64 | hintOption("ADORNMENT_PROVIDER", new AllValidAdornments()); | ||
65 | |||
66 | // internal helper for conciseness | ||
67 | private static <T, V extends T> QueryHintOption<T> hintOption(String hintKeyLocalName, V defaultValue) { | ||
68 | return new QueryHintOption<>(LocalSearchHintOptions.class, hintKeyLocalName, defaultValue); | ||
69 | } | ||
70 | } | ||
diff --git a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/LocalSearchHints.java b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/LocalSearchHints.java deleted file mode 100644 index 5f3895be..00000000 --- a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/matcher/integration/LocalSearchHints.java +++ /dev/null | |||
@@ -1,306 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Grill Balázs, 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.localsearch.matcher.integration; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.localsearch.planner.cost.ICostFunction; | ||
12 | import tools.refinery.viatra.runtime.localsearch.planner.cost.impl.IndexerBasedConstraintCostFunction; | ||
13 | import tools.refinery.viatra.runtime.localsearch.planner.cost.impl.StatisticsBasedConstraintCostFunction; | ||
14 | import tools.refinery.viatra.runtime.matchers.backend.*; | ||
15 | import tools.refinery.viatra.runtime.matchers.psystem.rewriters.IFlattenCallPredicate; | ||
16 | import tools.refinery.viatra.runtime.matchers.psystem.rewriters.IRewriterTraceCollector; | ||
17 | import tools.refinery.viatra.runtime.matchers.psystem.rewriters.NopTraceCollector; | ||
18 | |||
19 | import java.util.HashMap; | ||
20 | import java.util.Map; | ||
21 | import java.util.Objects; | ||
22 | |||
23 | import static tools.refinery.viatra.runtime.localsearch.matcher.integration.LocalSearchHintOptions.*; | ||
24 | import static tools.refinery.viatra.runtime.matchers.backend.CommonQueryHintOptions.normalizationTraceCollector; | ||
25 | |||
26 | /** | ||
27 | * Type safe builder and extractor for Local search specific hints | ||
28 | * | ||
29 | * @author Grill Balázs | ||
30 | * @since 1.4 | ||
31 | * | ||
32 | */ | ||
33 | public final class LocalSearchHints implements IMatcherCapability { | ||
34 | |||
35 | private Boolean useBase = null; | ||
36 | |||
37 | private Integer rowCount = null; | ||
38 | |||
39 | private ICostFunction costFunction = null; | ||
40 | |||
41 | private IFlattenCallPredicate flattenCallPredicate = null; | ||
42 | |||
43 | private ICallDelegationStrategy callDelegationStrategy = null; | ||
44 | |||
45 | private IAdornmentProvider adornmentProvider = null; | ||
46 | |||
47 | private IRewriterTraceCollector traceCollector = NopTraceCollector.INSTANCE; | ||
48 | |||
49 | private IQueryBackendFactory backendFactory = null; | ||
50 | |||
51 | private LocalSearchHints() {} | ||
52 | |||
53 | /** | ||
54 | * Return the default settings overridden by the given hints | ||
55 | */ | ||
56 | public static LocalSearchHints getDefaultOverriddenBy(QueryEvaluationHint overridingHint){ | ||
57 | return parse(getDefault().build(overridingHint)); | ||
58 | } | ||
59 | |||
60 | /** | ||
61 | * Default settings which are considered the most safe, providing a reasonable performance for most of the cases. Assumes the availability of the base indexer. | ||
62 | */ | ||
63 | public static LocalSearchHints getDefault(){ | ||
64 | return getDefaultGeneric(); | ||
65 | } | ||
66 | |||
67 | /** | ||
68 | * Initializes the generic (not EMF specific) search backend with the default settings | ||
69 | * @since 1.7 | ||
70 | */ | ||
71 | public static LocalSearchHints getDefaultGeneric(){ | ||
72 | LocalSearchHints result = new LocalSearchHints(); | ||
73 | result.useBase = true; // Should be unused; but a false value might cause surprises as an engine-default hint | ||
74 | result.rowCount = 4; | ||
75 | result.costFunction = new IndexerBasedConstraintCostFunction(StatisticsBasedConstraintCostFunction.INVERSE_NAVIGATION_PENALTY_GENERIC); | ||
76 | result.flattenCallPredicate = FLATTEN_CALL_PREDICATE.getDefaultValue(); | ||
77 | result.callDelegationStrategy = ICallDelegationStrategy.FULL_BACKEND_ADHESION; | ||
78 | result.adornmentProvider = new LazyPlanningAdornments(); | ||
79 | result.backendFactory = LocalSearchGenericBackendFactory.INSTANCE; | ||
80 | return result; | ||
81 | } | ||
82 | |||
83 | /** | ||
84 | * Initializes the default search backend with hybrid-enabled settings | ||
85 | * @since 2.1 | ||
86 | */ | ||
87 | public static LocalSearchHints getDefaultHybrid(){ | ||
88 | LocalSearchHints result = getDefault(); | ||
89 | result.callDelegationStrategy = ICallDelegationStrategy.PARTIAL_BACKEND_ADHESION; | ||
90 | result.flattenCallPredicate = new IFlattenCallPredicate.And( | ||
91 | new DontFlattenIncrementalPredicate(), new DontFlattenDisjunctive()); | ||
92 | return result; | ||
93 | } | ||
94 | |||
95 | /** | ||
96 | * Initializes the generic (not EMF specific) search backend with hybrid-enabled settings | ||
97 | * @since 2.1 | ||
98 | */ | ||
99 | public static LocalSearchHints getDefaultGenericHybrid(){ | ||
100 | LocalSearchHints result = getDefaultGeneric(); | ||
101 | result.callDelegationStrategy = ICallDelegationStrategy.PARTIAL_BACKEND_ADHESION; | ||
102 | result.flattenCallPredicate = new IFlattenCallPredicate.And( | ||
103 | new DontFlattenIncrementalPredicate(), new DontFlattenDisjunctive()); | ||
104 | return result; | ||
105 | } | ||
106 | |||
107 | public static LocalSearchHints parse(QueryEvaluationHint hint){ | ||
108 | LocalSearchHints result = new LocalSearchHints(); | ||
109 | |||
110 | result.useBase = USE_BASE_INDEX.getValueOrNull(hint); | ||
111 | result.rowCount = PLANNER_TABLE_ROW_COUNT.getValueOrNull(hint); | ||
112 | result.flattenCallPredicate = FLATTEN_CALL_PREDICATE.getValueOrNull(hint); | ||
113 | result.callDelegationStrategy = CALL_DELEGATION_STRATEGY.getValueOrNull(hint); | ||
114 | result.costFunction = PLANNER_COST_FUNCTION.getValueOrNull(hint); | ||
115 | result.adornmentProvider = ADORNMENT_PROVIDER.getValueOrNull(hint); | ||
116 | result.traceCollector = normalizationTraceCollector.getValueOrDefault(hint); | ||
117 | |||
118 | return result; | ||
119 | } | ||
120 | |||
121 | |||
122 | private Map<QueryHintOption<?>, Object> calculateHintMap() { | ||
123 | Map<QueryHintOption<?>, Object> map = new HashMap<>(); | ||
124 | if (useBase != null){ | ||
125 | USE_BASE_INDEX.insertOverridingValue(map, useBase); | ||
126 | } | ||
127 | if (rowCount != null){ | ||
128 | PLANNER_TABLE_ROW_COUNT.insertOverridingValue(map, rowCount); | ||
129 | } | ||
130 | if (costFunction != null){ | ||
131 | PLANNER_COST_FUNCTION.insertOverridingValue(map, costFunction); | ||
132 | } | ||
133 | if (flattenCallPredicate != null){ | ||
134 | FLATTEN_CALL_PREDICATE.insertOverridingValue(map, flattenCallPredicate); | ||
135 | } | ||
136 | if (callDelegationStrategy != null){ | ||
137 | CALL_DELEGATION_STRATEGY.insertOverridingValue(map, callDelegationStrategy); | ||
138 | } | ||
139 | if (adornmentProvider != null){ | ||
140 | ADORNMENT_PROVIDER.insertOverridingValue(map, adornmentProvider); | ||
141 | } | ||
142 | if (traceCollector != null){ | ||
143 | normalizationTraceCollector.insertOverridingValue(map, traceCollector); | ||
144 | } | ||
145 | return map; | ||
146 | } | ||
147 | |||
148 | public QueryEvaluationHint build(){ | ||
149 | Map<QueryHintOption<?>, Object> map = calculateHintMap(); | ||
150 | return new QueryEvaluationHint(map, backendFactory); | ||
151 | } | ||
152 | |||
153 | /** | ||
154 | * @since 1.7 | ||
155 | */ | ||
156 | public QueryEvaluationHint build(QueryEvaluationHint overridingHint) { | ||
157 | if (overridingHint == null) | ||
158 | return build(); | ||
159 | |||
160 | IQueryBackendFactory factory = (overridingHint.getQueryBackendFactory() == null) | ||
161 | ? this.backendFactory | ||
162 | : overridingHint.getQueryBackendFactory(); | ||
163 | |||
164 | Map<QueryHintOption<?>, Object> hints = calculateHintMap(); | ||
165 | if (overridingHint.getBackendHintSettings() != null) { | ||
166 | hints.putAll(overridingHint.getBackendHintSettings()); | ||
167 | } | ||
168 | |||
169 | return new QueryEvaluationHint(hints, factory); | ||
170 | } | ||
171 | |||
172 | public boolean isUseBase() { | ||
173 | return useBase; | ||
174 | } | ||
175 | |||
176 | public ICostFunction getCostFunction() { | ||
177 | return costFunction; | ||
178 | } | ||
179 | |||
180 | public IFlattenCallPredicate getFlattenCallPredicate() { | ||
181 | return flattenCallPredicate; | ||
182 | } | ||
183 | |||
184 | /** | ||
185 | * @since 2.1 | ||
186 | */ | ||
187 | public ICallDelegationStrategy getCallDelegationStrategy() { | ||
188 | return callDelegationStrategy; | ||
189 | } | ||
190 | |||
191 | public Integer getRowCount() { | ||
192 | return rowCount; | ||
193 | } | ||
194 | |||
195 | /** | ||
196 | * @since 1.5 | ||
197 | */ | ||
198 | public IAdornmentProvider getAdornmentProvider() { | ||
199 | return adornmentProvider; | ||
200 | } | ||
201 | |||
202 | /** | ||
203 | * @since 1.6 | ||
204 | */ | ||
205 | public IRewriterTraceCollector getTraceCollector() { | ||
206 | return traceCollector == null ? normalizationTraceCollector.getDefaultValue() : traceCollector; | ||
207 | } | ||
208 | |||
209 | public LocalSearchHints setUseBase(boolean useBase) { | ||
210 | this.useBase = useBase; | ||
211 | return this; | ||
212 | } | ||
213 | |||
214 | public LocalSearchHints setRowCount(int rowCount) { | ||
215 | this.rowCount = rowCount; | ||
216 | return this; | ||
217 | } | ||
218 | |||
219 | public LocalSearchHints setCostFunction(ICostFunction costFunction) { | ||
220 | this.costFunction = costFunction; | ||
221 | return this; | ||
222 | } | ||
223 | |||
224 | public LocalSearchHints setFlattenCallPredicate(IFlattenCallPredicate flattenCallPredicate) { | ||
225 | this.flattenCallPredicate = flattenCallPredicate; | ||
226 | return this; | ||
227 | } | ||
228 | |||
229 | |||
230 | /** | ||
231 | * @since 2.1 | ||
232 | */ | ||
233 | public LocalSearchHints setCallDelegationStrategy(ICallDelegationStrategy callDelegationStrategy) { | ||
234 | this.callDelegationStrategy = callDelegationStrategy; | ||
235 | return this; | ||
236 | } | ||
237 | |||
238 | /** | ||
239 | * @since 1.6 | ||
240 | */ | ||
241 | public LocalSearchHints setTraceCollector(IRewriterTraceCollector traceCollector) { | ||
242 | this.traceCollector = traceCollector; | ||
243 | return this; | ||
244 | } | ||
245 | |||
246 | /** | ||
247 | * @since 1.5 | ||
248 | */ | ||
249 | public LocalSearchHints setAdornmentProvider(IAdornmentProvider adornmentProvider) { | ||
250 | this.adornmentProvider = adornmentProvider; | ||
251 | return this; | ||
252 | } | ||
253 | |||
254 | public static LocalSearchHints customizeUseBase(boolean useBase){ | ||
255 | return new LocalSearchHints().setUseBase(useBase); | ||
256 | } | ||
257 | |||
258 | public static LocalSearchHints customizeRowCount(int rowCount){ | ||
259 | return new LocalSearchHints().setRowCount(rowCount); | ||
260 | } | ||
261 | |||
262 | public static LocalSearchHints customizeCostFunction(ICostFunction costFunction){ | ||
263 | return new LocalSearchHints().setCostFunction(costFunction); | ||
264 | } | ||
265 | |||
266 | public static LocalSearchHints customizeFlattenCallPredicate(IFlattenCallPredicate predicate){ | ||
267 | return new LocalSearchHints().setFlattenCallPredicate(predicate); | ||
268 | } | ||
269 | |||
270 | /** | ||
271 | * @since 2.1 | ||
272 | */ | ||
273 | public static LocalSearchHints customizeCallDelegationStrategy(ICallDelegationStrategy strategy){ | ||
274 | return new LocalSearchHints().setCallDelegationStrategy(strategy); | ||
275 | } | ||
276 | |||
277 | /** | ||
278 | * @since 1.5 | ||
279 | */ | ||
280 | public static LocalSearchHints customizeAdornmentProvider(IAdornmentProvider adornmentProvider){ | ||
281 | return new LocalSearchHints().setAdornmentProvider(adornmentProvider); | ||
282 | } | ||
283 | |||
284 | /** | ||
285 | * @since 1.6 | ||
286 | */ | ||
287 | public static LocalSearchHints customizeTraceCollector(IRewriterTraceCollector traceCollector){ | ||
288 | return new LocalSearchHints().setTraceCollector(traceCollector); | ||
289 | } | ||
290 | |||
291 | @Override | ||
292 | public boolean canBeSubstitute(IMatcherCapability capability) { | ||
293 | if (capability instanceof LocalSearchHints){ | ||
294 | LocalSearchHints other = (LocalSearchHints)capability; | ||
295 | /* | ||
296 | * We allow substitution of matchers if their functionally relevant settings are equal. | ||
297 | */ | ||
298 | return Objects.equals(other.useBase, useBase); | ||
299 | } | ||
300 | /* | ||
301 | * For any other cases (e.g. for Rete), we cannot assume | ||
302 | * that matchers created by LS are functionally equivalent. | ||
303 | */ | ||
304 | return false; | ||
305 | } | ||
306 | } | ||