Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZoltan Ujhelyi2017-06-29 09:02:22 +0000
committerZoltan Ujhelyi2017-07-11 09:46:21 +0000
commit0dff346884f3c638e4e962eb1ea7ce2253982707 (patch)
treeeece42149dd67e581e46f2752a2e132456dbc190
parent6e8603fa71bf000c110b14124330de6c8b150b0b (diff)
downloadorg.eclipse.viatra-0dff346884f3c638e4e962eb1ea7ce2253982707.tar.gz
org.eclipse.viatra-0dff346884f3c638e4e962eb1ea7ce2253982707.tar.xz
org.eclipse.viatra-0dff346884f3c638e4e962eb1ea7ce2253982707.zip
[469149] Initial version of generic local search backend
Change-Id: Ib4951c4178bb87e38dbc42d0a5db06c17dc71adc Signed-off-by: Zoltan Ujhelyi <ujhelyiz@incquerylabs.com>
-rw-r--r--query/plugins/org.eclipse.viatra.query.runtime.localsearch/.settings/.api_filters16
-rw-r--r--query/plugins/org.eclipse.viatra.query.runtime.localsearch/META-INF/MANIFEST.MF16
-rw-r--r--query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/AbstractLocalSearchResultProvider.java375
-rw-r--r--query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/GenericLocalSearchResultProvider.java56
-rw-r--r--query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchBackend.java28
-rw-r--r--query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchBackendFactory.java9
-rw-r--r--query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchGenericBackendFactory.java71
-rw-r--r--query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchHints.java23
-rw-r--r--query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchResultProvider.java341
-rw-r--r--query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/plan/CachingPlanProvider.java9
-rw-r--r--query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/plan/IPlanProvider.java3
-rw-r--r--query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/ILocalSearchPlanner.java41
-rw-r--r--query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/LocalSearchPlanner.java14
-rw-r--r--query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/POperationCompiler.java551
-rw-r--r--query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/compiler/AbstractOperationCompiler.java438
-rw-r--r--query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/compiler/EMFOperationCompiler.java174
-rw-r--r--query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/compiler/GenericOperationCompiler.java86
-rw-r--r--query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/compiler/IOperationCompiler.java50
18 files changed, 1398 insertions, 903 deletions
diff --git a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/.settings/.api_filters b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/.settings/.api_filters
index 00ea71416..5a3996d18 100644
--- a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/.settings/.api_filters
+++ b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/.settings/.api_filters
@@ -27,8 +27,20 @@
<message_argument value="SearchContext"/>
</message_arguments>
</filter>
+ <filter comment="Internal API implementation" id="640712815">
+ <message_arguments>
+ <message_argument value="ICache"/>
+ <message_argument value="SearchContext"/>
+ <message_argument value="getValue(Object, Class&lt;? extends T&gt;, IProvider&lt;T&gt;)"/>
+ </message_arguments>
+ </filter>
</resource>
<resource path="src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchBackend.java" type="org.eclipse.viatra.query.runtime.localsearch.matcher.integration.LocalSearchBackend">
+ <filter comment="Internal API update" id="337764418">
+ <message_arguments>
+ <message_argument value="org.eclipse.viatra.query.runtime.localsearch.matcher.integration.LocalSearchBackend"/>
+ </message_arguments>
+ </filter>
<filter comment="Internal API usage" id="640708718">
<message_arguments>
<message_argument value="PurgableCache()"/>
@@ -73,10 +85,10 @@
</filter>
</resource>
<resource path="src/org/eclipse/viatra/query/runtime/localsearch/plan/IPlanProvider.java" type="org.eclipse.viatra.query.runtime.localsearch.plan.IPlanProvider">
- <filter comment="Internal API modification" id="403804204">
+ <filter comment="Internal API update" id="403804204">
<message_arguments>
<message_argument value="org.eclipse.viatra.query.runtime.localsearch.plan.IPlanProvider"/>
- <message_argument value="getPlan(IQueryBackendContext, LocalSearchHints, MatcherReference)"/>
+ <message_argument value="getPlan(IQueryBackendContext, IOperationCompiler, LocalSearchHints, MatcherReference)"/>
</message_arguments>
</filter>
<filter comment="Internal API modification" id="405901410">
diff --git a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/META-INF/MANIFEST.MF b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/META-INF/MANIFEST.MF
index f50909db3..8153c9516 100644
--- a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/META-INF/MANIFEST.MF
+++ b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/META-INF/MANIFEST.MF
@@ -12,19 +12,15 @@ Require-Bundle: org.eclipse.viatra.query.runtime.base;bundle-version="[1.7.0,1.8
org.eclipse.viatra.query.runtime.base.itc;bundle-version="[1.7.0,1.8.0)"
Export-Package: org.eclipse.viatra.query.runtime.localsearch,
org.eclipse.viatra.query.runtime.localsearch.exceptions,
- org.eclipse.viatra.query.runtime.localsearch.matcher;
- uses:="com.google.common.collect",
- org.eclipse.viatra.query.runtime.localsearch.matcher.integration;
- uses:="com.google.common.collect",
+ org.eclipse.viatra.query.runtime.localsearch.matcher;uses:="com.google.common.collect",
+ org.eclipse.viatra.query.runtime.localsearch.matcher.integration;uses:="com.google.common.collect",
org.eclipse.viatra.query.runtime.localsearch.operations,
org.eclipse.viatra.query.runtime.localsearch.operations.check,
org.eclipse.viatra.query.runtime.localsearch.operations.extend,
- org.eclipse.viatra.query.runtime.localsearch.plan;
- uses:="com.google.common.collect",
- org.eclipse.viatra.query.runtime.localsearch.planner;
- uses:="com.google.common.base",
- org.eclipse.viatra.query.runtime.localsearch.planner.cost;
- uses:="com.google.common.base",
+ org.eclipse.viatra.query.runtime.localsearch.plan;uses:="com.google.common.collect",
+ org.eclipse.viatra.query.runtime.localsearch.planner;uses:="com.google.common.base",
+ org.eclipse.viatra.query.runtime.localsearch.planner.compiler,
+ org.eclipse.viatra.query.runtime.localsearch.planner.cost;uses:="com.google.common.base",
org.eclipse.viatra.query.runtime.localsearch.planner.cost.impl,
org.eclipse.viatra.query.runtime.localsearch.profiler
Import-Package: com.google.common.base;version="15.0.0",
diff --git a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/AbstractLocalSearchResultProvider.java b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/AbstractLocalSearchResultProvider.java
new file mode 100644
index 000000000..bf511625e
--- /dev/null
+++ b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/AbstractLocalSearchResultProvider.java
@@ -0,0 +1,375 @@
+/*******************************************************************************
+ * Copyright (c) 2010-2017, Zoltan Ujhelyi, IncQuery Labs Ltd.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Zoltan Ujhelyi - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.viatra.query.runtime.localsearch.matcher.integration;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.Set;
+import java.util.concurrent.Callable;
+
+import org.eclipse.viatra.query.runtime.exception.ViatraQueryException;
+import org.eclipse.viatra.query.runtime.localsearch.MatchingFrame;
+import org.eclipse.viatra.query.runtime.localsearch.exceptions.LocalSearchException;
+import org.eclipse.viatra.query.runtime.localsearch.matcher.ISearchContext;
+import org.eclipse.viatra.query.runtime.localsearch.matcher.LocalSearchMatcher;
+import org.eclipse.viatra.query.runtime.localsearch.matcher.MatcherReference;
+import org.eclipse.viatra.query.runtime.localsearch.plan.IPlanDescriptor;
+import org.eclipse.viatra.query.runtime.localsearch.plan.IPlanProvider;
+import org.eclipse.viatra.query.runtime.localsearch.plan.SearchPlan;
+import org.eclipse.viatra.query.runtime.localsearch.plan.SearchPlanExecutor;
+import org.eclipse.viatra.query.runtime.localsearch.planner.compiler.IOperationCompiler;
+import org.eclipse.viatra.query.runtime.localsearch.planner.util.SearchPlanForBody;
+import org.eclipse.viatra.query.runtime.matchers.backend.IMatcherCapability;
+import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackend;
+import org.eclipse.viatra.query.runtime.matchers.backend.IQueryResultProvider;
+import org.eclipse.viatra.query.runtime.matchers.backend.IUpdateable;
+import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint;
+import org.eclipse.viatra.query.runtime.matchers.backend.QueryHintOption;
+import org.eclipse.viatra.query.runtime.matchers.context.IInputKey;
+import org.eclipse.viatra.query.runtime.matchers.context.IQueryBackendContext;
+import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContext;
+import org.eclipse.viatra.query.runtime.matchers.context.IndexingService;
+import org.eclipse.viatra.query.runtime.matchers.planning.QueryProcessingException;
+import org.eclipse.viatra.query.runtime.matchers.psystem.PBody;
+import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall;
+import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter;
+import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery;
+import org.eclipse.viatra.query.runtime.matchers.psystem.rewriters.IFlattenCallPredicate;
+import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+/**
+ * @author Zoltan Ujhelyi
+ * @since 1.7
+ *
+ */
+public abstract class AbstractLocalSearchResultProvider implements IQueryResultProvider {
+
+ protected final LocalSearchBackend backend;
+ protected final IQueryBackendContext backendContext;
+ protected final IQueryRuntimeContext runtimeContext;
+ protected final PQuery query;
+ protected final QueryEvaluationHint userHints;
+ protected final IPlanProvider planProvider;
+ protected final ISearchContext searchContext;
+
+ /**
+ * @throws QueryProcessingException
+ * @since 1.5
+ */
+ public AbstractLocalSearchResultProvider(LocalSearchBackend backend, IQueryBackendContext context, PQuery query,
+ IPlanProvider planProvider, QueryEvaluationHint userHints) throws QueryProcessingException {
+ this.backend = backend;
+ this.backendContext = context;
+ this.query = query;
+
+ this.planProvider = planProvider;
+ this.userHints = userHints;
+ this.runtimeContext = context.getRuntimeContext();
+ this.searchContext = new ISearchContext.SearchContext(backendContext, userHints, backend.getCache());
+ }
+
+ protected abstract IOperationCompiler getOperationCompiler(IQueryBackendContext backendContext, LocalSearchHints configuration);
+
+ private IQueryRuntimeContext getRuntimeContext() {
+ return ((LocalSearchBackend)backend).getRuntimeContext();
+ }
+
+ private LocalSearchMatcher createMatcher(IPlanDescriptor plan, final ISearchContext searchContext) {
+ Collection<SearchPlanForBody> compiledPlans = Lists.newArrayList(plan.getPlan());
+
+ Collection<SearchPlanExecutor> executors = Collections2.transform(compiledPlans,
+ new Function<SearchPlanForBody, SearchPlanExecutor>() {
+
+ @Override
+ public SearchPlanExecutor apply(SearchPlanForBody input) {
+ final SearchPlan plan = new SearchPlan();
+ plan.addOperations(input.getCompiledOperations());
+
+ return new SearchPlanExecutor(plan, searchContext, input.getVariableKeys());
+ }
+ });
+
+ final Collection<Integer> parameterSizes = Collections2.transform(compiledPlans,
+ new Function<SearchPlanForBody, Integer>() {
+
+ @Override
+ public Integer apply(SearchPlanForBody input) {
+ PBody body = input.getBody();
+ return body.getUniqueVariables().size();
+ // return Math.max(input.getSymbolicParameters().size(), input.getUniqueVariables().size());
+ }
+ });
+
+ return new LocalSearchMatcher(plan, executors,
+ Collections.max(parameterSizes));
+ }
+
+ private IPlanDescriptor createPlan(MatcherReference key, IPlanProvider planProvider) throws QueryProcessingException {
+ LocalSearchHints configuration = overrideDefaultHints(key.getQuery());
+ IOperationCompiler compiler = getOperationCompiler(backendContext, configuration);
+ IPlanDescriptor plan = planProvider.getPlan(backendContext, compiler, configuration, key);
+ return plan;
+ }
+
+ private LocalSearchHints overrideDefaultHints(PQuery pQuery) {
+ return LocalSearchHints.getDefaultOverriddenBy(
+ computeOverridingHints(pQuery));
+ }
+
+ /**
+ * Combine with {@link QueryHintOption#getValueOrDefault(QueryEvaluationHint)} to access
+ * hint settings not covered by {@link LocalSearchHints}
+ */
+ private QueryEvaluationHint computeOverridingHints(PQuery pQuery) {
+ return backendContext.getHintProvider().getQueryEvaluationHint(pQuery).overrideBy(userHints);
+ }
+
+ private Iterator<MatcherReference> computeExpectedAdornments() {
+ return Iterators.transform(overrideDefaultHints(query).getAdornmentProvider().getAdornments(query).iterator(), new Function<Set<PParameter>, MatcherReference>() {
+
+ @Override
+ public MatcherReference apply(Set<PParameter> input) {
+ return new MatcherReference(query, input, userHints);
+ }
+ });
+ }
+
+ /**
+ * Prepare this result provider. This phase is separated from the constructor to allow the backend to cache its instance before
+ * requesting preparation for its dependencies.
+ * @since 1.5
+ */
+ public void prepare() throws QueryProcessingException {
+ try {
+ runtimeContext.coalesceTraversals(new Callable<Void>() {
+
+ @Override
+ public Void call() throws Exception {
+ indexInitializationBeforePlanning();
+ prepareDirectDependencies();
+ runtimeContext.executeAfterTraversal(new Runnable() {
+
+ @Override
+ public void run() {
+ try {
+ preparePlansForExpectedAdornments();
+ } catch (QueryProcessingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ return null;
+ }
+ });
+ } catch (InvocationTargetException e) {
+ throw new QueryProcessingException("Error while building required indexes: %s", new String[]{e.getTargetException().getMessage()}, "Error while building required indexes.", query, e);
+ }
+ }
+
+ protected void preparePlansForExpectedAdornments() throws QueryProcessingException {
+ // Plan for possible adornments
+ Iterator<MatcherReference> iterator = computeExpectedAdornments();
+ while(iterator.hasNext()){
+ LocalSearchHints configuration = overrideDefaultHints(query);
+ IOperationCompiler compiler = getOperationCompiler(backendContext, configuration);
+ IPlanDescriptor plan = planProvider.getPlan(backendContext, compiler, configuration, iterator.next());
+ // Index keys
+ try {
+ indexKeys(plan.getIteratedKeys());
+ } catch (InvocationTargetException e) {
+ throw new QueryProcessingException(e.getMessage(), null, e.getMessage(), query, e);
+ }
+ //Prepare dependencies
+ for(SearchPlanForBody body: plan.getPlan()){
+ for(MatcherReference dependency : body.getDependencies()){
+ try {
+ searchContext.getMatcher(dependency);
+ } catch (LocalSearchException e) {
+ throw new QueryProcessingException("Could not prepare dependency {1}", new String[]{dependency.toString()}, e.getMessage(), query, e);
+ }
+ }
+ }
+ }
+
+ }
+
+ protected void prepareDirectDependencies() throws QueryProcessingException {
+ // Do not prepare for any adornment at this point
+ IAdornmentProvider adornmentProvider = new IAdornmentProvider() {
+
+ @Override
+ public Iterable<Set<PParameter>> getAdornments(PQuery query) {
+ return Collections.emptySet();
+ }
+ };
+ @SuppressWarnings("rawtypes")
+ QueryEvaluationHint hints = new QueryEvaluationHint(Collections.<QueryHintOption, Object>singletonMap(LocalSearchHintOptions.ADORNMENT_PROVIDER, adornmentProvider), null);
+ for(PQuery dep : getDirectPositiveDependencies()){
+ backendContext.getResultProviderAccess().getResultProvider(dep, hints);
+ }
+ }
+
+ /**
+ * This method is called before planning start to allow indexing. It is important to note that this method is called
+ * inside a coalesceTraversals block, meaning (1) it is safe to add multiple registration requests as necessary, but
+ * (2) no value or statistics is available from the index.
+ *
+ * @throws QueryProcessingException
+ */
+ protected void indexInitializationBeforePlanning() throws QueryProcessingException {
+ // By default, no indexing is necessary
+ }
+
+ private Set<PQuery> getDirectPositiveDependencies() {
+ IFlattenCallPredicate flattenPredicate = overrideDefaultHints(query).getFlattenCallPredicate();
+ Queue<PQuery> queue = new LinkedList<PQuery>();
+ Set<PQuery> visited = new HashSet<PQuery>();
+ Set<PQuery> result = new HashSet<PQuery>();
+ queue.add(query);
+
+ while(!queue.isEmpty()){
+ PQuery next = queue.poll();
+ visited.add(next);
+ for(PBody body : next.getDisjunctBodies().getBodies()){
+ for(PositivePatternCall ppc : body.getConstraintsOfType(PositivePatternCall.class)){
+ PQuery dep = ppc.getSupplierKey();
+ if (flattenPredicate.shouldFlatten(ppc)){
+ if (!visited.contains(dep)){
+ queue.add(dep);
+ }
+ }else{
+ result.add(dep);
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ private LocalSearchMatcher initializeMatcher(Object[] parameters) {
+ try {
+ return newLocalSearchMatcher(parameters);
+ } catch (QueryProcessingException | ViatraQueryException e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ public LocalSearchMatcher newLocalSearchMatcher(Object[] parameters) throws ViatraQueryException, QueryProcessingException {
+
+ final Set<PParameter> adornment = Sets.newHashSet();
+ for (int i = 0; i < parameters.length; i++) {
+ if (parameters[i] != null) {
+ adornment.add(query.getParameters().get(i));
+ }
+ }
+
+ final MatcherReference reference = new MatcherReference(query, adornment, userHints);
+
+ IPlanDescriptor plan = createPlan(reference, planProvider);
+ if (overrideDefaultHints(reference.getQuery()).isUseBase()){
+ try {
+ indexKeys(plan.getIteratedKeys());
+ } catch (InvocationTargetException e) {
+ throw new ViatraQueryException("Could not index keys","Could not index keys", e);
+ }
+ }
+
+ LocalSearchMatcher matcher = createMatcher(plan, searchContext);
+ matcher.addAdapters(backend.getAdapters());
+ return matcher;
+ }
+
+ private void indexKeys(final Iterable<IInputKey> keys) throws InvocationTargetException {
+ final IQueryRuntimeContext qrc = getRuntimeContext();
+ qrc.coalesceTraversals(new Callable<Void>() {
+
+ @Override
+ public Void call() throws Exception {
+ for(IInputKey key : keys){
+ qrc.ensureIndexed(key, IndexingService.INSTANCES);
+ }
+ return null;
+ }
+ });
+ }
+
+ @Override
+ public Tuple getOneArbitraryMatch(Object[] parameters) {
+ try {
+ final LocalSearchMatcher matcher = initializeMatcher(parameters);
+ final MatchingFrame frame = matcher.editableMatchingFrame();
+ frame.setParameterValues(parameters);
+ return matcher.getOneArbitraryMatch(frame);
+ } catch (LocalSearchException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public int countMatches(Object[] parameters) {
+ try {
+ final LocalSearchMatcher matcher = initializeMatcher(parameters);
+ final MatchingFrame frame = matcher.editableMatchingFrame();
+ frame.setParameterValues(parameters);
+ return matcher.countMatches(frame);
+ } catch (LocalSearchException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public Collection<? extends Tuple> getAllMatches(Object[] parameters) {
+ try {
+ final LocalSearchMatcher matcher = initializeMatcher(parameters);
+ final MatchingFrame frame = matcher.editableMatchingFrame();
+ frame.setParameterValues(parameters);
+ return matcher.getAllMatches(frame);
+ } catch (LocalSearchException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public IQueryBackend getQueryBackend() {
+ return backend;
+ }
+
+ @Override
+ public void addUpdateListener(IUpdateable listener, Object listenerTag, boolean fireNow) {
+ // throw new UnsupportedOperationException(UPDATE_LISTENER_NOT_SUPPORTED);
+ }
+
+ @Override
+ public void removeUpdateListener(Object listenerTag) {
+ // throw new UnsupportedOperationException(UPDATE_LISTENER_NOT_SUPPORTED);
+ }
+
+ /**
+ * @since 1.4
+ */
+ public IMatcherCapability getCapabilites() {
+ LocalSearchHints configuration = overrideDefaultHints(query);
+ return configuration;
+ }
+
+} \ No newline at end of file
diff --git a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/GenericLocalSearchResultProvider.java b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/GenericLocalSearchResultProvider.java
new file mode 100644
index 000000000..093dc0f1e
--- /dev/null
+++ b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/GenericLocalSearchResultProvider.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2010-2015, Marton Bur, Zoltan Ujhelyi, Istvan Rath and Daniel Varro
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marton Bur, Zoltan Ujhelyi - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.viatra.query.runtime.localsearch.matcher.integration;
+
+import org.eclipse.viatra.query.runtime.localsearch.plan.IPlanProvider;
+import org.eclipse.viatra.query.runtime.localsearch.planner.compiler.GenericOperationCompiler;
+import org.eclipse.viatra.query.runtime.localsearch.planner.compiler.IOperationCompiler;
+import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint;
+import org.eclipse.viatra.query.runtime.matchers.context.IQueryBackendContext;
+import org.eclipse.viatra.query.runtime.matchers.context.IndexingService;
+import org.eclipse.viatra.query.runtime.matchers.planning.QueryProcessingException;
+import org.eclipse.viatra.query.runtime.matchers.psystem.PBody;
+import org.eclipse.viatra.query.runtime.matchers.psystem.PConstraint;
+import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint;
+import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery;
+
+/**
+ * @author Zoltan Ujhelyi
+ * @since 1.7
+ *
+ */
+public class GenericLocalSearchResultProvider extends AbstractLocalSearchResultProvider {
+
+ public GenericLocalSearchResultProvider(LocalSearchBackend backend, IQueryBackendContext context, PQuery query,
+ IPlanProvider planProvider, QueryEvaluationHint userHints) throws QueryProcessingException {
+ super(backend, context, query, planProvider, userHints);
+ }
+
+ @Override
+ protected void indexInitializationBeforePlanning() throws QueryProcessingException {
+ super.indexInitializationBeforePlanning();
+
+ for (PBody body : query.getDisjunctBodies().getBodies()) {
+ for (PConstraint constraint : body.getConstraints()) {
+ if (constraint instanceof TypeConstraint) {
+ runtimeContext.ensureIndexed(((TypeConstraint) constraint).getSupplierKey(), IndexingService.INSTANCES);
+ }
+ }
+ }
+ }
+
+ @Override
+ protected IOperationCompiler getOperationCompiler(IQueryBackendContext backendContext,
+ LocalSearchHints configuration) {
+ return new GenericOperationCompiler(runtimeContext);
+ }
+
+}
diff --git a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchBackend.java b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchBackend.java
index 0441b7f7b..24e3674d1 100644
--- a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchBackend.java
+++ b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchBackend.java
@@ -41,19 +41,23 @@ import com.google.common.collect.Table;
/**
* @author Marton Bur, Zoltan Ujhelyi
- *
+ * @noextend This class is not intended to be subclassed by clients.
*/
-public class LocalSearchBackend implements IQueryBackend {
+public abstract class LocalSearchBackend implements IQueryBackend {
IQueryBackendContext context;
IPlanProvider planProvider;
private final Set<ILocalSearchAdapter> adapters = Sets.newHashSet();
// Cache
- private final Table<EDataType, EClass, Set<EAttribute>> eAttributesByTypeForEClass;
+ /*
+ * @deprecated Use generalCache instead
+ */
+ @Deprecated
+ private final Table<EDataType, EClass, Set<EAttribute>> eAttributesByTypeForEClass = HashBasedTable.create();
private final PurgableCache generalCache;
- private final Multimap<PQuery, LocalSearchResultProvider> resultProviderCache = ArrayListMultimap.create();
+ private final Multimap<PQuery, AbstractLocalSearchResultProvider> resultProviderCache = ArrayListMultimap.create();
/**
* @since 1.5
@@ -61,7 +65,6 @@ public class LocalSearchBackend implements IQueryBackend {
public LocalSearchBackend(IQueryBackendContext context) {
super();
this.context = context;
- this.eAttributesByTypeForEClass = HashBasedTable.create();
this.generalCache = new PurgableCache();
this.planProvider = new CachingPlanProvider(context.getLogger());
}
@@ -84,18 +87,24 @@ public class LocalSearchBackend implements IQueryBackend {
throws QueryProcessingException {
IMatcherCapability requestedCapability = getHintProvider().getQueryEvaluationHint(query).overrideBy(hints).calculateRequiredCapability(query);
- for(LocalSearchResultProvider existingResultProvider : resultProviderCache.get(query)){
+ for(AbstractLocalSearchResultProvider existingResultProvider : resultProviderCache.get(query)){
if (requestedCapability.canBeSubstitute(existingResultProvider.getCapabilites())){
return existingResultProvider;
}
}
- LocalSearchResultProvider resultProvider = new LocalSearchResultProvider(this, context, query, planProvider, hints);
+ AbstractLocalSearchResultProvider resultProvider = initializeResultProvider(query, hints);
resultProviderCache.put(query, resultProvider);
resultProvider.prepare();
return resultProvider;
}
+ /**
+ * @throws QueryProcessingException
+ * @since 1.7
+ */
+ protected abstract AbstractLocalSearchResultProvider initializeResultProvider(PQuery query, QueryEvaluationHint hints) throws QueryProcessingException;
+
@Override
public void dispose() {
eAttributesByTypeForEClass.clear();
@@ -113,6 +122,11 @@ public class LocalSearchBackend implements IQueryBackend {
return null;
}
+ /**
+ *
+ * @deprecated use the general caching mechanism instead
+ */
+ @Deprecated
public Table<EDataType, EClass, Set<EAttribute>> geteAttributesByTypeForEClass() {
return eAttributesByTypeForEClass;
}
diff --git a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchBackendFactory.java b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchBackendFactory.java
index 25490b5e5..0d73caa92 100644
--- a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchBackendFactory.java
+++ b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchBackendFactory.java
@@ -15,6 +15,7 @@ import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackend;
import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackendFactory;
import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint;
import org.eclipse.viatra.query.runtime.matchers.context.IQueryBackendContext;
+import org.eclipse.viatra.query.runtime.matchers.planning.QueryProcessingException;
import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery;
/**
@@ -30,7 +31,13 @@ public enum LocalSearchBackendFactory implements IQueryBackendFactory {
*/
@Override
public IQueryBackend create(IQueryBackendContext context) {
- return new LocalSearchBackend(context);
+ return new LocalSearchBackend(context) {
+
+ @Override
+ protected AbstractLocalSearchResultProvider initializeResultProvider(PQuery query, QueryEvaluationHint hints) throws QueryProcessingException {
+ return new LocalSearchResultProvider(this, context, query, planProvider, hints);
+ }
+ };
}
@Override
diff --git a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchGenericBackendFactory.java b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchGenericBackendFactory.java
new file mode 100644
index 000000000..5630994fb
--- /dev/null
+++ b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchGenericBackendFactory.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2010-2015, Marton Bur, Zoltan Ujhelyi, Istvan Rath and Daniel Varro
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marton Bur, Zoltan Ujhelyi - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.viatra.query.runtime.localsearch.matcher.integration;
+
+import java.util.Set;
+
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EDataType;
+import org.eclipse.viatra.query.runtime.matchers.backend.IMatcherCapability;
+import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackend;
+import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackendFactory;
+import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint;
+import org.eclipse.viatra.query.runtime.matchers.context.IQueryBackendContext;
+import org.eclipse.viatra.query.runtime.matchers.planning.QueryProcessingException;
+import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery;
+
+import com.google.common.collect.Table;
+
+/**
+ * @author Marton Bur, Zoltan Ujhelyi
+ * @since 1.7
+ *
+ */
+public enum LocalSearchGenericBackendFactory implements IQueryBackendFactory {
+
+ INSTANCE;
+
+ /**
+ * @since 1.5
+ */
+ @Override
+ public IQueryBackend create(IQueryBackendContext context) {
+ return new LocalSearchBackend(context) {
+
+ @Override
+ protected AbstractLocalSearchResultProvider initializeResultProvider(PQuery query, QueryEvaluationHint hints) throws QueryProcessingException {
+ return new GenericLocalSearchResultProvider(this, context, query, planProvider, hints);
+ }
+
+ @Override
+ public Table<EDataType, EClass, Set<EAttribute>> geteAttributesByTypeForEClass() {
+ throw new UnsupportedOperationException("geteAttributesByTypeForEClass() is a legacy call not supported by the generic LS backend.");
+ }
+
+
+ };
+ }
+
+ @Override
+ public Class<? extends IQueryBackend> getBackendClass() {
+ return LocalSearchBackend.class;
+ }
+
+ /**
+ * @since 1.4
+ */
+ @Override
+ public IMatcherCapability calculateRequiredCapability(PQuery query, QueryEvaluationHint hint) {
+ return LocalSearchHints.parse(hint);
+ }
+
+}
diff --git a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchHints.java b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchHints.java
index da84b3f58..ea7c1af9a 100644
--- a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchHints.java
+++ b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchHints.java
@@ -23,6 +23,7 @@ import org.eclipse.viatra.query.runtime.localsearch.planner.cost.ICostFunction;
import org.eclipse.viatra.query.runtime.localsearch.planner.cost.impl.IndexerBasedConstraintCostFunction;
import org.eclipse.viatra.query.runtime.localsearch.planner.cost.impl.VariableBindingBasedCostFunction;
import org.eclipse.viatra.query.runtime.matchers.backend.IMatcherCapability;
+import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackendFactory;
import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint;
import org.eclipse.viatra.query.runtime.matchers.backend.QueryHintOption;
import org.eclipse.viatra.query.runtime.matchers.psystem.rewriters.DefaultFlattenCallPredicate;
@@ -55,6 +56,8 @@ public final class LocalSearchHints implements IMatcherCapability {
private IRewriterTraceCollector traceCollector = NopTraceCollector.INSTANCE;
+ private IQueryBackendFactory backendFactory = null;
+
private LocalSearchHints() {}
/**
@@ -74,6 +77,7 @@ public final class LocalSearchHints implements IMatcherCapability {
result.costFunction = PLANNER_COST_FUNCTION.getDefaultValue();
result.flattenCallPredicate = FLATTEN_CALL_PREDICATE.getDefaultValue();
result.adornmentProvider = ADORNMENT_PROVIDER.getDefaultValue();
+ result.backendFactory = LocalSearchBackendFactory.INSTANCE;
return result;
}
@@ -88,6 +92,7 @@ public final class LocalSearchHints implements IMatcherCapability {
result.costFunction = new IndexerBasedConstraintCostFunction();
result.flattenCallPredicate = new DefaultFlattenCallPredicate();
result.adornmentProvider = ADORNMENT_PROVIDER.getDefaultValue();
+ result.backendFactory = LocalSearchBackendFactory.INSTANCE;
return result;
}
@@ -101,6 +106,22 @@ public final class LocalSearchHints implements IMatcherCapability {
result.costFunction = new VariableBindingBasedCostFunction();
result.flattenCallPredicate = new NeverFlattenCallPredicate();
result.adornmentProvider = ADORNMENT_PROVIDER.getDefaultValue();
+ result.backendFactory = LocalSearchBackendFactory.INSTANCE;
+ return result;
+ }
+
+ /**
+ * Initializes the generic (not EMF specific) search backend with the default settings
+ * @since 1.7
+ */
+ public static LocalSearchHints getDefaultGeneric(){
+ LocalSearchHints result = new LocalSearchHints();
+ result.useBase = false;
+ result.rowCount = 4;
+ result.costFunction = new VariableBindingBasedCostFunction();
+ result.flattenCallPredicate = new NeverFlattenCallPredicate();
+ result.adornmentProvider = ADORNMENT_PROVIDER.getDefaultValue();
+ result.backendFactory = LocalSearchGenericBackendFactory.INSTANCE;
return result;
}
@@ -138,7 +159,7 @@ public final class LocalSearchHints implements IMatcherCapability {
if (traceCollector != null){
normalizationTraceCollector.insertOverridingValue(map, traceCollector);
}
- return new QueryEvaluationHint(map, LocalSearchBackendFactory.INSTANCE);
+ return new QueryEvaluationHint(map, backendFactory);
}
public boolean isUseBase() {
diff --git a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchResultProvider.java b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchResultProvider.java
index fa2b98ef8..c379b0e57 100644
--- a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchResultProvider.java
+++ b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchResultProvider.java
@@ -10,125 +10,23 @@
*******************************************************************************/
package org.eclipse.viatra.query.runtime.localsearch.matcher.integration;
-import java.lang.reflect.InvocationTargetException;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.Queue;
-import java.util.Set;
-import java.util.concurrent.Callable;
-
-import org.eclipse.viatra.query.runtime.exception.ViatraQueryException;
-import org.eclipse.viatra.query.runtime.localsearch.MatchingFrame;
-import org.eclipse.viatra.query.runtime.localsearch.exceptions.LocalSearchException;
-import org.eclipse.viatra.query.runtime.localsearch.matcher.ISearchContext;
-import org.eclipse.viatra.query.runtime.localsearch.matcher.LocalSearchMatcher;
-import org.eclipse.viatra.query.runtime.localsearch.matcher.MatcherReference;
-import org.eclipse.viatra.query.runtime.localsearch.plan.IPlanDescriptor;
import org.eclipse.viatra.query.runtime.localsearch.plan.IPlanProvider;
-import org.eclipse.viatra.query.runtime.localsearch.plan.SearchPlan;
-import org.eclipse.viatra.query.runtime.localsearch.plan.SearchPlanExecutor;
-import org.eclipse.viatra.query.runtime.localsearch.planner.util.SearchPlanForBody;
-import org.eclipse.viatra.query.runtime.matchers.backend.IMatcherCapability;
-import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackend;
-import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackendHintProvider;
-import org.eclipse.viatra.query.runtime.matchers.backend.IQueryResultProvider;
-import org.eclipse.viatra.query.runtime.matchers.backend.IUpdateable;
+import org.eclipse.viatra.query.runtime.localsearch.planner.compiler.EMFOperationCompiler;
+import org.eclipse.viatra.query.runtime.localsearch.planner.compiler.IOperationCompiler;
import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint;
-import org.eclipse.viatra.query.runtime.matchers.backend.QueryHintOption;
-import org.eclipse.viatra.query.runtime.matchers.context.IInputKey;
import org.eclipse.viatra.query.runtime.matchers.context.IQueryBackendContext;
-import org.eclipse.viatra.query.runtime.matchers.context.IQueryResultProviderAccess;
-import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContext;
import org.eclipse.viatra.query.runtime.matchers.context.IndexingService;
import org.eclipse.viatra.query.runtime.matchers.planning.QueryProcessingException;
-import org.eclipse.viatra.query.runtime.matchers.psystem.PBody;
-import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall;
-import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter;
import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery;
-import org.eclipse.viatra.query.runtime.matchers.psystem.rewriters.IFlattenCallPredicate;
-import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple;
-
-import com.google.common.base.Function;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.Iterators;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
/**
* @author Marton Bur, Zoltan Ujhelyi
*
*/
-public class LocalSearchResultProvider implements IQueryResultProvider {
-
- private final LocalSearchBackend backend;
- private final IQueryBackendHintProvider hintProvider;
- private final IQueryRuntimeContext runtimeContext;
- private final PQuery query;
- private final IQueryResultProviderAccess resultProviderAccess;
- private final QueryEvaluationHint userHints;
-
- private final IPlanProvider planProvider;
- private final ISearchContext searchContext;
-
- private IQueryRuntimeContext getRuntimeContext(){
- return ((LocalSearchBackend)backend).getRuntimeContext();
- }
-
- private LocalSearchMatcher createMatcher(IPlanDescriptor plan, final ISearchContext searchContext){
- Collection<SearchPlanForBody> compiledPlans = Lists.newArrayList(plan.getPlan());
-
- Collection<SearchPlanExecutor> executors = Collections2.transform(compiledPlans,
- new Function<SearchPlanForBody, SearchPlanExecutor>() {
-
- @Override
- public SearchPlanExecutor apply(SearchPlanForBody input) {
- final SearchPlan plan = new SearchPlan();
- plan.addOperations(input.getCompiledOperations());
-
- return new SearchPlanExecutor(plan, searchContext, input.getVariableKeys());
- }
- });
-
- final Collection<Integer> parameterSizes = Collections2.transform(compiledPlans,
- new Function<SearchPlanForBody, Integer>() {
-
- @Override
- public Integer apply(SearchPlanForBody input) {
- PBody body = input.getBody();
- return body.getUniqueVariables().size();
- // return Math.max(input.getSymbolicParameters().size(), input.getUniqueVariables().size());
- }
- });
-
- return new LocalSearchMatcher(plan, executors,
- Collections.max(parameterSizes));
- }
-
- private IPlanDescriptor createPlan(MatcherReference key, IPlanProvider planProvider) throws QueryProcessingException {
- LocalSearchHints configuration = overrideDefaultHints(key.getQuery());
- IPlanDescriptor plan = planProvider.getPlan(backend.getBackendContext(), configuration, key);
- return plan;
- }
-
-
- private LocalSearchHints overrideDefaultHints(PQuery pQuery) {
- return LocalSearchHints.getDefaultOverriddenBy(
- computeOverridingHints(pQuery));
- }
-
- /**
- * Combine with {@link QueryHintOption#getValueOrDefault(QueryEvaluationHint)} to access
- * hint settings not covered by {@link LocalSearchHints}
- */
- private QueryEvaluationHint computeOverridingHints(PQuery pQuery) {
- return hintProvider.getQueryEvaluationHint(pQuery).overrideBy(userHints);
- }
+public class LocalSearchResultProvider extends AbstractLocalSearchResultProvider {
/**
- * @throws QueryProcessingException
+ * @throws QueryProcessingException
* @since 1.5
*/
public LocalSearchResultProvider(LocalSearchBackend backend, IQueryBackendContext context, PQuery query,
@@ -136,239 +34,24 @@ public class LocalSearchResultProvider implements IQueryResultProvider {
this(backend, context, query, planProvider, null);
}
- private Iterator<MatcherReference> computeExpectedAdornments(){
- return Iterators.transform(overrideDefaultHints(query).getAdornmentProvider().getAdornments(query).iterator(), new Function<Set<PParameter>, MatcherReference>() {
-
- @Override
- public MatcherReference apply(Set<PParameter> input) {
- return new MatcherReference(query, input, userHints);
- }
- });
- }
-
/**
- * @throws QueryProcessingException
+ * @throws QueryProcessingException
* @since 1.5
*/
public LocalSearchResultProvider(LocalSearchBackend backend, IQueryBackendContext context, PQuery query,
IPlanProvider planProvider, QueryEvaluationHint userHints) throws QueryProcessingException {
- this.backend = backend;
- this.resultProviderAccess = context.getResultProviderAccess();
- this.hintProvider = context.getHintProvider();
- this.query = query;
-
- this.planProvider = planProvider;
- this.userHints = userHints;
- this.runtimeContext = context.getRuntimeContext();
-
- this.searchContext = new ISearchContext.SearchContext(context, userHints, backend.getCache());
- }
-
- /**
- * Prepare this result provider. This phase is separated from the constructor to allow the backend to cache its instance before
- * requesting preparation for its dependencies.
- * @since 1.5
- */
- public void prepare() throws QueryProcessingException{
- try {
- runtimeContext.coalesceTraversals(new Callable<Void>() {
-
- @Override
- public Void call() throws Exception {
- runtimeContext.ensureWildcardIndexing(IndexingService.STATISTICS);
- prepareDirectDependencies();
- runtimeContext.executeAfterTraversal(new Runnable() {
-
- @Override
- public void run() {
- try {
- preparePlansForExpectedAdornments();
- } catch (QueryProcessingException e) {
- throw new RuntimeException(e);
- }
- }
- });
- return null;
- }
- });
- } catch (InvocationTargetException e) {
- throw new QueryProcessingException("Error while building required indexes: %s", new String[]{e.getTargetException().getMessage()}, "Error while building required indexes.", query, e);
- }
- }
-
- private void preparePlansForExpectedAdornments() throws QueryProcessingException{
- // Plan for possible adornments
- Iterator<MatcherReference> iterator = computeExpectedAdornments();
- while(iterator.hasNext()){
- IPlanDescriptor plan = planProvider.getPlan(backend.getBackendContext(), overrideDefaultHints(query), iterator.next());
- // Index keys
- try {
- indexKeys(plan.getIteratedKeys());
- } catch (InvocationTargetException e) {
- throw new QueryProcessingException(e.getMessage(), null, e.getMessage(), query, e);
- }
- //Prepare dependencies
- for(SearchPlanForBody body: plan.getPlan()){
- for(MatcherReference dependency : body.getDependencies()){
- try {
- searchContext.getMatcher(dependency);
- } catch (LocalSearchException e) {
- throw new QueryProcessingException("Could not prepare dependency {1}", new String[]{dependency.toString()}, e.getMessage(), query, e);
- }
- }
- }
- }
-
- }
-
- private void prepareDirectDependencies() throws QueryProcessingException{
- // Do not prepare for any adornment at this point
- IAdornmentProvider adornmentProvider = new IAdornmentProvider() {
-
- @Override
- public Iterable<Set<PParameter>> getAdornments(PQuery query) {
- return Collections.emptySet();
- }
- };
- @SuppressWarnings("rawtypes")
- QueryEvaluationHint hints = new QueryEvaluationHint(Collections.<QueryHintOption, Object>singletonMap(LocalSearchHintOptions.ADORNMENT_PROVIDER, adornmentProvider), null);
- for(PQuery dep : getDirectPositiveDependencies()){
- resultProviderAccess.getResultProvider(dep, hints);
- }
- }
-
- private Set<PQuery> getDirectPositiveDependencies(){
- IFlattenCallPredicate flattenPredicate = overrideDefaultHints(query).getFlattenCallPredicate();
- Queue<PQuery> queue = new LinkedList<PQuery>();
- Set<PQuery> visited = new HashSet<PQuery>();
- Set<PQuery> result = new HashSet<PQuery>();
- queue.add(query);
-
- while(!queue.isEmpty()){
- PQuery next = queue.poll();
- visited.add(next);
- for(PBody body : next.getDisjunctBodies().getBodies()){
- for(PositivePatternCall ppc : body.getConstraintsOfType(PositivePatternCall.class)){
- PQuery dep = ppc.getSupplierKey();
- if (flattenPredicate.shouldFlatten(ppc)){
- if (!visited.contains(dep)){
- queue.add(dep);
- }
- }else{
- result.add(dep);
- }
- }
- }
- }
- return result;
- }
-
- private LocalSearchMatcher initializeMatcher(Object[] parameters) {
- try {
- return newLocalSearchMatcher(parameters);
- } catch (QueryProcessingException | ViatraQueryException e) {
- throw new RuntimeException(e);
- }
-
- }
-
- public LocalSearchMatcher newLocalSearchMatcher(Object[] parameters)
- throws ViatraQueryException, QueryProcessingException {
-
- final Set<PParameter> adornment = Sets.newHashSet();
- for (int i = 0; i < parameters.length; i++) {
- if (parameters[i] != null) {
- adornment.add(query.getParameters().get(i));
- }
- }
-
- final MatcherReference reference = new MatcherReference(query, adornment, userHints);
-
- IPlanDescriptor plan = createPlan(reference, planProvider);
- if (overrideDefaultHints(reference.getQuery()).isUseBase()){
- try {
- indexKeys(plan.getIteratedKeys());
- } catch (InvocationTargetException e) {
- throw new ViatraQueryException("Could not index keys","Could not index keys", e);
- }
- }
-
- LocalSearchMatcher matcher = createMatcher(plan, searchContext);
- matcher.addAdapters(backend.getAdapters());
- return matcher;
- }
-
- private void indexKeys(final Iterable<IInputKey> keys) throws InvocationTargetException{
- final IQueryRuntimeContext qrc = getRuntimeContext();
- qrc.coalesceTraversals(new Callable<Void>() {
-
- @Override
- public Void call() throws Exception {
- for(IInputKey key : keys){
- qrc.ensureIndexed(key, IndexingService.INSTANCES);
- }
- return null;
- }
- });
- }
-
- @Override
- public Tuple getOneArbitraryMatch(Object[] parameters) {
- try {
- final LocalSearchMatcher matcher = initializeMatcher(parameters);
- final MatchingFrame frame = matcher.editableMatchingFrame();
- frame.setParameterValues(parameters);
- return matcher.getOneArbitraryMatch(frame);
- } catch (LocalSearchException e) {
- throw new RuntimeException(e);
- }
- }
-
- @Override
- public int countMatches(Object[] parameters) {
- try {
- final LocalSearchMatcher matcher = initializeMatcher(parameters);
- final MatchingFrame frame = matcher.editableMatchingFrame();
- frame.setParameterValues(parameters);
- return matcher.countMatches(frame);
- } catch (LocalSearchException e) {
- throw new RuntimeException(e);
- }
- }
-
- @Override
- public Collection<? extends Tuple> getAllMatches(Object[] parameters) {
- try {
- final LocalSearchMatcher matcher = initializeMatcher(parameters);
- final MatchingFrame frame = matcher.editableMatchingFrame();
- frame.setParameterValues(parameters);
- return matcher.getAllMatches(frame);
- } catch (LocalSearchException e) {
- throw new RuntimeException(e);
- }
+ super(backend, context, query, planProvider, userHints);
}
@Override
- public IQueryBackend getQueryBackend() {
- return backend;
+ protected void indexInitializationBeforePlanning() throws QueryProcessingException {
+ super.indexInitializationBeforePlanning();
+ runtimeContext.ensureWildcardIndexing(IndexingService.STATISTICS);
}
@Override
- public void addUpdateListener(IUpdateable listener, Object listenerTag, boolean fireNow) {
- // throw new UnsupportedOperationException(UPDATE_LISTENER_NOT_SUPPORTED);
- }
-
- @Override
- public void removeUpdateListener(Object listenerTag) {
- // throw new UnsupportedOperationException(UPDATE_LISTENER_NOT_SUPPORTED);
- }
-
- /**
- * @since 1.4
- */
- public IMatcherCapability getCapabilites() {
- LocalSearchHints configuration = overrideDefaultHints(query);
- return configuration;
+ protected IOperationCompiler getOperationCompiler(IQueryBackendContext backendContext,
+ LocalSearchHints configuration) {
+ return new EMFOperationCompiler(runtimeContext, configuration.isUseBase());
}
-
}
diff --git a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/plan/CachingPlanProvider.java b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/plan/CachingPlanProvider.java
index 5cf34a649..43fefd5e2 100644
--- a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/plan/CachingPlanProvider.java
+++ b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/plan/CachingPlanProvider.java
@@ -17,6 +17,8 @@ import org.eclipse.viatra.query.runtime.localsearch.matcher.MatcherReference;
import org.eclipse.viatra.query.runtime.localsearch.matcher.integration.LocalSearchBackend;
import org.eclipse.viatra.query.runtime.localsearch.matcher.integration.LocalSearchHints;
import org.eclipse.viatra.query.runtime.localsearch.planner.LocalSearchPlanner;
+import org.eclipse.viatra.query.runtime.localsearch.planner.compiler.EMFOperationCompiler;
+import org.eclipse.viatra.query.runtime.localsearch.planner.compiler.IOperationCompiler;
import org.eclipse.viatra.query.runtime.localsearch.planner.util.SearchPlanForBody;
import org.eclipse.viatra.query.runtime.matchers.context.IQueryBackendContext;
import org.eclipse.viatra.query.runtime.matchers.planning.QueryProcessingException;
@@ -47,11 +49,12 @@ public class CachingPlanProvider implements IPlanProvider {
@Deprecated
public IPlanDescriptor getPlan(LocalSearchBackend backend, final LocalSearchHints configuration, MatcherReference key)
throws QueryProcessingException {
- return getPlan(backend.getBackendContext(), configuration, key);
+ IOperationCompiler compiler = new EMFOperationCompiler(backend.getRuntimeContext(), configuration.isUseBase());
+ return getPlan(backend.getBackendContext(), compiler, configuration, key);
}
@Override
- public IPlanDescriptor getPlan(IQueryBackendContext backend, final LocalSearchHints configuration, MatcherReference key)
+ public IPlanDescriptor getPlan(IQueryBackendContext backend, IOperationCompiler compiler, final LocalSearchHints configuration, MatcherReference key)
throws QueryProcessingException {
if (cache.containsKey(key)){
@@ -59,7 +62,7 @@ public class CachingPlanProvider implements IPlanProvider {
return cache.get(key).iterator().next();
}else{
- LocalSearchPlanner planner = new LocalSearchPlanner(backend, logger, configuration);
+ LocalSearchPlanner planner = new LocalSearchPlanner(backend, compiler, logger, configuration);
Collection<SearchPlanForBody> plansForBodies = planner.plan(key.getQuery(), key.getAdornment());
diff --git a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/plan/IPlanProvider.java b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/plan/IPlanProvider.java
index 029671f61..6d759d30c 100644
--- a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/plan/IPlanProvider.java
+++ b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/plan/IPlanProvider.java
@@ -12,6 +12,7 @@ package org.eclipse.viatra.query.runtime.localsearch.plan;
import org.eclipse.viatra.query.runtime.localsearch.matcher.MatcherReference;
import org.eclipse.viatra.query.runtime.localsearch.matcher.integration.LocalSearchHints;
+import org.eclipse.viatra.query.runtime.localsearch.planner.compiler.IOperationCompiler;
import org.eclipse.viatra.query.runtime.matchers.context.IQueryBackendContext;
import org.eclipse.viatra.query.runtime.matchers.planning.QueryProcessingException;
@@ -25,6 +26,6 @@ public interface IPlanProvider {
/**
* @since 1.7
*/
- public IPlanDescriptor getPlan(IQueryBackendContext backend, LocalSearchHints configuration, MatcherReference key) throws QueryProcessingException;
+ public IPlanDescriptor getPlan(IQueryBackendContext backend, IOperationCompiler compiler, LocalSearchHints configuration, MatcherReference key) throws QueryProcessingException;
}
diff --git a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/ILocalSearchPlanner.java b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/ILocalSearchPlanner.java
new file mode 100644
index 000000000..1cd3e68ca
--- /dev/null
+++ b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/ILocalSearchPlanner.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2010-2017, Zoltan Ujhelyi, IncQuery Labs Ltd.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Zoltan Ujhelyi - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.viatra.query.runtime.localsearch.planner;
+
+import java.util.Collection;
+import java.util.Set;
+
+import org.eclipse.viatra.query.runtime.localsearch.planner.util.SearchPlanForBody;
+import org.eclipse.viatra.query.runtime.matchers.planning.QueryProcessingException;
+import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter;
+import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery;
+
+/**
+ * @author Zoltan Ujhelyi
+ * @since 1.7
+ */
+public interface ILocalSearchPlanner {
+
+ /**
+ * Creates executable plans for the provided query. It is required to call one of the
+ * <code>initializePlanner()</code> methods before calling this method.
+ *
+ * @param querySpec
+ * @param boundParameters
+ * a set of bound parameters
+ * @return a mapping between ISearchOperation list and a mapping, that holds a PVariable-Integer mapping for the
+ * list of ISearchOperations
+ * @throws QueryProcessingException
+ */
+ Collection<SearchPlanForBody> plan(PQuery querySpec, Set<PParameter> boundParameters)
+ throws QueryProcessingException;
+
+} \ No newline at end of file
diff --git a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/LocalSearchPlanner.java b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/LocalSearchPlanner.java
index 8f7c122a8..8559a52bb 100644
--- a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/LocalSearchPlanner.java
+++ b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/LocalSearchPlanner.java
@@ -19,6 +19,8 @@ import org.apache.log4j.Logger;
import org.eclipse.viatra.query.runtime.localsearch.matcher.integration.LocalSearchBackend;
import org.eclipse.viatra.query.runtime.localsearch.matcher.integration.LocalSearchHints;
import org.eclipse.viatra.query.runtime.localsearch.operations.ISearchOperation;
+import org.eclipse.viatra.query.runtime.localsearch.planner.compiler.EMFOperationCompiler;
+import org.eclipse.viatra.query.runtime.localsearch.planner.compiler.IOperationCompiler;
import org.eclipse.viatra.query.runtime.localsearch.planner.util.SearchPlanForBody;
import org.eclipse.viatra.query.runtime.matchers.context.IQueryBackendContext;
import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContext;
@@ -43,13 +45,14 @@ import com.google.common.collect.Sets;
* @author Marton Bur
* @noreference This class is not intended to be referenced by clients.
*/
-public class LocalSearchPlanner {
+public class LocalSearchPlanner implements ILocalSearchPlanner {
// Externally set tools for planning
private final PDisjunctionRewriter preprocessor;
private final LocalSearchRuntimeBasedStrategy plannerStrategy;
private final IQueryRuntimeContext runtimeContext;
private final LocalSearchHints configuration;
+ private final IOperationCompiler operationCompiler;
private final IQueryBackendContext context;
// private final LocalSearchBackend backend;
@@ -59,16 +62,19 @@ public class LocalSearchPlanner {
*/
@Deprecated
public LocalSearchPlanner(LocalSearchBackend backend, Logger logger, final LocalSearchHints configuration) {
- this(backend.getBackendContext(), logger, configuration);
+ this(backend.getBackendContext(),
+ new EMFOperationCompiler(backend.getRuntimeContext(), configuration.isUseBase()), logger,
+ configuration);
}
/**
* @since 1.7
*/
- public LocalSearchPlanner(IQueryBackendContext backendContext, Logger logger, final LocalSearchHints configuration) {
+ public LocalSearchPlanner(IQueryBackendContext backendContext, IOperationCompiler compiler, Logger logger, final LocalSearchHints configuration) {
this.runtimeContext = backendContext.getRuntimeContext();
this.configuration = configuration;
+ this.operationCompiler = compiler;
PQueryFlattener flattener = new PQueryFlattener(configuration.getFlattenCallPredicate());
/*
* TODO https://bugs.eclipse.org/bugs/show_bug.cgi?id=439358: The normalizer is initialized with the false
@@ -102,6 +108,7 @@ public class LocalSearchPlanner {
* list of ISearchOperations
* @throws QueryProcessingException
*/
+ @Override
public Collection<SearchPlanForBody> plan(PQuery querySpec, Set<PParameter> boundParameters)
throws QueryProcessingException {
// 1. Preparation
@@ -117,7 +124,6 @@ public class LocalSearchPlanner {
SubPlan plan = plannerStrategy.plan(normalizedBody, boundVariables, context, configuration);
// 3. PConstraint -> POperation compilation step
// * Pay extra caution to extend operations, when more than one variables are unbound
- POperationCompiler operationCompiler = new POperationCompiler(runtimeContext, configuration.isUseBase());
List<ISearchOperation> compiledOperations = operationCompiler.compile(plan, boundParameters);
// Store the variable mappings for the plans for debug purposes (traceability information)
SearchPlanForBody compiledPlan = new SearchPlanForBody(normalizedBody,
diff --git a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/POperationCompiler.java b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/POperationCompiler.java
index 2d8f393f1..a2b2f3cdd 100644
--- a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/POperationCompiler.java
+++ b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/POperationCompiler.java
@@ -10,563 +10,24 @@
*******************************************************************************/
package org.eclipse.viatra.query.runtime.localsearch.planner;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.eclipse.emf.ecore.EReference;
-import org.eclipse.emf.ecore.EStructuralFeature;
-import org.eclipse.viatra.query.runtime.emf.EMFQueryRuntimeContext;
-import org.eclipse.viatra.query.runtime.emf.types.EClassTransitiveInstancesKey;
-import org.eclipse.viatra.query.runtime.emf.types.EClassUnscopedTransitiveInstancesKey;
-import org.eclipse.viatra.query.runtime.emf.types.EDataTypeInSlotsKey;
-import org.eclipse.viatra.query.runtime.emf.types.EStructuralFeatureInstancesKey;
-import org.eclipse.viatra.query.runtime.localsearch.matcher.MatcherReference;
-import org.eclipse.viatra.query.runtime.localsearch.operations.ISearchOperation;
-import org.eclipse.viatra.query.runtime.localsearch.operations.check.AggregatorCheck;
-import org.eclipse.viatra.query.runtime.localsearch.operations.check.BinaryTransitiveClosureCheck;
-import org.eclipse.viatra.query.runtime.localsearch.operations.check.CheckConstant;
-import org.eclipse.viatra.query.runtime.localsearch.operations.check.CheckPositivePatternCall;
-import org.eclipse.viatra.query.runtime.localsearch.operations.check.CountCheck;
-import org.eclipse.viatra.query.runtime.localsearch.operations.check.ExpressionCheck;
-import org.eclipse.viatra.query.runtime.localsearch.operations.check.ExpressionEvalCheck;
-import org.eclipse.viatra.query.runtime.localsearch.operations.check.InequalityCheck;
-import org.eclipse.viatra.query.runtime.localsearch.operations.check.InstanceOfClassCheck;
-import org.eclipse.viatra.query.runtime.localsearch.operations.check.InstanceOfDataTypeCheck;
-import org.eclipse.viatra.query.runtime.localsearch.operations.check.InstanceOfJavaClassCheck;
-import org.eclipse.viatra.query.runtime.localsearch.operations.check.NACOperation;
-import org.eclipse.viatra.query.runtime.localsearch.operations.check.StructuralFeatureCheck;
-import org.eclipse.viatra.query.runtime.localsearch.operations.check.nobase.ScopeCheck;
-import org.eclipse.viatra.query.runtime.localsearch.operations.extend.AggregatorExtend;
-import org.eclipse.viatra.query.runtime.localsearch.operations.extend.CountOperation;
-import org.eclipse.viatra.query.runtime.localsearch.operations.extend.ExpressionEval;
-import org.eclipse.viatra.query.runtime.localsearch.operations.extend.ExtendBinaryTransitiveClosure;
-import org.eclipse.viatra.query.runtime.localsearch.operations.extend.ExtendConstant;
-import org.eclipse.viatra.query.runtime.localsearch.operations.extend.ExtendPositivePatternCall;
-import org.eclipse.viatra.query.runtime.localsearch.operations.extend.ExtendToEStructuralFeatureSource;
-import org.eclipse.viatra.query.runtime.localsearch.operations.extend.ExtendToEStructuralFeatureTarget;
-import org.eclipse.viatra.query.runtime.localsearch.operations.extend.IterateOverContainers;
-import org.eclipse.viatra.query.runtime.localsearch.operations.extend.IterateOverEClassInstances;
-import org.eclipse.viatra.query.runtime.localsearch.operations.extend.IterateOverEDatatypeInstances;
-import org.eclipse.viatra.query.runtime.localsearch.planner.util.CompilerHelper;
-import org.eclipse.viatra.query.runtime.matchers.context.IInputKey;
+import org.eclipse.viatra.query.runtime.localsearch.planner.compiler.EMFOperationCompiler;
import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContext;
-import org.eclipse.viatra.query.runtime.matchers.context.common.JavaTransitiveInstancesKey;
-import org.eclipse.viatra.query.runtime.matchers.planning.QueryProcessingException;
-import org.eclipse.viatra.query.runtime.matchers.planning.SubPlan;
-import org.eclipse.viatra.query.runtime.matchers.planning.operations.PApply;
-import org.eclipse.viatra.query.runtime.matchers.planning.operations.POperation;
-import org.eclipse.viatra.query.runtime.matchers.planning.operations.PProject;
-import org.eclipse.viatra.query.runtime.matchers.planning.operations.PStart;
-import org.eclipse.viatra.query.runtime.matchers.psystem.PConstraint;
-import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable;
-import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.AggregatorConstraint;
-import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.ExportedParameter;
-import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.ExpressionEvaluation;
-import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.Inequality;
-import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.NegativePatternCall;
-import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.PatternCallBasedDeferred;
-import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.PatternMatchCounter;
-import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.TypeFilterConstraint;
-import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.BinaryTransitiveClosure;
-import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.ConstantValue;
-import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall;
-import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint;
-import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter;
-import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery;
-
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
/**
* An EMF specific plan compiler for the local search-based pattern matcher
*
* @author Marton Bur
* @noreference This class is not intended to be referenced by clients.
+ * @deprecated Use the refactored {@link EMFOperationCompiler} instead
*/
-public class POperationCompiler {
-
- /**
- *
- */
- private static final String UNSUPPORTED_TYPE_MESSAGE = "Unsupported type: ";
- private List<ISearchOperation> operations;
- private Set<MatcherReference> dependencies = Sets.newHashSet();
- private Map<PConstraint, Set<Integer>> variableBindings;
- private Map<PVariable, Integer> variableMappings;
- private final boolean baseIndexAvailable;
- private final EMFQueryRuntimeContext runtimeContext;
-
- private class FrameMapping{
- final Map<PParameter, Integer> mapping = Maps.newHashMap();
- final Set<PParameter> adornment = Sets.newHashSet();
-
- public FrameMapping(PatternCallBasedDeferred constraint, Map<PVariable, Integer> variableMapping) {
- final Set<Integer> bindings = variableBindings.get(constraint);
- int keySize = constraint.getActualParametersTuple().getSize();
- for (int i = 0; i < keySize; i++) {
- PParameter symbolicParameter = constraint.getReferredQuery().getParameters().get(i);
- PVariable parameter = (PVariable) constraint.getActualParametersTuple().get(i);
- mapping.put(symbolicParameter, variableMapping.get(parameter));
- if (bindings.contains(variableMapping.get(parameter))) {
- adornment.add(symbolicParameter);
- }
- }
- }
-
- public FrameMapping(PositivePatternCall pCall, Map<PVariable, Integer> variableMapping){
- final Set<Integer> bindings = variableBindings.get(pCall);
- int keySize = pCall.getVariablesTuple().getSize();
- for (int i = 0; i < keySize; i++) {
- PParameter symbolicParameter = pCall.getReferredQuery().getParameters().get(i);
- PVariable parameter = (PVariable) pCall.getVariablesTuple().get(i);
- mapping.put(symbolicParameter, variableMapping.get(parameter));
- if (bindings.contains(variableMapping.get(parameter))) {
- adornment.add(symbolicParameter);
- }
- }
- }
- }
+@Deprecated
+public class POperationCompiler extends EMFOperationCompiler {
public POperationCompiler(IQueryRuntimeContext runtimeContext) {
- this(runtimeContext, false);
+ super(runtimeContext, false);
}
public POperationCompiler(IQueryRuntimeContext runtimeContext, boolean baseIndexAvailable) {
- this.runtimeContext = (EMFQueryRuntimeContext) runtimeContext;
- this.baseIndexAvailable = baseIndexAvailable;
- }
-
- /**
- * Compiles a plan of <code>POperation</code>s to a list of type <code>List&ltISearchOperation></code>
- *
- * @param plan
- * @param boundParameters
- * @return an ordered list of POperations that make up the compiled search plan
- * @throws QueryProcessingException
- */
- public List<ISearchOperation> compile(SubPlan plan, Set<PParameter> boundParameters) throws QueryProcessingException {
-
- variableMappings = CompilerHelper.createVariableMapping(plan);
- variableBindings = CompilerHelper.cacheVariableBindings(plan, variableMappings, boundParameters);
-
- operations = Lists.newArrayList();
-
- List<POperation> operationList = CompilerHelper.createOperationsList(plan);
- for (POperation pOperation : operationList) {
- compile(pOperation, variableMappings);
- }
-
- return operations;
- }
-
- private void compile(POperation pOperation, Map<PVariable, Integer> variableMapping) throws QueryProcessingException {
-
- if (pOperation instanceof PApply) {
- PApply pApply = (PApply) pOperation;
- PConstraint pConstraint = pApply.getPConstraint();
-
- if (isCheck(pConstraint, variableMapping)) {
- // check
- createCheckDispatcher(pConstraint, variableMapping);
- } else {
- // extend
- createExtendDispatcher(pConstraint, variableMapping);
- }
-
- } else if (pOperation instanceof PStart) {
- // nop
- } else if (pOperation instanceof PProject) {
- // nop
- } else {
- throw new QueryProcessingException("PStart, PApply or PProject was expected, received: " + pOperation.getClass(), null,"Unexpected POperation type", null);
- }
-
- }
-
- private boolean isCheck(PConstraint pConstraint, final Map<PVariable, Integer> variableMapping){
- if (pConstraint instanceof NegativePatternCall){
- return true;
- }else if (pConstraint instanceof PositivePatternCall){
- // Positive pattern call is check if all non-single used variables are bound
- return variableBindings.get(pConstraint).containsAll(Collections2.transform(Sets.filter(pConstraint.getAffectedVariables(), new Predicate<PVariable>() {
-
- @Override
- public boolean apply(PVariable input) {
- return input.getReferringConstraints().size() > 1;
- }
- }), new Function<PVariable, Integer>() {
-
- @Override
- public Integer apply(PVariable input) {
- return variableMapping.get(input);
- }
-
- }));
- }else if (pConstraint instanceof AggregatorConstraint){
- PVariable outputvar = ((AggregatorConstraint) pConstraint).getResultVariable();
- return variableBindings.get(pConstraint).contains(variableMapping.get(outputvar));
- }else if (pConstraint instanceof PatternMatchCounter){
- PVariable outputvar = ((PatternMatchCounter) pConstraint).getResultVariable();
- return variableBindings.get(pConstraint).contains(variableMapping.get(outputvar));
- }else if (pConstraint instanceof ExpressionEvaluation){
- PVariable outputvar = ((ExpressionEvaluation) pConstraint).getOutputVariable();
- return outputvar == null || variableBindings.get(pConstraint).contains(variableMapping.get(outputvar));
- } else {
- // In other cases, all variables shall be bound to be a check
- Set<PVariable> affectedVariables = pConstraint.getAffectedVariables();
- Set<Integer> varIndices = Sets.newHashSet();
- for (PVariable variable : affectedVariables) {
- varIndices.add(variableMapping.get(variable));
- }
- return variableBindings.get(pConstraint).containsAll(varIndices);
- }
- }
-
- private void createCheckDispatcher(PConstraint pConstraint, Map<PVariable, Integer> variableMapping) throws QueryProcessingException {
-
-
- // DeferredPConstraint subclasses
-
- // Equalities are normalized
-
- if (pConstraint instanceof Inequality) {
- createCheck((Inequality) pConstraint, variableMapping);
- } else if (pConstraint instanceof PositivePatternCall){
- createCheck((PositivePatternCall) pConstraint, variableMapping);
- } else if (pConstraint instanceof NegativePatternCall) {
- createCheck((NegativePatternCall) pConstraint,variableMapping);
- } else if (pConstraint instanceof AggregatorConstraint) {
- createCheck((AggregatorConstraint) pConstraint, variableMapping);
- } else if (pConstraint instanceof PatternMatchCounter) {
- createCheck((PatternMatchCounter) pConstraint, variableMapping);
- } else if (pConstraint instanceof ExpressionEvaluation) {
- createCheck((ExpressionEvaluation) pConstraint, variableMapping);
- } else if (pConstraint instanceof TypeFilterConstraint) {
- createCheck((TypeFilterConstraint) pConstraint,variableMapping);
- } else if (pConstraint instanceof ExportedParameter) {
- // Nothing to do here
- } else
-
- // EnumerablePConstraint subclasses
-
- if (pConstraint instanceof BinaryTransitiveClosure) {
- createCheck((BinaryTransitiveClosure) pConstraint, variableMapping);
- } else if (pConstraint instanceof ConstantValue) {
- createCheck((ConstantValue) pConstraint, variableMapping);
- } else if (pConstraint instanceof TypeConstraint) {
- createCheck((TypeConstraint) pConstraint,variableMapping);
- } else {
- String msg = "Unsupported Check constraint: "+pConstraint.toString();
- throw new QueryProcessingException(msg, null, msg, null);
- }
-
- }
-
- /**
- * @param pConstraint
- * @param variableMapping
- */
- private void createCheck(PatternMatchCounter counter, Map<PVariable, Integer> variableMapping) {
- FrameMapping mapping = new FrameMapping(counter, variableMapping);
-
- PQuery referredQuery = counter.getReferredQuery();
- MatcherReference matcherReference = new MatcherReference(referredQuery, mapping.adornment);
- operations.add(new CountCheck(matcherReference, mapping.mapping, variableMapping.get(counter.getResultVariable())));
- dependencies.add(matcherReference);
- }
-
- private void createCheck(PositivePatternCall pCall, Map<PVariable, Integer> variableMapping) {
- FrameMapping mapping = new FrameMapping(pCall, variableMapping);
- MatcherReference matcherReference = new MatcherReference(pCall.getReferredQuery(), mapping.adornment);
- operations.add(new CheckPositivePatternCall(matcherReference, mapping.mapping));
- dependencies.add(matcherReference);
- }
-
- private void createCheck(ConstantValue constant, Map<PVariable, Integer> variableMapping) {
- int position = variableMapping.get(constant.getVariablesTuple().get(0));
- operations.add(new CheckConstant(position, constant.getSupplierKey()));
- }
-
- private void createCheck(TypeFilterConstraint typeConstraint, Map<PVariable, Integer> variableMapping) throws QueryProcessingException {
- final IInputKey inputKey = typeConstraint.getInputKey();
- if (inputKey instanceof JavaTransitiveInstancesKey) {
- operations.add(new InstanceOfJavaClassCheck(variableMapping.get(typeConstraint.getVariablesTuple().get(0)), ((JavaTransitiveInstancesKey) inputKey).getInstanceClass()));
- } else if (inputKey instanceof EDataTypeInSlotsKey) { // TODO probably only occurs as TypeConstraint
- operations.add(new InstanceOfDataTypeCheck(variableMapping.get(typeConstraint.getVariablesTuple().get(0)),
- ((EDataTypeInSlotsKey) inputKey).getEmfKey()));
- } else if (inputKey instanceof EClassUnscopedTransitiveInstancesKey) {
- operations.add(new InstanceOfClassCheck(variableMapping.get(typeConstraint.getVariablesTuple().get(0)), ((EClassUnscopedTransitiveInstancesKey) inputKey).getEmfKey()));
- } else {
- String msg = UNSUPPORTED_TYPE_MESSAGE + inputKey;
- throw new QueryProcessingException(msg, null, msg, null);
- }
- }
-
- private void createCheck(TypeConstraint typeConstraint, Map<PVariable, Integer> variableMapping) throws QueryProcessingException {
- final IInputKey inputKey = typeConstraint.getSupplierKey();
- if (inputKey instanceof EClassTransitiveInstancesKey) {
- operations.add(new InstanceOfClassCheck(variableMapping.get(typeConstraint.getVariablesTuple().get(0)), ((EClassTransitiveInstancesKey) inputKey).getEmfKey()));
- operations.add(new ScopeCheck(variableMapping.get(typeConstraint.getVariablesTuple().get(0)), runtimeContext.getEmfScope()));
- } else if (inputKey instanceof EStructuralFeatureInstancesKey) {
- int sourcePosition = variableMapping.get(typeConstraint.getVariablesTuple().get(0));
- int targetPosition = variableMapping.get(typeConstraint.getVariablesTuple().get(1));
- operations.add(new StructuralFeatureCheck(sourcePosition, targetPosition,
- ((EStructuralFeatureInstancesKey) inputKey).getEmfKey()));
- } else if (inputKey instanceof EDataTypeInSlotsKey) {
- operations.add(new InstanceOfDataTypeCheck(variableMapping.get(typeConstraint.getVariablesTuple().get(0)),
- ((EDataTypeInSlotsKey) inputKey).getEmfKey()));
- } else {
- String msg = UNSUPPORTED_TYPE_MESSAGE + inputKey;
- throw new QueryProcessingException(msg, null, msg, null);
- }
- }
-
- private void createCheck(BinaryTransitiveClosure binaryTransitiveColsure, Map<PVariable, Integer> variableMapping) {
- int sourcePosition = variableMapping.get(binaryTransitiveColsure.getVariablesTuple().get(0));
- int targetPosition = variableMapping.get(binaryTransitiveColsure.getVariablesTuple().get(1));
-
- PQuery referredQuery = binaryTransitiveColsure.getReferredQuery();
-
- operations.add(new BinaryTransitiveClosureCheck(new MatcherReference(referredQuery, ImmutableSet.of(referredQuery.getParameters().get(0), referredQuery.getParameters().get(1))), sourcePosition, targetPosition));
- //The second parameter is NOT bound during execution!
- Set<PParameter> adornment = ImmutableSet.of(referredQuery.getParameters().get(0));
- dependencies.add(new MatcherReference(referredQuery, adornment));
- }
-
-
- private void createCheck(ExpressionEvaluation expressionEvaluation, Map<PVariable, Integer> variableMapping) {
- // Fill unbound variables with null; simply copy all variables. Unbound variables will be null anyway
- Iterable<String> inputParameterNames = expressionEvaluation.getEvaluator().getInputParameterNames();
- Map<String, Integer> nameMap = Maps.newHashMap();
-
- for (String pVariableName : inputParameterNames) {
- PVariable pVariable = expressionEvaluation.getPSystem().getVariableByNameChecked(pVariableName);
- nameMap.put(pVariableName, variableMapping.get(pVariable));
- }
-
- // output variable can be null; if null it is an ExpressionCheck
- if(expressionEvaluation.getOutputVariable() == null){
- operations.add(new ExpressionCheck(expressionEvaluation.getEvaluator(), nameMap));
- } else {
- operations.add(new ExpressionEvalCheck(expressionEvaluation.getEvaluator(), nameMap, variableMapping.get(expressionEvaluation.getOutputVariable())));
- }
- }
-
- private void createCheck(AggregatorConstraint aggregator, Map<PVariable, Integer> variableMapping) {
- FrameMapping mapping = new FrameMapping(aggregator, variableMapping);
-
- PQuery referredQuery = aggregator.getReferredQuery();
- MatcherReference matcherReference = new MatcherReference(referredQuery, mapping.adornment);
- operations.add(new AggregatorCheck(matcherReference, aggregator, mapping.mapping, variableMapping.get(aggregator.getResultVariable())));
- dependencies.add(matcherReference);
- }
-
- private void createCheck(NegativePatternCall negativePatternCall, Map<PVariable, Integer> variableMapping) {
- FrameMapping mapping = new FrameMapping(negativePatternCall, variableMapping);
- PQuery referredQuery = negativePatternCall.getReferredQuery();
- MatcherReference matcherReference = new MatcherReference(referredQuery, mapping.adornment);
- operations.add(new NACOperation(matcherReference, mapping.mapping));
- dependencies.add(matcherReference);
- }
-
- private void createCheck(Inequality inequality, Map<PVariable, Integer> variableMapping) {
- operations.add(new InequalityCheck(variableMapping.get(inequality.getWho()), variableMapping.get(inequality.getWithWhom())));
- }
-
-
- private void createExtendDispatcher(PConstraint pConstraint, Map<PVariable, Integer> variableMapping) throws QueryProcessingException {
-
- // DeferredPConstraint subclasses
-
- // Equalities are normalized
- if (pConstraint instanceof PositivePatternCall) {
- createExtend((PositivePatternCall)pConstraint, variableMapping);
- } else if (pConstraint instanceof AggregatorConstraint) {
- createExtend((AggregatorConstraint) pConstraint, variableMapping);
- } else if (pConstraint instanceof PatternMatchCounter) {
- createExtend((PatternMatchCounter) pConstraint, variableMapping);
- } else if (pConstraint instanceof ExpressionEvaluation) {
- createExtend((ExpressionEvaluation) pConstraint, variableMapping);
- } else if (pConstraint instanceof ExportedParameter) {
- // ExportedParameters are compiled to NOP
- } else
-
- // EnumerablePConstraint subclasses
-
- if (pConstraint instanceof ConstantValue) {
- createExtend((ConstantValue) pConstraint, variableMapping);
- } else if (pConstraint instanceof TypeConstraint) {
- createExtend((TypeConstraint) pConstraint, variableMapping);
- } else if (pConstraint instanceof BinaryTransitiveClosure) {
- createExtend((BinaryTransitiveClosure)pConstraint, variableMapping);
- } else {
- String msg = "Unsupported Extend constraint: "+pConstraint.toString();
- throw new QueryProcessingException(msg, null, msg, null);
- }
- }
-
- private void createExtend(PositivePatternCall pCall, Map<PVariable, Integer> variableMapping) {
- FrameMapping mapping = new FrameMapping(pCall, variableMapping);
- MatcherReference matcherReference = new MatcherReference(pCall.getReferredQuery(), mapping.adornment);
- operations.add(new ExtendPositivePatternCall(matcherReference, mapping.mapping));
- dependencies.add(matcherReference);
- }
-
- private void createExtend(BinaryTransitiveClosure binaryTransitiveClosure, Map<PVariable, Integer> variableMapping) throws QueryProcessingException {
- int sourcePosition = variableMapping.get(binaryTransitiveClosure.getVariablesTuple().get(0));
- int targetPosition = variableMapping.get(binaryTransitiveClosure.getVariablesTuple().get(1));
-
- PQuery referredQuery = binaryTransitiveClosure.getReferredQuery();
-
- boolean sourceBound = variableBindings.get(binaryTransitiveClosure).contains(sourcePosition);
- boolean targetBound = variableBindings.get(binaryTransitiveClosure).contains(targetPosition);
-
- if (sourceBound && !targetBound) {
- Set<PParameter> adornment = ImmutableSet.of(referredQuery.getParameters().get(0));
- operations.add(new ExtendBinaryTransitiveClosure.Forward(new MatcherReference(referredQuery, adornment), sourcePosition, targetPosition));
- dependencies.add(new MatcherReference(referredQuery, adornment));
- } else if (!sourceBound && targetBound) {
- Set<PParameter> adornment = ImmutableSet.of(referredQuery.getParameters().get(1));
- operations.add(new ExtendBinaryTransitiveClosure.Backward(new MatcherReference(referredQuery, adornment), sourcePosition, targetPosition));
- dependencies.add(new MatcherReference(referredQuery, adornment));
- } else {
- String msg = "Binary transitive closure not supported with two unbound parameters";
- throw new QueryProcessingException(msg, null, msg, binaryTransitiveClosure.getPSystem().getPattern());
- }
- }
-
- private void createExtend(ConstantValue constant, Map<PVariable, Integer> variableMapping) {
- int position = variableMapping.get(constant.getVariablesTuple().get(0));
- operations.add(new ExtendConstant(position, constant.getSupplierKey()));
- }
-
- private void createExtend(TypeConstraint typeConstraint, Map<PVariable, Integer> variableMapping) {
- final IInputKey inputKey = typeConstraint.getSupplierKey();
- if (inputKey instanceof EDataTypeInSlotsKey) {
- if(baseIndexAvailable){
- operations.add(new IterateOverEDatatypeInstances(variableMapping.get(typeConstraint.getVariableInTuple(0)), ((EDataTypeInSlotsKey) inputKey).getEmfKey()));
- } else {
- int position = variableMapping.get(typeConstraint.getVariableInTuple(0));
- operations
- .add(new org.eclipse.viatra.query.runtime.localsearch.operations.extend.nobase.IterateOverEDatatypeInstances(position,
- ((EDataTypeInSlotsKey) inputKey).getEmfKey(), runtimeContext.getEmfScope()));
- operations.add(new ScopeCheck(position, runtimeContext.getEmfScope()));
- }
- } else if (inputKey instanceof EClassTransitiveInstancesKey) {
- if(baseIndexAvailable){
- operations.add(new IterateOverEClassInstances(variableMapping.get(typeConstraint.getVariableInTuple(0)),
- ((EClassTransitiveInstancesKey) inputKey).getEmfKey()));
- } else {
- int position = variableMapping.get(typeConstraint.getVariableInTuple(0));
- operations
- .add(new org.eclipse.viatra.query.runtime.localsearch.operations.extend.nobase.IterateOverEClassInstances(
- position,
- ((EClassTransitiveInstancesKey) inputKey).getEmfKey(), runtimeContext.getEmfScope()));
- operations.add(new ScopeCheck(position, runtimeContext.getEmfScope()));
- }
- } else if (inputKey instanceof EStructuralFeatureInstancesKey) {
- final EStructuralFeature feature = ((EStructuralFeatureInstancesKey) inputKey).getEmfKey();
-
- int sourcePosition = variableMapping.get(typeConstraint.getVariablesTuple().get(0));
- int targetPosition = variableMapping.get(typeConstraint.getVariablesTuple().get(1));
-
- boolean fromBound = variableBindings.get(typeConstraint).contains(sourcePosition);
- boolean toBound = variableBindings.get(typeConstraint).contains(targetPosition);
-
- if (fromBound && !toBound) {
- if (baseIndexAvailable) {
- operations.add(new ExtendToEStructuralFeatureTarget(sourcePosition, targetPosition, feature));
- } else {
- operations
- .add(new org.eclipse.viatra.query.runtime.localsearch.operations.extend.nobase.ExtendToEStructuralFeatureTarget(
- sourcePosition, targetPosition, feature));
- operations.add(new ScopeCheck(targetPosition, runtimeContext.getEmfScope()));
- }
- }
- else if(!fromBound && toBound){
- if (feature instanceof EReference && ((EReference)feature).isContainment()) {
- // The iterate is also used to traverse a single container (third parameter)
- operations.add(new IterateOverContainers(sourcePosition, targetPosition, false));
- operations.add(new ScopeCheck(sourcePosition, runtimeContext.getEmfScope()));
- } else if(baseIndexAvailable){
- operations.add(new ExtendToEStructuralFeatureSource(sourcePosition, targetPosition, feature));
- } else {
- operations.add(new org.eclipse.viatra.query.runtime.localsearch.operations.extend.nobase.ExtendToEStructuralFeatureSource(
- sourcePosition, targetPosition, feature));
- operations.add(new ScopeCheck(sourcePosition, runtimeContext.getEmfScope()));
- }
- } else {
- // TODO Elaborate solution based on the navigability of edges
- // As of now a static solution is implemented
- if (baseIndexAvailable) {
- operations.add(new IterateOverEClassInstances(sourcePosition, feature.getEContainingClass()));
- operations.add(new ExtendToEStructuralFeatureTarget(sourcePosition, targetPosition, feature));
- } else {
- operations
- .add(new org.eclipse.viatra.query.runtime.localsearch.operations.extend.nobase.IterateOverEClassInstances(
- sourcePosition, feature.getEContainingClass(), runtimeContext.getEmfScope()));
- operations.add(new ScopeCheck(sourcePosition, runtimeContext.getEmfScope()));
- operations
- .add(new org.eclipse.viatra.query.runtime.localsearch.operations.extend.nobase.ExtendToEStructuralFeatureTarget(
- sourcePosition, targetPosition, feature));
- operations.add(new ScopeCheck(targetPosition, runtimeContext.getEmfScope()));
- }
- }
-
- } else {
- throw new IllegalArgumentException(UNSUPPORTED_TYPE_MESSAGE + inputKey);
- }
- }
-
- private void createExtend(ExpressionEvaluation expressionEvaluation, Map<PVariable, Integer> variableMapping) {
- // Fill unbound variables with null; simply copy all variables. Unbound variables will be null anyway
- Iterable<String> inputParameterNames = expressionEvaluation.getEvaluator().getInputParameterNames();
- Map<String, Integer> nameMap = Maps.newHashMap();
-
- for (String pVariableName : inputParameterNames) {
- PVariable pVariable = expressionEvaluation.getPSystem().getVariableByNameChecked(pVariableName);
- nameMap.put(pVariableName, variableMapping.get(pVariable));
- }
-
- // output variable can be null; if null it is an ExpressionCheck
- if(expressionEvaluation.getOutputVariable() == null){
- operations.add(new ExpressionCheck(expressionEvaluation.getEvaluator(), nameMap));
- } else {
- operations.add(new ExpressionEval(expressionEvaluation.getEvaluator(), nameMap, variableMapping.get(expressionEvaluation.getOutputVariable())));
- }
- }
-
- private void createExtend(AggregatorConstraint aggregator, Map<PVariable, Integer> variableMapping) {
- FrameMapping mapping = new FrameMapping(aggregator, variableMapping);
-
- PQuery referredQuery = aggregator.getReferredQuery();
- MatcherReference matcherReference = new MatcherReference(referredQuery, mapping.adornment);
- operations.add(new AggregatorExtend(matcherReference, aggregator, mapping.mapping, variableMapping.get(aggregator.getResultVariable())));
- dependencies.add(matcherReference);
- }
-
- private void createExtend(PatternMatchCounter patternMatchCounter, Map<PVariable, Integer> variableMapping) {
- FrameMapping mapping = new FrameMapping(patternMatchCounter, variableMapping);
-
- PQuery referredQuery = patternMatchCounter.getReferredQuery();
- MatcherReference matcherReference = new MatcherReference(referredQuery, mapping.adornment);
- operations.add(new CountOperation(matcherReference, mapping.mapping, variableMapping.get(patternMatchCounter.getResultVariable())));
- dependencies.add(matcherReference);
- }
-
- public Set<MatcherReference> getDependencies() {
- return dependencies;
- }
- /**
- * @return the cached variable bindings for the previously created plan
- */
- public Map<PVariable, Integer> getVariableMappings() {
- return variableMappings;
+ super(runtimeContext, baseIndexAvailable);
}
}
diff --git a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/compiler/AbstractOperationCompiler.java b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/compiler/AbstractOperationCompiler.java
new file mode 100644
index 000000000..468c3f879
--- /dev/null
+++ b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/compiler/AbstractOperationCompiler.java
@@ -0,0 +1,438 @@
+/*******************************************************************************
+ * Copyright (c) 2010-2017, Zoltan Ujhelyi, IncQuery Labs Ltd.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Zoltan Ujhelyi - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.viatra.query.runtime.localsearch.planner.compiler;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.viatra.query.runtime.emf.EMFQueryRuntimeContext;
+import org.eclipse.viatra.query.runtime.localsearch.matcher.MatcherReference;
+import org.eclipse.viatra.query.runtime.localsearch.operations.ISearchOperation;
+import org.eclipse.viatra.query.runtime.localsearch.operations.check.AggregatorCheck;
+import org.eclipse.viatra.query.runtime.localsearch.operations.check.BinaryTransitiveClosureCheck;
+import org.eclipse.viatra.query.runtime.localsearch.operations.check.CheckConstant;
+import org.eclipse.viatra.query.runtime.localsearch.operations.check.CheckPositivePatternCall;
+import org.eclipse.viatra.query.runtime.localsearch.operations.check.CountCheck;
+import org.eclipse.viatra.query.runtime.localsearch.operations.check.ExpressionCheck;
+import org.eclipse.viatra.query.runtime.localsearch.operations.check.ExpressionEvalCheck;
+import org.eclipse.viatra.query.runtime.localsearch.operations.check.InequalityCheck;
+import org.eclipse.viatra.query.runtime.localsearch.operations.check.NACOperation;
+import org.eclipse.viatra.query.runtime.localsearch.operations.extend.AggregatorExtend;
+import org.eclipse.viatra.query.runtime.localsearch.operations.extend.CountOperation;
+import org.eclipse.viatra.query.runtime.localsearch.operations.extend.ExpressionEval;
+import org.eclipse.viatra.query.runtime.localsearch.operations.extend.ExtendBinaryTransitiveClosure;
+import org.eclipse.viatra.query.runtime.localsearch.operations.extend.ExtendConstant;
+import org.eclipse.viatra.query.runtime.localsearch.operations.extend.ExtendPositivePatternCall;
+import org.eclipse.viatra.query.runtime.localsearch.planner.util.CompilerHelper;
+import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContext;
+import org.eclipse.viatra.query.runtime.matchers.planning.QueryProcessingException;
+import org.eclipse.viatra.query.runtime.matchers.planning.SubPlan;
+import org.eclipse.viatra.query.runtime.matchers.planning.operations.PApply;
+import org.eclipse.viatra.query.runtime.matchers.planning.operations.POperation;
+import org.eclipse.viatra.query.runtime.matchers.planning.operations.PProject;
+import org.eclipse.viatra.query.runtime.matchers.planning.operations.PStart;
+import org.eclipse.viatra.query.runtime.matchers.psystem.PConstraint;
+import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable;
+import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.AggregatorConstraint;
+import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.ExportedParameter;
+import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.ExpressionEvaluation;
+import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.Inequality;
+import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.NegativePatternCall;
+import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.PatternCallBasedDeferred;
+import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.PatternMatchCounter;
+import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.TypeFilterConstraint;
+import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.BinaryTransitiveClosure;
+import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.ConstantValue;
+import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall;
+import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint;
+import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter;
+import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+/**
+ * @author Zoltan Ujhelyi
+ * @since 1.7
+ *
+ */
+public abstract class AbstractOperationCompiler implements IOperationCompiler {
+
+ public class FrameMapping{
+ public final Map<PParameter, Integer> mapping = Maps.newHashMap();
+ public final Set<PParameter> adornment = Sets.newHashSet();
+
+ public FrameMapping(PatternCallBasedDeferred constraint, Map<PVariable, Integer> variableMapping) {
+ final Set<Integer> bindings = variableBindings.get(constraint);
+ int keySize = constraint.getActualParametersTuple().getSize();
+ for (int i = 0; i < keySize; i++) {
+ PParameter symbolicParameter = constraint.getReferredQuery().getParameters().get(i);
+ PVariable parameter = (PVariable) constraint.getActualParametersTuple().get(i);
+ mapping.put(symbolicParameter, variableMapping.get(parameter));
+ if (bindings.contains(variableMapping.get(parameter))) {
+ adornment.add(symbolicParameter);
+ }
+ }
+ }
+
+ public FrameMapping(PositivePatternCall pCall, Map<PVariable, Integer> variableMapping){
+ final Set<Integer> bindings = variableBindings.get(pCall);
+ int keySize = pCall.getVariablesTuple().getSize();
+ for (int i = 0; i < keySize; i++) {
+ PParameter symbolicParameter = pCall.getReferredQuery().getParameters().get(i);
+ PVariable parameter = (PVariable) pCall.getVariablesTuple().get(i);
+ mapping.put(symbolicParameter, variableMapping.get(parameter));
+ if (bindings.contains(variableMapping.get(parameter))) {
+ adornment.add(symbolicParameter);
+ }
+ }
+ }
+ }
+
+ protected static final String UNSUPPORTED_TYPE_MESSAGE = "Unsupported type: ";
+
+ protected abstract void createExtend(TypeConstraint typeConstraint, Map<PVariable, Integer> variableMapping);
+
+ protected abstract void createCheck(TypeConstraint typeConstraint, Map<PVariable, Integer> variableMapping) throws QueryProcessingException;
+
+ protected abstract void createCheck(TypeFilterConstraint typeConstraint, Map<PVariable, Integer> variableMapping) throws QueryProcessingException;
+
+ protected List<ISearchOperation> operations;
+ protected Set<MatcherReference> dependencies = Sets.newHashSet();
+ protected Map<PConstraint, Set<Integer>> variableBindings;
+ private Map<PVariable, Integer> variableMappings;
+ protected final EMFQueryRuntimeContext runtimeContext;
+
+ public AbstractOperationCompiler(IQueryRuntimeContext runtimeContext) {
+ this.runtimeContext = (EMFQueryRuntimeContext) runtimeContext;
+ }
+
+ /**
+ * Compiles a plan of <code>POperation</code>s to a list of type <code>List&ltISearchOperation></code>
+ *
+ * @param plan
+ * @param boundParameters
+ * @return an ordered list of POperations that make up the compiled search plan
+ * @throws QueryProcessingException
+ */
+ @Override
+ public List<ISearchOperation> compile(SubPlan plan, Set<PParameter> boundParameters) throws QueryProcessingException {
+
+ variableMappings = CompilerHelper.createVariableMapping(plan);
+ variableBindings = CompilerHelper.cacheVariableBindings(plan, variableMappings, boundParameters);
+
+ operations = Lists.newArrayList();
+
+ List<POperation> operationList = CompilerHelper.createOperationsList(plan);
+ for (POperation pOperation : operationList) {
+ compile(pOperation, variableMappings);
+ }
+
+ return operations;
+ }
+
+ private void compile(POperation pOperation, Map<PVariable, Integer> variableMapping) throws QueryProcessingException {
+
+ if (pOperation instanceof PApply) {
+ PApply pApply = (PApply) pOperation;
+ PConstraint pConstraint = pApply.getPConstraint();
+
+ if (isCheck(pConstraint, variableMapping)) {
+ // check
+ createCheckDispatcher(pConstraint, variableMapping);
+ } else {
+ // extend
+ createExtendDispatcher(pConstraint, variableMapping);
+ }
+
+ } else if (pOperation instanceof PStart) {
+ // nop
+ } else if (pOperation instanceof PProject) {
+ // nop
+ } else {
+ throw new QueryProcessingException("PStart, PApply or PProject was expected, received: " + pOperation.getClass(), null,"Unexpected POperation type", null);
+ }
+
+ }
+
+ private void createCheckDispatcher(PConstraint pConstraint, Map<PVariable, Integer> variableMapping) throws QueryProcessingException {
+
+
+ // DeferredPConstraint subclasses
+
+ // Equalities are normalized
+
+ if (pConstraint instanceof Inequality) {
+ createCheck((Inequality) pConstraint, variableMapping);
+ } else if (pConstraint instanceof PositivePatternCall){
+ createCheck((PositivePatternCall) pConstraint, variableMapping);
+ } else if (pConstraint instanceof NegativePatternCall) {
+ createCheck((NegativePatternCall) pConstraint,variableMapping);
+ } else if (pConstraint instanceof AggregatorConstraint) {
+ createCheck((AggregatorConstraint) pConstraint, variableMapping);
+ } else if (pConstraint instanceof PatternMatchCounter) {
+ createCheck((PatternMatchCounter) pConstraint, variableMapping);
+ } else if (pConstraint instanceof ExpressionEvaluation) {
+ createCheck((ExpressionEvaluation) pConstraint, variableMapping);
+ } else if (pConstraint instanceof TypeFilterConstraint) {
+ createCheck((TypeFilterConstraint) pConstraint,variableMapping);
+ } else if (pConstraint instanceof ExportedParameter) {
+ // Nothing to do here
+ } else
+
+ // EnumerablePConstraint subclasses
+
+ if (pConstraint instanceof BinaryTransitiveClosure) {
+ createCheck((BinaryTransitiveClosure) pConstraint, variableMapping);
+ } else if (pConstraint instanceof ConstantValue) {
+ createCheck((ConstantValue) pConstraint, variableMapping);
+ } else if (pConstraint instanceof TypeConstraint) {
+ createCheck((TypeConstraint) pConstraint,variableMapping);
+ } else {
+ String msg = "Unsupported Check constraint: "+pConstraint.toString();
+ throw new QueryProcessingException(msg, null, msg, null);
+ }
+
+ }
+
+ protected void createExtendDispatcher(PConstraint pConstraint, Map<PVariable, Integer> variableMapping) throws QueryProcessingException {
+
+ // DeferredPConstraint subclasses
+
+ // Equalities are normalized
+ if (pConstraint instanceof PositivePatternCall) {
+ createExtend((PositivePatternCall)pConstraint, variableMapping);
+ } else if (pConstraint instanceof AggregatorConstraint) {
+ createExtend((AggregatorConstraint) pConstraint, variableMapping);
+ } else if (pConstraint instanceof PatternMatchCounter) {
+ createExtend((PatternMatchCounter) pConstraint, variableMapping);
+ } else if (pConstraint instanceof ExpressionEvaluation) {
+ createExtend((ExpressionEvaluation) pConstraint, variableMapping);
+ } else if (pConstraint instanceof ExportedParameter) {
+ // ExportedParameters are compiled to NOP
+ } else
+
+ // EnumerablePConstraint subclasses
+
+ if (pConstraint instanceof ConstantValue) {
+ createExtend((ConstantValue) pConstraint, variableMapping);
+ } else if (pConstraint instanceof TypeConstraint) {
+ createExtend((TypeConstraint) pConstraint, variableMapping);
+ } else if (pConstraint instanceof BinaryTransitiveClosure) {
+ createExtend((BinaryTransitiveClosure)pConstraint, variableMapping);
+ } else {
+ String msg = "Unsupported Extend constraint: "+pConstraint.toString();
+ throw new QueryProcessingException(msg, null, msg, null);
+ }
+ }
+
+ private boolean isCheck(PConstraint pConstraint, final Map<PVariable, Integer> variableMapping) {
+ if (pConstraint instanceof NegativePatternCall){
+ return true;
+ }else if (pConstraint instanceof PositivePatternCall){
+ // Positive pattern call is check if all non-single used variables are bound
+ return variableBindings.get(pConstraint).containsAll(Collections2.transform(Sets.filter(pConstraint.getAffectedVariables(), new Predicate<PVariable>() {
+
+ @Override
+ public boolean apply(PVariable input) {
+ return input.getReferringConstraints().size() > 1;
+ }
+ }), new Function<PVariable, Integer>() {
+
+ @Override
+ public Integer apply(PVariable input) {
+ return variableMapping.get(input);
+ }
+
+ }));
+ }else if (pConstraint instanceof AggregatorConstraint){
+ PVariable outputvar = ((AggregatorConstraint) pConstraint).getResultVariable();
+ return variableBindings.get(pConstraint).contains(variableMapping.get(outputvar));
+ }else if (pConstraint instanceof PatternMatchCounter){
+ PVariable outputvar = ((PatternMatchCounter) pConstraint).getResultVariable();
+ return variableBindings.get(pConstraint).contains(variableMapping.get(outputvar));
+ }else if (pConstraint instanceof ExpressionEvaluation){
+ PVariable outputvar = ((ExpressionEvaluation) pConstraint).getOutputVariable();
+ return outputvar == null || variableBindings.get(pConstraint).contains(variableMapping.get(outputvar));
+ } else {
+ // In other cases, all variables shall be bound to be a check
+ Set<PVariable> affectedVariables = pConstraint.getAffectedVariables();
+ Set<Integer> varIndices = Sets.newHashSet();
+ for (PVariable variable : affectedVariables) {
+ varIndices.add(variableMapping.get(variable));
+ }
+ return variableBindings.get(pConstraint).containsAll(varIndices);
+ }
+ }
+
+ @Override
+ public Set<MatcherReference> getDependencies() {
+ return dependencies;
+ }
+
+ /**
+ * @return the cached variable bindings for the previously created plan
+ */
+ @Override
+ public Map<PVariable, Integer> getVariableMappings() {
+ return variableMappings;
+ }
+
+ protected void createCheck(PatternMatchCounter counter, Map<PVariable, Integer> variableMapping) {
+ FrameMapping mapping = new FrameMapping(counter, variableMapping);
+
+ PQuery referredQuery = counter.getReferredQuery();
+ MatcherReference matcherReference = new MatcherReference(referredQuery, mapping.adornment);
+ operations.add(new CountCheck(matcherReference, mapping.mapping, variableMapping.get(counter.getResultVariable())));
+ dependencies.add(matcherReference);
+ }
+
+ protected void createCheck(PositivePatternCall pCall, Map<PVariable, Integer> variableMapping) {
+ FrameMapping mapping = new FrameMapping(pCall, variableMapping);
+ MatcherReference matcherReference = new MatcherReference(pCall.getReferredQuery(), mapping.adornment);
+ operations.add(new CheckPositivePatternCall(matcherReference, mapping.mapping));
+ dependencies.add(matcherReference);
+ }
+
+ protected void createCheck(ConstantValue constant, Map<PVariable, Integer> variableMapping) {
+ int position = variableMapping.get(constant.getVariablesTuple().get(0));
+ operations.add(new CheckConstant(position, constant.getSupplierKey()));
+ }
+
+ protected void createCheck(BinaryTransitiveClosure binaryTransitiveColsure, Map<PVariable, Integer> variableMapping) {
+ int sourcePosition = variableMapping.get(binaryTransitiveColsure.getVariablesTuple().get(0));
+ int targetPosition = variableMapping.get(binaryTransitiveColsure.getVariablesTuple().get(1));
+
+ PQuery referredQuery = binaryTransitiveColsure.getReferredQuery();
+
+ operations.add(new BinaryTransitiveClosureCheck(new MatcherReference(referredQuery, ImmutableSet.of(referredQuery.getParameters().get(0), referredQuery.getParameters().get(1))), sourcePosition, targetPosition));
+ //The second parameter is NOT bound during execution!
+ Set<PParameter> adornment = ImmutableSet.of(referredQuery.getParameters().get(0));
+ dependencies.add(new MatcherReference(referredQuery, adornment));
+ }
+
+ protected void createCheck(ExpressionEvaluation expressionEvaluation, Map<PVariable, Integer> variableMapping) {
+ // Fill unbound variables with null; simply copy all variables. Unbound variables will be null anyway
+ Iterable<String> inputParameterNames = expressionEvaluation.getEvaluator().getInputParameterNames();
+ Map<String, Integer> nameMap = Maps.newHashMap();
+
+ for (String pVariableName : inputParameterNames) {
+ PVariable pVariable = expressionEvaluation.getPSystem().getVariableByNameChecked(pVariableName);
+ nameMap.put(pVariableName, variableMapping.get(pVariable));
+ }
+
+ // output variable can be null; if null it is an ExpressionCheck
+ if(expressionEvaluation.getOutputVariable() == null){
+ operations.add(new ExpressionCheck(expressionEvaluation.getEvaluator(), nameMap));
+ } else {
+ operations.add(new ExpressionEvalCheck(expressionEvaluation.getEvaluator(), nameMap, variableMapping.get(expressionEvaluation.getOutputVariable())));
+ }
+ }
+
+ protected void createCheck(AggregatorConstraint aggregator, Map<PVariable, Integer> variableMapping) {
+ FrameMapping mapping = new FrameMapping(aggregator, variableMapping);
+
+ PQuery referredQuery = aggregator.getReferredQuery();
+ MatcherReference matcherReference = new MatcherReference(referredQuery, mapping.adornment);
+ operations.add(new AggregatorCheck(matcherReference, aggregator, mapping.mapping, variableMapping.get(aggregator.getResultVariable())));
+ dependencies.add(matcherReference);
+ }
+
+ protected void createCheck(NegativePatternCall negativePatternCall, Map<PVariable, Integer> variableMapping) {
+ FrameMapping mapping = new FrameMapping(negativePatternCall, variableMapping);
+ PQuery referredQuery = negativePatternCall.getReferredQuery();
+ MatcherReference matcherReference = new MatcherReference(referredQuery, mapping.adornment);
+ operations.add(new NACOperation(matcherReference, mapping.mapping));
+ dependencies.add(matcherReference);
+ }
+
+ protected void createCheck(Inequality inequality, Map<PVariable, Integer> variableMapping) {
+ operations.add(new InequalityCheck(variableMapping.get(inequality.getWho()), variableMapping.get(inequality.getWithWhom())));
+ }
+
+ protected void createExtend(PositivePatternCall pCall, Map<PVariable, Integer> variableMapping) {
+ FrameMapping mapping = new FrameMapping(pCall, variableMapping);
+ MatcherReference matcherReference = new MatcherReference(pCall.getReferredQuery(), mapping.adornment);
+ operations.add(new ExtendPositivePatternCall(matcherReference, mapping.mapping));
+ dependencies.add(matcherReference);
+ }
+
+ protected void createExtend(BinaryTransitiveClosure binaryTransitiveClosure, Map<PVariable, Integer> variableMapping) throws QueryProcessingException {
+ int sourcePosition = variableMapping.get(binaryTransitiveClosure.getVariablesTuple().get(0));
+ int targetPosition = variableMapping.get(binaryTransitiveClosure.getVariablesTuple().get(1));
+
+ PQuery referredQuery = binaryTransitiveClosure.getReferredQuery();
+
+ boolean sourceBound = variableBindings.get(binaryTransitiveClosure).contains(sourcePosition);
+ boolean targetBound = variableBindings.get(binaryTransitiveClosure).contains(targetPosition);
+
+ if (sourceBound && !targetBound) {
+ Set<PParameter> adornment = ImmutableSet.of(referredQuery.getParameters().get(0));
+ operations.add(new ExtendBinaryTransitiveClosure.Forward(new MatcherReference(referredQuery, adornment), sourcePosition, targetPosition));
+ dependencies.add(new MatcherReference(referredQuery, adornment));
+ } else if (!sourceBound && targetBound) {
+ Set<PParameter> adornment = ImmutableSet.of(referredQuery.getParameters().get(1));
+ operations.add(new ExtendBinaryTransitiveClosure.Backward(new MatcherReference(referredQuery, adornment), sourcePosition, targetPosition));
+ dependencies.add(new MatcherReference(referredQuery, adornment));
+ } else {
+ String msg = "Binary transitive closure not supported with two unbound parameters";
+ throw new QueryProcessingException(msg, null, msg, binaryTransitiveClosure.getPSystem().getPattern());
+ }
+ }
+
+ protected void createExtend(ConstantValue constant, Map<PVariable, Integer> variableMapping) {
+ int position = variableMapping.get(constant.getVariablesTuple().get(0));
+ operations.add(new ExtendConstant(position, constant.getSupplierKey()));
+ }
+
+ protected void createExtend(ExpressionEvaluation expressionEvaluation, Map<PVariable, Integer> variableMapping) {
+ // Fill unbound variables with null; simply copy all variables. Unbound variables will be null anyway
+ Iterable<String> inputParameterNames = expressionEvaluation.getEvaluator().getInputParameterNames();
+ Map<String, Integer> nameMap = Maps.newHashMap();
+
+ for (String pVariableName : inputParameterNames) {
+ PVariable pVariable = expressionEvaluation.getPSystem().getVariableByNameChecked(pVariableName);
+ nameMap.put(pVariableName, variableMapping.get(pVariable));
+ }
+
+ // output variable can be null; if null it is an ExpressionCheck
+ if(expressionEvaluation.getOutputVariable() == null){
+ operations.add(new ExpressionCheck(expressionEvaluation.getEvaluator(), nameMap));
+ } else {
+ operations.add(new ExpressionEval(expressionEvaluation.getEvaluator(), nameMap, variableMapping.get(expressionEvaluation.getOutputVariable())));
+ }
+ }
+
+ protected void createExtend(AggregatorConstraint aggregator, Map<PVariable, Integer> variableMapping) {
+ FrameMapping mapping = new FrameMapping(aggregator, variableMapping);
+
+ PQuery referredQuery = aggregator.getReferredQuery();
+ MatcherReference matcherReference = new MatcherReference(referredQuery, mapping.adornment);
+ operations.add(new AggregatorExtend(matcherReference, aggregator, mapping.mapping, variableMapping.get(aggregator.getResultVariable())));
+ dependencies.add(matcherReference);
+ }
+
+ protected void createExtend(PatternMatchCounter patternMatchCounter, Map<PVariable, Integer> variableMapping) {
+ FrameMapping mapping = new FrameMapping(patternMatchCounter, variableMapping);
+
+ PQuery referredQuery = patternMatchCounter.getReferredQuery();
+ MatcherReference matcherReference = new MatcherReference(referredQuery, mapping.adornment);
+ operations.add(new CountOperation(matcherReference, mapping.mapping, variableMapping.get(patternMatchCounter.getResultVariable())));
+ dependencies.add(matcherReference);
+ }
+
+} \ No newline at end of file
diff --git a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/compiler/EMFOperationCompiler.java b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/compiler/EMFOperationCompiler.java
new file mode 100644
index 000000000..4d7789dc6
--- /dev/null
+++ b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/compiler/EMFOperationCompiler.java
@@ -0,0 +1,174 @@
+/*******************************************************************************
+ * Copyright (c) 2010-2017, Zoltan Ujhelyi, IncQuery Labs Ltd.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Zoltan Ujhelyi - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.viatra.query.runtime.localsearch.planner.compiler;
+
+import java.util.Map;
+
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.viatra.query.runtime.emf.types.EClassTransitiveInstancesKey;
+import org.eclipse.viatra.query.runtime.emf.types.EClassUnscopedTransitiveInstancesKey;
+import org.eclipse.viatra.query.runtime.emf.types.EDataTypeInSlotsKey;
+import org.eclipse.viatra.query.runtime.emf.types.EStructuralFeatureInstancesKey;
+import org.eclipse.viatra.query.runtime.localsearch.operations.check.InstanceOfClassCheck;
+import org.eclipse.viatra.query.runtime.localsearch.operations.check.InstanceOfDataTypeCheck;
+import org.eclipse.viatra.query.runtime.localsearch.operations.check.InstanceOfJavaClassCheck;
+import org.eclipse.viatra.query.runtime.localsearch.operations.check.StructuralFeatureCheck;
+import org.eclipse.viatra.query.runtime.localsearch.operations.check.nobase.ScopeCheck;
+import org.eclipse.viatra.query.runtime.localsearch.operations.extend.ExtendToEStructuralFeatureSource;
+import org.eclipse.viatra.query.runtime.localsearch.operations.extend.ExtendToEStructuralFeatureTarget;
+import org.eclipse.viatra.query.runtime.localsearch.operations.extend.IterateOverContainers;
+import org.eclipse.viatra.query.runtime.localsearch.operations.extend.IterateOverEClassInstances;
+import org.eclipse.viatra.query.runtime.localsearch.operations.extend.IterateOverEDatatypeInstances;
+import org.eclipse.viatra.query.runtime.matchers.context.IInputKey;
+import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContext;
+import org.eclipse.viatra.query.runtime.matchers.context.common.JavaTransitiveInstancesKey;
+import org.eclipse.viatra.query.runtime.matchers.planning.QueryProcessingException;
+import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable;
+import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.TypeFilterConstraint;
+import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint;
+
+/**
+ * Operation compiler implementation that uses EMF-specific operations.
+ *
+ * @author Zoltan Ujhelyi
+ * @since 1.7
+ *
+ */
+public class EMFOperationCompiler extends AbstractOperationCompiler {
+
+ private boolean baseIndexAvailable;
+
+ public EMFOperationCompiler(IQueryRuntimeContext runtimeContext) {
+ this(runtimeContext, false);
+ }
+
+ public EMFOperationCompiler(IQueryRuntimeContext runtimeContext, boolean baseIndexAvailable) {
+ super(runtimeContext);
+ this.baseIndexAvailable = baseIndexAvailable;
+ }
+
+ @Override
+ protected void createCheck(TypeFilterConstraint typeConstraint, Map<PVariable, Integer> variableMapping) throws QueryProcessingException {
+ final IInputKey inputKey = typeConstraint.getInputKey();
+ if (inputKey instanceof JavaTransitiveInstancesKey) {
+ operations.add(new InstanceOfJavaClassCheck(variableMapping.get(typeConstraint.getVariablesTuple().get(0)), ((JavaTransitiveInstancesKey) inputKey).getInstanceClass()));
+ } else if (inputKey instanceof EDataTypeInSlotsKey) { // TODO probably only occurs as TypeConstraint
+ operations.add(new InstanceOfDataTypeCheck(variableMapping.get(typeConstraint.getVariablesTuple().get(0)),
+ ((EDataTypeInSlotsKey) inputKey).getEmfKey()));
+ } else if (inputKey instanceof EClassUnscopedTransitiveInstancesKey) {
+ operations.add(new InstanceOfClassCheck(variableMapping.get(typeConstraint.getVariablesTuple().get(0)), ((EClassUnscopedTransitiveInstancesKey) inputKey).getEmfKey()));
+ } else {
+ String msg = UNSUPPORTED_TYPE_MESSAGE + inputKey;
+ throw new QueryProcessingException(msg, null, msg, null);
+ }
+ }
+
+ @Override
+ protected void createCheck(TypeConstraint typeConstraint, Map<PVariable, Integer> variableMapping) throws QueryProcessingException {
+ final IInputKey inputKey = typeConstraint.getSupplierKey();
+ if (inputKey instanceof EClassTransitiveInstancesKey) {
+ operations.add(new InstanceOfClassCheck(variableMapping.get(typeConstraint.getVariablesTuple().get(0)), ((EClassTransitiveInstancesKey) inputKey).getEmfKey()));
+ operations.add(new ScopeCheck(variableMapping.get(typeConstraint.getVariablesTuple().get(0)), runtimeContext.getEmfScope()));
+ } else if (inputKey instanceof EStructuralFeatureInstancesKey) {
+ int sourcePosition = variableMapping.get(typeConstraint.getVariablesTuple().get(0));
+ int targetPosition = variableMapping.get(typeConstraint.getVariablesTuple().get(1));
+ operations.add(new StructuralFeatureCheck(sourcePosition, targetPosition,
+ ((EStructuralFeatureInstancesKey) inputKey).getEmfKey()));
+ } else if (inputKey instanceof EDataTypeInSlotsKey) {
+ operations.add(new InstanceOfDataTypeCheck(variableMapping.get(typeConstraint.getVariablesTuple().get(0)),
+ ((EDataTypeInSlotsKey) inputKey).getEmfKey()));
+ } else {
+ String msg = UNSUPPORTED_TYPE_MESSAGE + inputKey;
+ throw new QueryProcessingException(msg, null, msg, null);
+ }
+ }
+
+ @Override
+ public void createExtend(TypeConstraint typeConstraint, Map<PVariable, Integer> variableMapping) {
+ final IInputKey inputKey = typeConstraint.getSupplierKey();
+ if (inputKey instanceof EDataTypeInSlotsKey) {
+ if(baseIndexAvailable){
+ operations.add(new IterateOverEDatatypeInstances(variableMapping.get(typeConstraint.getVariableInTuple(0)), ((EDataTypeInSlotsKey) inputKey).getEmfKey()));
+ } else {
+ int position = variableMapping.get(typeConstraint.getVariableInTuple(0));
+ operations
+ .add(new org.eclipse.viatra.query.runtime.localsearch.operations.extend.nobase.IterateOverEDatatypeInstances(position,
+ ((EDataTypeInSlotsKey) inputKey).getEmfKey(), runtimeContext.getEmfScope()));
+ operations.add(new ScopeCheck(position, runtimeContext.getEmfScope()));
+ }
+ } else if (inputKey instanceof EClassTransitiveInstancesKey) {
+ if(baseIndexAvailable){
+ operations.add(new IterateOverEClassInstances(variableMapping.get(typeConstraint.getVariableInTuple(0)),
+ ((EClassTransitiveInstancesKey) inputKey).getEmfKey()));
+ } else {
+ int position = variableMapping.get(typeConstraint.getVariableInTuple(0));
+ operations
+ .add(new org.eclipse.viatra.query.runtime.localsearch.operations.extend.nobase.IterateOverEClassInstances(
+ position,
+ ((EClassTransitiveInstancesKey) inputKey).getEmfKey(), runtimeContext.getEmfScope()));
+ operations.add(new ScopeCheck(position, runtimeContext.getEmfScope()));
+ }
+ } else if (inputKey instanceof EStructuralFeatureInstancesKey) {
+ final EStructuralFeature feature = ((EStructuralFeatureInstancesKey) inputKey).getEmfKey();
+
+ int sourcePosition = variableMapping.get(typeConstraint.getVariablesTuple().get(0));
+ int targetPosition = variableMapping.get(typeConstraint.getVariablesTuple().get(1));
+
+ boolean fromBound = variableBindings.get(typeConstraint).contains(sourcePosition);
+ boolean toBound = variableBindings.get(typeConstraint).contains(targetPosition);
+
+ if (fromBound && !toBound) {
+ if (baseIndexAvailable) {
+ operations.add(new ExtendToEStructuralFeatureTarget(sourcePosition, targetPosition, feature));
+ } else {
+ operations
+ .add(new org.eclipse.viatra.query.runtime.localsearch.operations.extend.nobase.ExtendToEStructuralFeatureTarget(
+ sourcePosition, targetPosition, feature));
+ operations.add(new ScopeCheck(targetPosition, runtimeContext.getEmfScope()));
+ }
+ }
+ else if(!fromBound && toBound){
+ if (feature instanceof EReference && ((EReference)feature).isContainment()) {
+ // The iterate is also used to traverse a single container (third parameter)
+ operations.add(new IterateOverContainers(sourcePosition, targetPosition, false));
+ operations.add(new ScopeCheck(sourcePosition, runtimeContext.getEmfScope()));
+ } else if(baseIndexAvailable){
+ operations.add(new ExtendToEStructuralFeatureSource(sourcePosition, targetPosition, feature));
+ } else {
+ operations.add(new org.eclipse.viatra.query.runtime.localsearch.operations.extend.nobase.ExtendToEStructuralFeatureSource(
+ sourcePosition, targetPosition, feature));
+ operations.add(new ScopeCheck(sourcePosition, runtimeContext.getEmfScope()));
+ }
+ } else {
+ // TODO Elaborate solution based on the navigability of edges
+ // As of now a static solution is implemented
+ if (baseIndexAvailable) {
+ operations.add(new IterateOverEClassInstances(sourcePosition, feature.getEContainingClass()));
+ operations.add(new ExtendToEStructuralFeatureTarget(sourcePosition, targetPosition, feature));
+ } else {
+ operations
+ .add(new org.eclipse.viatra.query.runtime.localsearch.operations.extend.nobase.IterateOverEClassInstances(
+ sourcePosition, feature.getEContainingClass(), runtimeContext.getEmfScope()));
+ operations.add(new ScopeCheck(sourcePosition, runtimeContext.getEmfScope()));
+ operations
+ .add(new org.eclipse.viatra.query.runtime.localsearch.operations.extend.nobase.ExtendToEStructuralFeatureTarget(
+ sourcePosition, targetPosition, feature));
+ operations.add(new ScopeCheck(targetPosition, runtimeContext.getEmfScope()));
+ }
+ }
+
+ } else {
+ throw new IllegalArgumentException(UNSUPPORTED_TYPE_MESSAGE + inputKey);
+ }
+ }
+
+}
diff --git a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/compiler/GenericOperationCompiler.java b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/compiler/GenericOperationCompiler.java
new file mode 100644
index 000000000..8ba698d90
--- /dev/null
+++ b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/compiler/GenericOperationCompiler.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2010-2017, Zoltan Ujhelyi, IncQuery Labs Ltd.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Zoltan Ujhelyi - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.viatra.query.runtime.localsearch.planner.compiler;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.viatra.query.runtime.localsearch.operations.generic.GenericTypeCheck;
+import org.eclipse.viatra.query.runtime.localsearch.operations.generic.GenericTypeExtend;
+import org.eclipse.viatra.query.runtime.matchers.context.IInputKey;
+import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContext;
+import org.eclipse.viatra.query.runtime.matchers.planning.QueryProcessingException;
+import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable;
+import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.TypeFilterConstraint;
+import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint;
+import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple;
+
+/**
+ * @author Zoltan Ujhelyi
+ * @since 1.7
+ *
+ */
+public class GenericOperationCompiler extends AbstractOperationCompiler {
+
+ public GenericOperationCompiler(IQueryRuntimeContext runtimeContext) {
+ super(runtimeContext);
+ }
+
+ @Override
+ protected void createCheck(TypeFilterConstraint typeConstraint, Map<PVariable, Integer> variableMapping)
+ throws QueryProcessingException {
+ IInputKey inputKey = typeConstraint.getInputKey();
+ Tuple tuple = typeConstraint.getVariablesTuple();
+ Integer[] positions = new Integer[tuple.getSize()];
+ for (int i = 0; i < tuple.getSize(); i++) {
+ PVariable variable = (PVariable) tuple.get(i);
+ positions[i] = variableMapping.get(variable);
+ }
+ operations.add(new GenericTypeCheck(inputKey, positions));
+
+ }
+
+ @Override
+ protected void createCheck(TypeConstraint typeConstraint, Map<PVariable, Integer> variableMapping)
+ throws QueryProcessingException {
+ IInputKey inputKey = typeConstraint.getSupplierKey();
+ Tuple tuple = typeConstraint.getVariablesTuple();
+ Integer[] positions = new Integer[tuple.getSize()];
+ for (int i = 0; i < tuple.getSize(); i++) {
+ PVariable variable = (PVariable) tuple.get(i);
+ positions[i] = variableMapping.get(variable);
+ }
+ operations.add(new GenericTypeCheck(inputKey, positions));
+ }
+
+ @Override
+ protected void createExtend(TypeConstraint typeConstraint, Map<PVariable, Integer> variableMapping) {
+ IInputKey inputKey = typeConstraint.getSupplierKey();
+ Tuple tuple = typeConstraint.getVariablesTuple();
+
+ Integer[] positions = new Integer[tuple.getSize()];
+ Set<Integer> boundVariables = new HashSet<>();
+ for (int i = 0; i < tuple.getSize(); i++) {
+ PVariable variable = (PVariable) tuple.get(i);
+ Integer position = variableMapping.get(variable);
+ positions[i] = position;
+ if (variableBindings.get(typeConstraint).contains(position)) {
+ boundVariables.add(position);
+ }
+ }
+ operations.add(new GenericTypeExtend(inputKey, positions, boundVariables));
+
+ }
+
+
+
+}
diff --git a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/compiler/IOperationCompiler.java b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/compiler/IOperationCompiler.java
new file mode 100644
index 000000000..cc8974d7b
--- /dev/null
+++ b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/planner/compiler/IOperationCompiler.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2010-2017, Zoltan Ujhelyi, IncQuery Labs Ltd.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Zoltan Ujhelyi - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.viatra.query.runtime.localsearch.planner.compiler;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.viatra.query.runtime.localsearch.matcher.MatcherReference;
+import org.eclipse.viatra.query.runtime.localsearch.operations.ISearchOperation;
+import org.eclipse.viatra.query.runtime.matchers.planning.QueryProcessingException;
+import org.eclipse.viatra.query.runtime.matchers.planning.SubPlan;
+import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable;
+import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter;
+
+/**
+ * An operation compiler is responsible for creating executable search plans from the subplan structure.
+ *
+ * @author Zoltan Ujhelyi
+ * @since 1.7
+ *
+ */
+public interface IOperationCompiler {
+
+ /**
+ * Compiles a plan of <code>POperation</code>s to a list of type <code>List&ltISearchOperation></code>
+ *
+ * @param plan
+ * @param boundParameters
+ * @return an ordered list of POperations that make up the compiled search plan
+ * @throws QueryProcessingException
+ */
+ List<ISearchOperation> compile(SubPlan plan, Set<PParameter> boundParameters) throws QueryProcessingException;
+
+ Set<MatcherReference> getDependencies();
+
+ /**
+ * @return the cached variable bindings for the previously created plan
+ */
+ Map<PVariable, Integer> getVariableMappings();
+
+} \ No newline at end of file

Back to the top