/* * Copyright 2003-2017 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.interpreted; import jetbrains.mps.generator.impl.GenerationFailureException; import jetbrains.mps.generator.impl.RuleUtil; import jetbrains.mps.generator.impl.TemplateQueryException; import jetbrains.mps.generator.impl.query.MapConfigurationCondition; import jetbrains.mps.generator.impl.query.QueryKey; import jetbrains.mps.generator.impl.query.QueryKeyImpl; import jetbrains.mps.generator.impl.query.QueryProviderBase; 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.TemplateWeavingRule; import jetbrains.mps.generator.template.ITemplateGenerator; import jetbrains.mps.generator.template.TemplateQueryContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.mps.openapi.language.SConcept; 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.List; /** * Evgeny Gryaznov, Nov 29, 2010 */ public class TemplateMappingConfigurationInterpreted implements TemplateMappingConfiguration { private final SNode myMappingConfiguration; private final TemplateModel myModel; private List<TemplateReductionRule> myReductionRules; private List<TemplateCreateRootRule> myCreateRootRules; private List<TemplateRootMappingRule> myRootMappingRules; private List<TemplateWeavingRule> myWeavingRules; private List<TemplateDropRootRule> myDropRootRules; private List<TemplateMappingScript> myPreScripts; private List<TemplateMappingScript> myPostScripts; private List<TemplateDropAttributeRule> myDropAttributeRules; private MapConfigurationCondition myCondition; private volatile boolean myInitialized = false; public TemplateMappingConfigurationInterpreted(TemplateModel model, SNode mappingConfiguration) { myModel = model; myMappingConfiguration = mappingConfiguration; } private void init() { if (myInitialized) { return; } synchronized (this) { myCreateRootRules = new ArrayList<TemplateCreateRootRule>(5); myRootMappingRules = new ArrayList<TemplateRootMappingRule>(5); myWeavingRules = new ArrayList<TemplateWeavingRule>(5); myDropRootRules = new ArrayList<TemplateDropRootRule>(5); myDropAttributeRules = new ArrayList<TemplateDropAttributeRule>(5); myPreScripts = new ArrayList<TemplateMappingScript>(5); myPostScripts = new ArrayList<TemplateMappingScript>(5); ArrayList<TemplateReductionRule> reductionRules = new ArrayList<TemplateReductionRule>(20); ArrayList<TemplateReductionRule> patternRules = new ArrayList<TemplateReductionRule>(5); for (SNode child : myMappingConfiguration.getChildren()) { final SConcept childConcept = child.getConcept(); if (RuleUtil.concept_Reduction_MappingRule.equals(childConcept)) { reductionRules.add(new TemplateReductionRuleInterpreted(child)); } else if (RuleUtil.concept_Root_MappingRule.equals(childConcept)) { myRootMappingRules.add(new TemplateRootMappingRuleInterpreted(child)); } else if (RuleUtil.concept_PatternReduction_MappingRule.equals(childConcept)) { patternRules.add(new TemplateReductionPatternRuleInterpreted(child)); } else if (RuleUtil.concept_CreateRootRule.equals(childConcept)) { myCreateRootRules.add(new TemplateCreateRootRuleInterpreted(child)); } else if (RuleUtil.concept_Weaving_MappingRule.equals(childConcept)) { myWeavingRules.add(new TemplateWeavingRuleInterpreted(child)); } else if (RuleUtil.concept_DropRootRule.equals(childConcept)) { myDropRootRules.add(new TemplateDropRuleInterpreted(child)); } else if (RuleUtil.concept_MappingScriptReference.equals(childConcept)) { SNode mappingScript = RuleUtil.getMappingScriptReference_Script(child); if (mappingScript == null) { continue; } if (RuleUtil.link_MappingConfiguration_preMappingScript.equals(child.getContainmentLink())) { myPreScripts.add(new TemplateMappingScriptInterpreted(mappingScript)); } else { myPostScripts.add(new TemplateMappingScriptInterpreted(mappingScript)); } } else if (RuleUtil.concept_DropAttributeRule.equals(childConcept)) { myDropAttributeRules.add(new DropAttributeRuleInterpreted(child)); } } if (patternRules.isEmpty()) { myReductionRules = reductionRules; } else { myReductionRules = new ArrayList<TemplateReductionRule>(patternRules.size() + reductionRules.size()); myReductionRules.addAll(patternRules); myReductionRules.addAll(reductionRules); } myInitialized = true; } } @Override public boolean isTopPriority() { return RuleUtil.getMappingConfiguration_TopPrio(myMappingConfiguration); } @Override public SNodeReference getMappingNode() { return myMappingConfiguration.getReference(); } @Override public boolean isApplicable(ITemplateGenerator generator) throws GenerationFailureException { try { if (myCondition == null) { SNode condition = RuleUtil.getMappingConfiguration_IsApplicable(myMappingConfiguration); if (condition != null) { QueryKey identity = new QueryKeyImpl(getMappingNode(), condition.getNodeId(), myMappingConfiguration); myCondition = generator.getQueryProvider(getMappingNode()).getMapConfigurationCondition(identity); } else { myCondition = new QueryProviderBase.Defaults(); } } return myCondition.check(new TemplateQueryContext(getMappingNode(), generator)); } catch (GenerationFailureException ex) { throw ex; } catch(Throwable th) { // FIXME technically, this catch shall be inside DefaultQueryExecutionContext, where all such catch are kept. But there's no corresponding method in DQEC TemplateQueryException ex = new TemplateQueryException("error executing map config condition", th); ex.setTemplateModelLocation(getMappingNode()); throw ex; } } @Override public String getName() { return myMappingConfiguration.getName(); } @Override public Collection<TemplateRootMappingRule> getRootRules() { init(); return myRootMappingRules; } @Override public Collection<TemplateCreateRootRule> getCreateRules() { init(); return myCreateRootRules; } @Override public Collection<TemplateDropRootRule> getDropRules() { init(); return myDropRootRules; } @Override public Collection<TemplateReductionRule> getReductionRules() { init(); return myReductionRules; } @Override public Collection<TemplateWeavingRule> getWeavingRules() { init(); return myWeavingRules; } @Override public Collection<TemplateMappingScript> getPreScripts() { init(); return myPreScripts; } @Override public Collection<TemplateMappingScript> getPostScripts() { init(); return myPostScripts; } @NotNull @Override public Collection<TemplateDropAttributeRule> getDropAttributeRules() { init(); return myDropAttributeRules; } @Override public TemplateModel getModel() { return myModel; } }