/*
* Copyright 2003-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jetbrains.mps.generator.impl.template;
import jetbrains.mps.generator.impl.GenerationFailureException;
import jetbrains.mps.generator.impl.dependencies.DependenciesReadListener;
import jetbrains.mps.generator.impl.interpreted.TemplateCreateRootRuleInterpreted;
import jetbrains.mps.generator.impl.interpreted.TemplateRootMappingRuleInterpreted;
import jetbrains.mps.generator.impl.query.CallArgumentQuery;
import jetbrains.mps.generator.impl.query.IfMacroCondition;
import jetbrains.mps.generator.impl.query.InlineSwitchCaseCondition;
import jetbrains.mps.generator.impl.query.InsertMacroQuery;
import jetbrains.mps.generator.impl.query.MapNodeQuery;
import jetbrains.mps.generator.impl.query.MapPostProcessor;
import jetbrains.mps.generator.impl.query.PropertyValueQuery;
import jetbrains.mps.generator.impl.query.ReferenceTargetQuery;
import jetbrains.mps.generator.impl.query.SourceNodeQuery;
import jetbrains.mps.generator.impl.query.SourceNodesQuery;
import jetbrains.mps.generator.impl.query.VariableValueQuery;
import jetbrains.mps.generator.runtime.GenerationException;
import jetbrains.mps.generator.runtime.TemplateContext;
import jetbrains.mps.generator.runtime.TemplateCreateRootRule;
import jetbrains.mps.generator.runtime.TemplateExecutionEnvironment;
import jetbrains.mps.generator.runtime.TemplateMappingScript;
import jetbrains.mps.generator.runtime.TemplateReductionRule;
import jetbrains.mps.generator.runtime.TemplateRootMappingRule;
import jetbrains.mps.generator.runtime.TemplateRuleWithCondition;
import jetbrains.mps.generator.runtime.TemplateWeavingRule;
import jetbrains.mps.generator.template.IfMacroContext;
import jetbrains.mps.generator.template.InlineSwitchCaseContext;
import jetbrains.mps.generator.template.InsertMacroContext;
import jetbrains.mps.generator.template.MapSrcMacroContext;
import jetbrains.mps.generator.template.MapSrcMacroPostProcContext;
import jetbrains.mps.generator.template.PropertyMacroContext;
import jetbrains.mps.generator.template.QueryExecutionContext;
import jetbrains.mps.generator.template.ReferenceMacroContext;
import jetbrains.mps.generator.template.SourceSubstituteMacroNodeContext;
import jetbrains.mps.generator.template.SourceSubstituteMacroNodesContext;
import jetbrains.mps.generator.template.TemplateArgumentContext;
import jetbrains.mps.generator.template.TemplateVarContext;
import jetbrains.mps.smodel.NodeReadEventsCaster;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.mps.openapi.model.SModel;
import org.jetbrains.mps.openapi.model.SNode;
import java.util.Collection;
/**
* Evgeny Gryaznov, May 12, 2010
*/
public class QueryExecutionContextWithDependencyRecording implements QueryExecutionContext {
private final QueryExecutionContext wrapped;
private final DependenciesReadListener listener;
public QueryExecutionContextWithDependencyRecording(QueryExecutionContext wrapped, DependenciesReadListener listener) {
this.wrapped = wrapped;
this.listener = listener;
}
@Override
public boolean evaluate(@NotNull InlineSwitchCaseCondition condition, @NotNull InlineSwitchCaseContext context) throws GenerationFailureException {
try {
NodeReadEventsCaster.setNodesReadListener(listener);
return wrapped.evaluate(condition, context);
} finally {
NodeReadEventsCaster.removeNodesReadListener();
}
}
@Override
public boolean evaluate(@NotNull IfMacroCondition condition, @NotNull IfMacroContext context) throws GenerationFailureException {
try {
NodeReadEventsCaster.setNodesReadListener(listener);
return wrapped.evaluate(condition, context);
} finally {
NodeReadEventsCaster.removeNodesReadListener();
}
}
@Nullable
@Override
public SNode evaluate(@NotNull MapNodeQuery query, @NotNull MapSrcMacroContext context) throws GenerationFailureException {
try {
NodeReadEventsCaster.setNodesReadListener(listener);
return wrapped.evaluate(query, context);
} finally {
NodeReadEventsCaster.removeNodesReadListener();
}
}
@Override
public void execute(@NotNull MapPostProcessor codeBlock, @NotNull MapSrcMacroPostProcContext context) throws GenerationFailureException {
try {
NodeReadEventsCaster.setNodesReadListener(listener);
wrapped.execute(codeBlock, context);
} finally {
NodeReadEventsCaster.removeNodesReadListener();
}
}
@Nullable
@Override
public Object evaluate(@NotNull PropertyValueQuery query, @NotNull PropertyMacroContext context) throws GenerationFailureException {
try {
NodeReadEventsCaster.setNodesReadListener(listener);
return wrapped.evaluate(query, context);
} finally {
NodeReadEventsCaster.removeNodesReadListener();
}
}
@Nullable
@Override
public SNode evaluate(@NotNull SourceNodeQuery query, @NotNull SourceSubstituteMacroNodeContext context) throws GenerationFailureException {
try {
NodeReadEventsCaster.setNodesReadListener(listener);
return wrapped.evaluate(query, context);
} finally {
NodeReadEventsCaster.removeNodesReadListener();
}
}
@Nullable
@Override
public Object evaluate(@NotNull CallArgumentQuery query, @NotNull TemplateArgumentContext context) throws GenerationFailureException {
try {
NodeReadEventsCaster.setNodesReadListener(listener);
return wrapped.evaluate(query, context);
} finally {
NodeReadEventsCaster.removeNodesReadListener();
}
}
@Nullable
@Override
public Object evaluate(@NotNull VariableValueQuery query, @NotNull TemplateVarContext context) throws GenerationFailureException {
try {
NodeReadEventsCaster.setNodesReadListener(listener);
return wrapped.evaluate(query, context);
} finally {
NodeReadEventsCaster.removeNodesReadListener();
}
}
@NotNull
@Override
public Collection<SNode> evaluate(@NotNull SourceNodesQuery query, @NotNull SourceSubstituteMacroNodesContext context) throws GenerationFailureException {
try {
NodeReadEventsCaster.setNodesReadListener(listener);
return wrapped.evaluate(query, context);
} finally {
NodeReadEventsCaster.removeNodesReadListener();
}
}
@Nullable
@Override
public SNode evaluate(@NotNull InsertMacroQuery query, @NotNull InsertMacroContext context) throws GenerationFailureException {
try {
NodeReadEventsCaster.setNodesReadListener(listener);
return wrapped.evaluate(query, context);
} finally {
NodeReadEventsCaster.removeNodesReadListener();
}
}
@Nullable
@Override
public Object evaluate(@NotNull ReferenceTargetQuery query, @NotNull ReferenceMacroContext context) throws GenerationFailureException {
try {
NodeReadEventsCaster.setNodesReadListener(listener);
return wrapped.evaluate(query, context);
} finally {
NodeReadEventsCaster.removeNodesReadListener();
}
}
@Override
public Collection<SNode> applyRule(TemplateReductionRule rule, TemplateContext context) throws GenerationException {
try {
final DependenciesReadListener l;
if (context.getEnvironment().getGenerator().isIncremental()) {
// this code used to be in TemplateReductionRuleInterpreted, added to address MPS-16916
// Moved here for next reasons: (a) generated rules shall behave the same as interpreted;
// (b) this class is the only place we install listeners via NodeReadEventsCaster, and there shall be no way to get into TRRI with a
// listener installed (for TRRI to uninstall one) other than through this method.
// However, I don't understand why there's difference in change tracking in incremental vs non-incremental mode,
// and why only reduction rules are considered.
l = null; // turn tracing off
} else {
l = listener;
}
NodeReadEventsCaster.setNodesReadListener(l);
return wrapped.applyRule(rule, context);
} finally {
NodeReadEventsCaster.removeNodesReadListener();
}
}
@Override
public boolean isApplicable(@NotNull TemplateRuleWithCondition rule, @NotNull TemplateContext context) throws GenerationFailureException {
try {
NodeReadEventsCaster.setNodesReadListener(listener);
return wrapped.isApplicable(rule, context);
} finally {
NodeReadEventsCaster.removeNodesReadListener();
}
}
@Override
public Collection<SNode> applyRule(TemplateRootMappingRule rule, TemplateContext context) throws GenerationException {
if(rule instanceof TemplateRootMappingRuleInterpreted) {
return wrapped.applyRule(rule, context);
}
try {
NodeReadEventsCaster.setNodesReadListener(listener);
return wrapped.applyRule(rule, context);
} finally {
NodeReadEventsCaster.removeNodesReadListener();
}
}
@Override
public Collection<SNode> applyRule(TemplateCreateRootRule rule, TemplateExecutionEnvironment environment) throws GenerationException {
if(rule instanceof TemplateCreateRootRuleInterpreted) {
return wrapped.applyRule(rule, environment);
}
try {
NodeReadEventsCaster.setNodesReadListener(listener);
return wrapped.applyRule(rule, environment);
} finally {
NodeReadEventsCaster.removeNodesReadListener();
}
}
@Override
public boolean applyRule(TemplateWeavingRule rule, TemplateContext context, SNode outputContextNode) throws GenerationException {
// FIXME why there's code above not to listen when interpreted rule is applied? Should I do the same here?
try {
NodeReadEventsCaster.setNodesReadListener(listener);
return wrapped.applyRule(rule, context, outputContextNode);
} finally {
NodeReadEventsCaster.removeNodesReadListener();
}
}
@Override
public SNode getContextNode(TemplateWeavingRule rule, TemplateContext context) throws GenerationFailureException {
try {
NodeReadEventsCaster.setNodesReadListener(listener);
return wrapped.getContextNode(rule, context);
} finally {
NodeReadEventsCaster.removeNodesReadListener();
}
}
@Override
public void executeScript(TemplateMappingScript mappingScript, SModel model) throws GenerationFailureException {
try {
NodeReadEventsCaster.setNodesReadListener(listener);
wrapped.executeScript(mappingScript, model);
} finally {
NodeReadEventsCaster.removeNodesReadListener();
}
}
@Override
public boolean isMultithreaded() {
return false;
}
}