/* * 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.test; import jetbrains.mps.extapi.model.PersistenceProblem; import jetbrains.mps.extapi.model.SModelBase; import jetbrains.mps.project.AbstractModule; import jetbrains.mps.project.ModuleId; import jetbrains.mps.project.structure.modules.ModuleDescriptor; import jetbrains.mps.project.structure.modules.ModuleReference; import jetbrains.mps.smodel.InvalidSModel; import jetbrains.mps.smodel.ModelLoadResult; import jetbrains.mps.smodel.RegularModelDescriptor; import jetbrains.mps.smodel.loading.ModelLoadingState; import jetbrains.mps.smodel.persistence.def.ModelPersistence; import jetbrains.mps.smodel.persistence.def.ModelReadException; import jetbrains.mps.util.JDOMUtil; import org.jdom.Document; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.mps.openapi.language.SLanguage; import org.jetbrains.mps.openapi.model.SModel; import org.jetbrains.mps.openapi.model.SModel.Problem; import org.jetbrains.mps.openapi.model.SModel.Problem.Kind; import org.jetbrains.mps.openapi.model.SModelId; import org.jetbrains.mps.openapi.model.SModelReference; import org.jetbrains.mps.openapi.module.SDependency; import org.jetbrains.mps.openapi.module.SModule; import org.jetbrains.mps.openapi.module.SModuleReference; import org.jetbrains.mps.openapi.persistence.NullDataSource; import org.jetbrains.mps.openapi.persistence.PersistenceFacade; import java.util.Collections; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** * Evgeny Gryaznov, 10/18/10 */ public class TestModule extends AbstractModule { private SModule myPeer; private Map<String, SModel> myModels = new ConcurrentHashMap<String, SModel>(); public TestModule(String namespace, String moduleId, SModule peer) { myPeer = peer; SModuleReference reference = new ModuleReference(namespace, ModuleId.fromString(moduleId)); setModuleReference(reference); } @Override public void dispose() { clearAll(); super.dispose(); } private void clearAll() { myPeer = null; myModels.clear(); dependenciesChanged(); } public SModel createModel(SModel originalModel) { String originalLong = originalModel.getName().getLongName(); String newModelName = originalLong + "@999"; SModel result = new TestSModelDescriptor(newModelName, originalModel); myModels.put(result.getName().getValue(), result); return result; } public void publish(SModel descr) { registerModel((SModelBase) descr); } public String toString() { return getModuleName() + " [test transient module]"; } @Override public ModuleDescriptor getModuleDescriptor() { // todo: is it ok? // At least, JavaModuleFacet cares about proper module descriptor (although it's not obvious whether there's JMF for this module at all) // What are scenarios for this TestModule anyway? return ((AbstractModule) myPeer).getModuleDescriptor(); } @Override public SModel getModel(SModelId id) { SModel m = super.getModel(id); if (m == null) { boolean own = id.getModelName() != null && myModels.containsKey(id.getModelName()); m = own ? myModels.get(id.getModelName()) : null; } return m; } @Override public Iterable<SDependency> getDeclaredDependencies() { return myPeer.getDeclaredDependencies(); } @Override public Set<SLanguage> getUsedLanguages() { return myPeer.getUsedLanguages(); } class TestSModelDescriptor extends RegularModelDescriptor { private final SModel myToCopy; private TestSModelDescriptor(String modelName, SModel toCopy) { super(PersistenceFacade.getInstance().createModelReference(null, jetbrains.mps.smodel.SModelId.generate(), modelName), new NullDataSource()); myToCopy = toCopy; } @NotNull @Override public ModelLoadResult<jetbrains.mps.smodel.SModel> createModel() { if (!myToCopy.isLoaded()) { // we are going to access internal/implementation model which might be in a partially-loaded // state (only public API guarantees proper loading). With partial model, we could face odd // issues (e.g. incomplete set of implicit imports as implementation node's concepts are not considered) myToCopy.load(); } Document document = ModelPersistence.saveModel(((SModelBase) myToCopy).getSModel()); Element rootElement = document.getRootElement(); rootElement.setAttribute(ModelPersistence.REF, getReference().toString()); String modelContent = JDOMUtil.asString(document); try { return new ModelLoadResult<jetbrains.mps.smodel.SModel>(ModelPersistence.readModel(modelContent, false), ModelLoadingState.FULLY_LOADED); } catch (ModelReadException e) { return new ModelLoadResult<jetbrains.mps.smodel.SModel>(new StubModel(PersistenceFacade.getInstance().createModelReference(getName().getLongName()), e), ModelLoadingState.FULLY_LOADED); } } } private static class StubModel extends jetbrains.mps.smodel.SModel implements InvalidSModel { private ModelReadException myCause; public StubModel(@NotNull SModelReference modelReference, @Nullable ModelReadException cause) { super(modelReference); myCause = cause; } @NotNull @Override public Iterable<Problem> getProblems() { return Collections.<Problem>singleton( new PersistenceProblem(Kind.Load, myCause == null ? "Couldn't read model." : myCause.getMessageEx(), null, true)); } } }