/* * 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; import jetbrains.mps.extapi.module.ModuleFacetBase; import jetbrains.mps.generator.impl.GenPlanTranslator; import jetbrains.mps.generator.impl.plan.EngagedGeneratorCollector; import jetbrains.mps.generator.impl.plan.RegularPlanBuilder; import jetbrains.mps.smodel.language.LanguageRegistry; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.mps.openapi.model.SModel; import org.jetbrains.mps.openapi.model.SModelReference; import org.jetbrains.mps.openapi.persistence.Memento; import org.jetbrains.mps.openapi.persistence.PersistenceFacade; /** * @author Artem Tikhomirov * @since 3.3 */ public class CustomGenerationModuleFacet extends ModuleFacetBase implements ModelGenerationPlan.Provider { public static final String FACET_TYPE = "generator"; private SModelReference myPlanModel; private ModelGenerationPlan myCachedPlanInstance; private long myCachedPlanTimestamp; public CustomGenerationModuleFacet() { super(FACET_TYPE); } @Override public String getFacetPresentation() { return "Custom generation"; } @Nullable public ModelGenerationPlan getPlan(@NotNull SModel model) { if (myPlanModel == null) { return null; } SModel planModel = myPlanModel.resolve(model.getRepository()); if (planModel == null || !planModel.getRootNodes().iterator().hasNext()) { return null; } final long modelActualTimestamp = planModel.getSource().getTimestamp(); if (myCachedPlanInstance != null && myCachedPlanTimestamp == modelActualTimestamp) { // as long as there's single plan per module, no need to create MGP instance for each model, reuse. return myCachedPlanInstance; } myCachedPlanTimestamp = modelActualTimestamp; GenPlanTranslator gpt = new GenPlanTranslator(planModel.getRootNodes().iterator().next()); EngagedGeneratorCollector egc = new EngagedGeneratorCollector(model, null); // see comment in GenPlanExtractor regarding additional languages RegularPlanBuilder planBuilder = new RegularPlanBuilder(LanguageRegistry.getInstance(model.getRepository()), egc.getGenerators()); gpt.feed(planBuilder); myCachedPlanInstance = planBuilder.wrapUp(gpt.getPlanIdentity()); return myCachedPlanInstance; } // despite public, these methods are not part of the contract. // it's facet's implementation details @Nullable public SModelReference getPlanModelReference() { return myPlanModel; } public void setPlanModelReference(@Nullable SModelReference modelRef) { myPlanModel = modelRef; myCachedPlanInstance = null; } @Override public void load(Memento memento) { String value = memento.get("planModel"); myPlanModel = value == null ? null : PersistenceFacade.getInstance().createModelReference(value); } @Override public void save(Memento memento) { memento.put("planModel", myPlanModel == null ? null : PersistenceFacade.getInstance().asString(myPlanModel)); } }