/* * 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; import jetbrains.mps.generator.runtime.TemplateCreateRootRule; import jetbrains.mps.generator.runtime.TemplateDropAttributeRule; import jetbrains.mps.generator.runtime.TemplateDropRootRule; import jetbrains.mps.generator.runtime.TemplateMappingConfiguration; import jetbrains.mps.generator.runtime.TemplateMappingScript; import jetbrains.mps.generator.runtime.TemplateModel; import jetbrains.mps.generator.runtime.TemplateReductionRule; import jetbrains.mps.generator.runtime.TemplateRootMappingRule; import jetbrains.mps.generator.runtime.TemplateSwitchMapping; import jetbrains.mps.generator.runtime.TemplateWeavingRule; import jetbrains.mps.util.FlattenIterable; import org.jetbrains.annotations.NotNull; import org.jetbrains.mps.openapi.model.SNode; import org.jetbrains.mps.openapi.model.SNodeReference; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.List; /** * Manages rules/templates/switches of a major step. */ public class RuleManager { private FlattenIterable<TemplateCreateRootRule> myCreateRootRules; private FlattenIterable<TemplateRootMappingRule> myRoot_MappingRules; private FlattenIterable<TemplateWeavingRule> myWeaving_MappingRules; private final TemplateSwitchGraph myTemplateSwitchGraph; private final ScriptManager myPreScripts, myPostScripts; private final FastRuleFinder<TemplateReductionRule> myReductionRuleFinder; private final FastRuleFinder<TemplateDropRootRule> myDropRuleFinder; private final FastRuleFinder<TemplateDropAttributeRule> myDropAttributeFinder; /** * * @param configurations where to pick rules for the step from * @param templateModels where to look for switches * @throws GenerationFailureException if there are troubles building relevant information (e.g. cycles in switch extends) */ public RuleManager(List<TemplateMappingConfiguration> configurations, Collection<TemplateModel> templateModels) throws GenerationFailureException { myTemplateSwitchGraph = new TemplateSwitchGraph(templateModels); myCreateRootRules = new FlattenIterable<TemplateCreateRootRule>(configurations.size()); myRoot_MappingRules = new FlattenIterable<TemplateRootMappingRule>(configurations.size()); myWeaving_MappingRules = new FlattenIterable<TemplateWeavingRule>(configurations.size()); FlattenIterable<TemplateDropRootRule> dropRootRules = new FlattenIterable<TemplateDropRootRule>(configurations.size()); FlattenIterable<TemplateDropAttributeRule> dropAttributeRules = new FlattenIterable<TemplateDropAttributeRule>(configurations.size()); FlattenIterable<TemplateReductionRule> reductionRules = new FlattenIterable<TemplateReductionRule>(); LinkedList<TemplateMappingScript> postScripts = new LinkedList<TemplateMappingScript>(); LinkedList<TemplateMappingScript> preScripts = new LinkedList<TemplateMappingScript>(); for (TemplateMappingConfiguration mappingConfig : configurations) { myCreateRootRules.add(mappingConfig.getCreateRules()); myRoot_MappingRules.add(mappingConfig.getRootRules()); myWeaving_MappingRules.add(mappingConfig.getWeavingRules()); dropRootRules.add(mappingConfig.getDropRules()); dropAttributeRules.add(mappingConfig.getDropAttributeRules()); reductionRules.add(mappingConfig.getReductionRules()); for (TemplateMappingScript postMappingScript : mappingConfig.getPostScripts()) { if (postMappingScript.getKind() != TemplateMappingScript.POSTPROCESS) { continue; } postScripts.add(postMappingScript); } for (TemplateMappingScript preMappingScript : mappingConfig.getPreScripts()) { if (preMappingScript.getKind() != TemplateMappingScript.PREPROCESS) { continue; } preScripts.add(preMappingScript); } } myReductionRuleFinder = new FastRuleFinder<TemplateReductionRule>(reductionRules); myDropRuleFinder = new FastRuleFinder<TemplateDropRootRule>(dropRootRules); myDropAttributeFinder = new FastRuleFinder<TemplateDropAttributeRule>(dropAttributeRules); myPreScripts = new ScriptManager(preScripts.isEmpty() ? Collections.<TemplateMappingScript>emptyList() : new ArrayList<TemplateMappingScript>(preScripts)); myPostScripts = new ScriptManager(postScripts.isEmpty() ? Collections.<TemplateMappingScript>emptyList() : new ArrayList<TemplateMappingScript>(postScripts)); } @NotNull public Iterable<TemplateCreateRootRule> getCreateRootRules() { return myCreateRootRules; } @NotNull public Iterable<TemplateRootMappingRule> getRoot_MappingRules() { return myRoot_MappingRules; } @NotNull public Iterable<TemplateWeavingRule> getWeaving_MappingRules() { return myWeaving_MappingRules; } @NotNull public List<TemplateDropRootRule> getDropRootRules(SNode inputRootNode) { final List<TemplateDropRootRule> rv = myDropRuleFinder.findReductionRules(inputRootNode); return rv == null ? Collections.<TemplateDropRootRule>emptyList() : rv; } @NotNull public List<TemplateDropAttributeRule> getDropAttributeRules(@NotNull SNode attributeNode) { List<TemplateDropAttributeRule> rules = myDropAttributeFinder.findReductionRules(attributeNode); return rules == null ? Collections.<TemplateDropAttributeRule>emptyList() : rules; } @NotNull public FastRuleFinder<TemplateReductionRule> getReductionRules() { return myReductionRuleFinder; } public FastRuleFinder getSwitchRules(SNodeReference switch_) { return myTemplateSwitchGraph.getRuleFinder(switch_); } public TemplateSwitchMapping getSwitch(SNodeReference switch_) { return myTemplateSwitchGraph.getSwitch(switch_); } public ScriptManager getPreProcessScripts() { return myPreScripts; } public ScriptManager getPostProcessScripts() { return myPostScripts; } public final class ScriptManager { private final List<TemplateMappingScript> myScripts; public ScriptManager(List<TemplateMappingScript> scripts) { myScripts = scripts; } public List<TemplateMappingScript> getScripts() { return myScripts; } public boolean isEmpty() { return myScripts.isEmpty(); } public boolean modifiesModel() { for (TemplateMappingScript script : myScripts) { if (script.modifiesModel()) { return true; } } return false; } } }