/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
/**
* Created by christoferdutz on 20.09.14.
*/
public final class LanguageRegistry {
private static LanguageRegistry instance = new LanguageRegistry();
private Map<String, Language> languages;
private LanguageRegistry() {
List<Language> languagesList = new ArrayList<>();
ServiceLoader<Language> languageLoader = ServiceLoader.load(Language.class);
Iterator<Language> iterator = languageLoader.iterator();
while (iterator.hasNext()) {
try {
Language language = iterator.next();
languagesList.add(language);
} catch (UnsupportedClassVersionError e) {
// Some languages require java8 and are therefore only available
// if java8 or later is used as runtime.
System.err.println("Ignoring language for PMD: " + e.toString());
}
}
// sort languages by terse name. Avoiding differences in the order of languages
// across JVM versions / OS.
Collections.sort(languagesList, new Comparator<Language>() {
@Override
public int compare(Language o1, Language o2) {
return o1.getTerseName().compareToIgnoreCase(o2.getTerseName());
}
});
// using a linked hash map to maintain insertion order
languages = new LinkedHashMap<>();
for (Language language : languagesList) {
languages.put(language.getName(), language);
}
}
public static LanguageRegistry getInstance() {
return instance;
}
public static Collection<Language> getLanguages() {
return getInstance().languages.values();
}
public static Language getLanguage(String languageName) {
return getInstance().languages.get(languageName);
}
public static Language getDefaultLanguage() {
Language defaultLanguage = getLanguage("Java");
if (defaultLanguage == null) {
Collection<Language> allLanguages = getInstance().languages.values();
if (!allLanguages.isEmpty()) {
defaultLanguage = allLanguages.iterator().next();
}
}
return defaultLanguage;
}
public static Language findLanguageByTerseName(String terseName) {
for (Language language : getInstance().languages.values()) {
if (language.getTerseName().equals(terseName)) {
return language;
}
}
return null;
}
public static LanguageVersion findLanguageVersionByTerseName(String terseNameAndVersion) {
String version;
String terseName;
if (terseNameAndVersion.contains(" ")) {
version = terseNameAndVersion.substring(terseNameAndVersion.lastIndexOf(' ') + 1);
terseName = terseNameAndVersion.substring(0, terseNameAndVersion.lastIndexOf(' '));
} else {
version = null;
terseName = terseNameAndVersion;
}
Language language = findLanguageByTerseName(terseName);
if (language != null) {
if (version == null) {
return language.getDefaultVersion();
} else {
return language.getVersion(version);
}
}
return null;
}
public static List<Language> findByExtension(String extension) {
List<Language> languages = new ArrayList<>();
for (Language language : getInstance().languages.values()) {
if (language.hasExtension(extension)) {
languages.add(language);
}
}
return languages;
}
public static List<LanguageVersion> findAllVersions() {
List<LanguageVersion> versions = new ArrayList<>();
for (Language language : getLanguages()) {
for (LanguageVersion languageVersion : language.getVersions()) {
versions.add(languageVersion);
}
}
return versions;
}
/**
* A utility method to find the Languages which have Rule support.
*
* @return A List of Languages with Rule support.
*/
public static List<Language> findWithRuleSupport() {
List<Language> languages = new ArrayList<>();
for (Language language : getInstance().languages.values()) {
if (language.getRuleChainVisitorClass() != null) {
languages.add(language);
}
}
return languages;
}
public static String commaSeparatedTerseNamesForLanguage(List<Language> languages) {
StringBuilder builder = new StringBuilder();
for (Language language : languages) {
if (builder.length() > 0) {
builder.append(", ");
}
builder.append(language.getTerseName());
}
return builder.toString();
}
public static String commaSeparatedTerseNamesForLanguageVersion(List<LanguageVersion> languageVersions) {
if (languageVersions == null || languageVersions.isEmpty()) {
return "";
}
StringBuilder builder = new StringBuilder();
builder.append(languageVersions.get(0).getTerseName());
for (int i = 1; i < languageVersions.size(); i++) {
builder.append(", ").append(languageVersions.get(i).getTerseName());
}
return builder.toString();
}
}