/*
* ******************************************************************************
* MontiCore Language Workbench
* Copyright (c) 2015, MontiCore, All rights reserved.
*
* This project is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this project. If not, see <http://www.gnu.org/licenses/>.
* ******************************************************************************
*/
package de.monticore;
import com.google.common.collect.ImmutableList;
import de.monticore.ast.ASTNode;
import de.monticore.modelloader.ModelingLanguageModelLoader;
import de.monticore.symboltable.Symbol;
import de.monticore.symboltable.resolving.ResolvingFilter;
import de.se_rwth.commons.logging.Log;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Optional;
import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.isNullOrEmpty;
/**
* Base class for language families. Provides access to language-related
* functionality, like parsing, model analysis and code generation.
*
* @author Pedram Mir Seyed Nazari
*
*/
// TODO PN extract interface, analogous to ModelingLanguage
public class ModelingLanguageFamily {
// TODO PN adding of other modeling language families should be possible, too.
// TODO PN add name for language family?
private final Collection<ModelingLanguage> modelingLanguages = new LinkedHashSet<>();
/**
* All resolvers added directly to this language family (not those of the single modeling
* languages).
*/
private final Collection<ResolvingFilter<? extends Symbol>> resolvingFilters = new LinkedHashSet<>();
public Optional<ModelingLanguage> getLanguageByFileExtension(final String fileExtension) {
checkArgument(!isNullOrEmpty(fileExtension), "File extension may not be null or empty");
final String cleanedFileExtension = fileExtension.startsWith(".")
? fileExtension.substring(1) : fileExtension;
for (ModelingLanguage modelingLanguage : modelingLanguages) {
if (modelingLanguage.getFileExtension().equals(cleanedFileExtension)) {
return Optional.of(modelingLanguage);
}
}
return Optional.empty();
}
public void addModelingLanguage(final ModelingLanguage newModelingLanguage) {
Log.errorIfNull(newModelingLanguage);
for (ModelingLanguage modelingLanguage : modelingLanguages) {
if (modelingLanguage.getFileExtension().equals(newModelingLanguage.getFileExtension())) {
Log.info("0xA1027 The languages \"" + modelingLanguage.getName() + "\" and \"" +
newModelingLanguage.getName() + "\" use both the file extension \"" + modelingLanguage
.getFileExtension() + "\".", ModelingLanguageFamily.class.getName());
}
}
modelingLanguages.add(newModelingLanguage);
}
public Collection<ModelingLanguage> getModelingLanguages() {
return ImmutableList.copyOf(modelingLanguages);
}
/**
* @return all resolvers specified in this language family and all its single languages.
*/
public Collection<ResolvingFilter<? extends Symbol>> getAllResolvers() {
final Collection<ResolvingFilter<? extends Symbol>> allResolvingFilters = new LinkedHashSet<>();
allResolvingFilters.addAll(resolvingFilters);
for (ModelingLanguage language : modelingLanguages) {
allResolvingFilters.addAll(language.getResolvingFilters());
}
return allResolvingFilters;
}
/**
* Adds a {@link de.monticore.symboltable.resolving.ResolvingFilter} directly to this language family.
* Usually, only {@link de.monticore.symboltable.resolving.CommonAdaptedResolvingFilter}s
* need to be added, since the modeling languages already define their default resolvers (see
* {@link ModelingLanguage#getResolvingFilters()}).
*
* @param resolvingFilter the resolver to be added
*/
public void addResolver(ResolvingFilter<? extends Symbol> resolvingFilter) {
resolvingFilters.add(resolvingFilter);
}
public Collection<ModelingLanguageModelLoader<? extends ASTNode>> getAllModelLoaders() {
final Collection<ModelingLanguageModelLoader<? extends ASTNode>> allModelLoader =
modelingLanguages.stream().map(ModelingLanguage::getModelLoader).collect(Collectors.toSet());
return allModelLoader;
}
}