package gherkin;
import gherkin.deps.com.google.gson.Gson;
import gherkin.deps.com.google.gson.reflect.TypeToken;
import gherkin.formatter.PrettyFormatter;
import gherkin.formatter.model.Comment;
import gherkin.formatter.model.DataTableRow;
import gherkin.formatter.model.Row;
import gherkin.lexer.Lexer;
import gherkin.lexer.Listener;
import gherkin.util.Mapper;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import static gherkin.util.FixJava.join;
import static gherkin.util.FixJava.map;
public class I18n {
private static final List<String> FEATURE_ELEMENT_KEYWORD_KEYS = Arrays.asList("feature", "background", "scenario", "scenario_outline", "examples");
private static final List<String> STEP_KEYWORD_KEYS = Arrays.asList("given", "when", "then", "and", "but");
private static final List<String> KEYWORD_KEYS = new ArrayList<String>();
static {
KEYWORD_KEYS.addAll(FEATURE_ELEMENT_KEYWORD_KEYS);
KEYWORD_KEYS.addAll(STEP_KEYWORD_KEYS);
}
private static final Mapper<String, String> QUOTE_MAPPER = new Mapper<String, String>() {
@Override
public String map(String o) {
return '"' + o + '"';
}
};
private static final Mapper<String, String> CODE_KEYWORD_MAPPER = new Mapper<String, String>() {
@Override
public String map(String keyword) {
return codeKeywordFor(keyword);
}
};
private static Map<String, Map<String, String>> I18N;
static {
try {
I18N = new Gson().fromJson(new InputStreamReader(I18n.class.getResourceAsStream("/gherkin/i18n.json"), "UTF-8"), new TypeToken<Map<String, Map<String, String>>>() {
}.getType());
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
public static String codeKeywordFor(String keyword) {
return keyword.replaceAll("[\\s',!]", "");
}
public static List<I18n> getAll() {
List<I18n> result = new ArrayList<I18n>();
Set<String> isoCodes = new TreeSet<String>(I18N.keySet());
for (String isoCode : isoCodes) {
result.add(new I18n(isoCode));
}
return result;
}
private final String isoCode;
private final Locale locale;
private final Map<String, List<String>> keywords;
public I18n(String isoCode) {
this.isoCode = isoCode;
this.locale = localeFor(this.isoCode);
this.keywords = new HashMap<String, List<String>>();
Map<String, String> keywordMap = I18N.get(isoCode);
for (Map.Entry<String, String> entry : keywordMap.entrySet()) {
List<String> keywordList = Arrays.asList(entry.getValue().split("\\|"));
if (STEP_KEYWORD_KEYS.contains(entry.getKey())) {
List<String> stepKeywords = new ArrayList<String>();
for (String s : keywordList) {
stepKeywords.add((s + " ").replaceFirst("< $", ""));
}
keywordList = stepKeywords;
}
this.keywords.put(entry.getKey(), Collections.unmodifiableList(keywordList));
}
}
public String getIsoCode() {
return isoCode;
}
public Locale getLocale() {
return locale;
}
public String getUnderscoredIsoCode() {
return getIsoCode().replaceAll("[\\s-]", "_").toLowerCase();
}
public Lexer lexer(Listener listener) {
String qualifiedI18nLexerClassName = "gherkin.lexer." + capitalize(getUnderscoredIsoCode());
try {
Class<?> delegateClass = getClass().getClassLoader().loadClass(qualifiedI18nLexerClassName);
return (Lexer) delegateClass.getConstructor(Listener.class).newInstance(listener);
} catch (Exception e) {
throw new RuntimeException("Couldn't load lexer class: " + qualifiedI18nLexerClassName, e);
}
}
private String capitalize(String s) {
return s.substring(0, 1).toUpperCase() + s.substring(1);
}
public List<String> keywords(String key) {
if (!keywords.containsKey(key)) {
throw new RuntimeException("No such key: " + key + ". Available keys: " + keywords.keySet());
}
return keywords.get(key);
}
public List<String> getCodeKeywords() {
List<String> result = map(getStepKeywords(), CODE_KEYWORD_MAPPER);
result.remove("*");
ListIterator<String> it = result.listIterator();
while (it.hasNext()) {
if (it.next().matches("^\\d.*")) {
it.remove();
}
}
return result;
}
public List<String> getStepKeywords() {
SortedSet<String> result = new TreeSet<String>();
for (String keyword : STEP_KEYWORD_KEYS) {
result.addAll(keywords.get(keyword));
}
return new ArrayList<String>(result);
}
public String getKeywordTable() {
StringWriter writer = new StringWriter();
PrettyFormatter pf = new PrettyFormatter(writer, true, false);
List<Row> table = new ArrayList<Row>();
for (String key : KEYWORD_KEYS) {
List<String> cells = Arrays.asList(key, join(map(keywords(key), QUOTE_MAPPER), ", "));
table.add(new DataTableRow(Collections.<Comment>emptyList(), cells, -1));
}
for (String key : STEP_KEYWORD_KEYS) {
List<String> codeKeywordList = new ArrayList<String>(keywords.get(key));
codeKeywordList.remove("* ");
String codeKeywords = join(map(map(codeKeywordList, CODE_KEYWORD_MAPPER), QUOTE_MAPPER), ", ");
List<String> cells = Arrays.asList(key + " (code)", codeKeywords);
table.add(new DataTableRow(Collections.<Comment>emptyList(), cells, -1));
}
pf.table(table);
return writer.getBuffer().toString();
}
private Locale localeFor(String isoString) {
String[] languageAndCountry = isoString.split("-");
if (languageAndCountry.length == 1) {
return new Locale(isoString);
} else {
return new Locale(languageAndCountry[0], languageAndCountry[1]);
}
}
}