/* * 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.project.structure.modules; import jetbrains.mps.project.structure.modules.mappingpriorities.MappingPriorityRule; import jetbrains.mps.smodel.Generator; import jetbrains.mps.util.annotation.ToRemove; import jetbrains.mps.util.io.ModelInputStream; import jetbrains.mps.util.io.ModelOutputStream; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.mps.openapi.module.SModuleReference; import org.jetbrains.mps.openapi.module.SRepository; import java.io.IOException; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import static java.util.stream.Collectors.toList; public class GeneratorDescriptor extends ModuleDescriptor { private String myAlias; private Set<SModuleReference> myDepGenerators; private List<MappingPriorityRule> myPriorityRules; private boolean myGenerateTemplates = false; private boolean myQueriesViaReflection = true; private String myGenOutputPath; private SModuleReference mySourceLanguage; public GeneratorDescriptor() { super(); myDepGenerators = new LinkedHashSet<>(); myPriorityRules = new ArrayList<>(); } /** * for whatever reason, getGeneratorUID() is in fact module name, or what {@link #getNamespace()} is for other modules. * In generators, {@link #getNamespace()} is employed for module alias, instead. Shall refactor this, use namespace uniformly among modules * to represent its name, and use dedicated {@code getAlias()} to keep generator short name (if needed). * @deprecated use {@link #getNamespace()} */ @Deprecated @ToRemove(version = 2017.1) public String getGeneratorUID() { return getNamespace(); } /** * @deprecated identical to {@link #setNamespace(String)} */ @Deprecated @ToRemove(version = 2017.1) public void setGeneratorUID(String generatorUID) { setNamespace(generatorUID); } public void setSourceLanguage(SModuleReference sourceLanguage) { mySourceLanguage = sourceLanguage; } public void setAlias(String alias) { myAlias = alias; } /** * While we keep machine-generated module name for Generator modules, alias is a part * which Language Designer may pick to his liking. Note, {@link Generator#getAlias()} includes * qualifed name of source language as prefix, and value of this method is only a suffix, likely kept unchanged during module renames. */ public String getAlias() { return myAlias; } /** * @return identifier of a language this generator transforms */ @NotNull public SModuleReference getSourceLanguage() { return mySourceLanguage; } public Set<SModuleReference> getDepGenerators() { return myDepGenerators; } public List<MappingPriorityRule> getPriorityRules() { return myPriorityRules; } public boolean isGenerateTemplates() { return myGenerateTemplates; } public void setGenerateTemplates(boolean generateTemplates) { myGenerateTemplates = generateTemplates; } /** * @return <code>true</code> to execute method in QueriesGenerated via reflection, * <code>false</code> to provide mechanism for direct calls */ public boolean isReflectiveQueries() { return myQueriesViaReflection; } public void setReflectiveQueries(boolean value) { myQueriesViaReflection = value; } /** * Expects at least model read access (although likely no reason to invoke in any other case but from write that modified smth) * @param repository where to look old/new module references up. */ @Override public boolean updateModuleRefs(SRepository repository) { RefUpdateUtil uu = new RefUpdateUtil(repository); return RefUpdateUtil.composeUpdates( super.updateModuleRefs(repository), uu.updateModuleRefs(myDepGenerators), uu.updateMappingPriorityRules(myPriorityRules)); } /** * FIXME Likely, {@link SolutionDescriptor#getOutputPath()}, {@link LanguageDescriptor#getGenPath()} and this one need to move to * ModuleDescriptor. I would do that once there's clear idea whether to use IFile, java.io.File or Path for these locations, * and whether to keep these as module descriptor attributes or inside relevant {@link jetbrains.mps.project.facets.GenerationTargetFacet facets}. * @return filesystem location where generated files for the generator go, or null if this module doesn't support output */ @Nullable public String getOutputPath() { return myGenOutputPath; } public void setOutputPath(@Nullable String path) { myGenOutputPath = path; } @Override protected int getHeaderMarker() { return 0x45459797; } @Override public void save(ModelOutputStream stream) throws IOException { super.save(stream); stream.writeString(myAlias); stream.writeBoolean(myGenerateTemplates); stream.writeString(myGenOutputPath); stream.writeModuleReference(mySourceLanguage); stream.writeInt(myDepGenerators.size()); for (SModuleReference ref : myDepGenerators) { stream.writeModuleReference(ref); } stream.writeInt(myPriorityRules.size()); for (MappingPriorityRule rule : myPriorityRules) { rule.save(stream); } } @Override public void load(ModelInputStream stream) throws IOException { super.load(stream); myAlias = stream.readString(); myGenerateTemplates = stream.readBoolean(); myGenOutputPath = stream.readString(); mySourceLanguage = stream.readModuleReference(); myDepGenerators.clear(); for (int size = stream.readInt(); size > 0; size--) { myDepGenerators.add(stream.readModuleReference()); } for (int size = stream.readInt(); size > 0; size--) { MappingPriorityRule rule = new MappingPriorityRule(); rule.load(stream); myPriorityRules.add(rule); } } @NotNull @Override public GeneratorDescriptor copy() { GeneratorDescriptor copy = super.copy0(GeneratorDescriptor::new); copy.setAlias(myAlias); copy.setGenerateTemplates(isGenerateTemplates()); copy.setOutputPath(getOutputPath()); copy.setReflectiveQueries(isReflectiveQueries()); copy.setSourceLanguage(getSourceLanguage()); copy.getDepGenerators().addAll(getDepGenerators()); copy.getPriorityRules().addAll(getPriorityRules().stream().map(MappingPriorityRule::copy).collect(toList())); return copy; } }