/*
* Copyright 2016 Nokia Solutions and Networks
* Licensed under the Apache License, Version 2.0,
* see license.txt file for details.
*/
package org.robotframework.ide.eclipse.main.plugin.assist;
import static com.google.common.collect.Iterables.transform;
import static org.robotframework.ide.eclipse.main.plugin.assist.AssistProposals.sortedByLabels;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import com.google.common.base.CaseFormat;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableTable;
import com.google.common.collect.ImmutableTable.Builder;
import com.google.common.collect.Table;
public class RedSettingProposals {
private static final Table<SettingTarget, String, String> DESCRIBED_SETTINGS;
static {
final Builder<SettingTarget, String, String> builder = ImmutableTable.<SettingTarget, String, String> builder();
builder.put(SettingTarget.TEST_CASE, "[tags]",
"These tags are set to this test case and they possibly override Default Tags");
builder.put(SettingTarget.TEST_CASE, "[documentation]",
"Documentation of current test case");
builder.put(SettingTarget.TEST_CASE, "[setup]",
"The keyword %s is executed before other keywords inside the definition");
builder.put(SettingTarget.TEST_CASE, "[template]",
"The keyword %s is used as a template");
builder.put(SettingTarget.TEST_CASE, "[timeout]",
"Specifies maximum time this test case is allowed to execute before being aborted.\n"
+ "This setting overrides Test Timeout setting set on suite level\n"
+ "Numerical values are intepreted as seconds but special syntax like '1min 15s' or '2 hours' can be used.");
builder.put(SettingTarget.TEST_CASE, "[teardown]",
"The keyword %s is executed after every other keyword inside the definition");
builder.put(SettingTarget.KEYWORD, "[tags]",
"These tags are set to this keyword and are not affected by Default Tags or Force Tags setting");
builder.put(SettingTarget.KEYWORD, "[documentation]",
"Documentation of current keyword");
builder.put(SettingTarget.KEYWORD, "[teardown]",
"The keyword %s is executed after every other keyword inside the definition");
builder.put(SettingTarget.KEYWORD, "[arguments]",
"Specifies arguments of current keyword");
builder.put(SettingTarget.KEYWORD, "[timeout]",
"Specifies maximum time this keyword is allowed to execute before being aborted.\n"
+ "This setting overrides Test Timeout setting set on suite level\n"
+ "Numerical values are intepreted as seconds but special syntax like '1min 15s' or '2 hours' can be used.");
builder.put(SettingTarget.KEYWORD, "[return]",
"Specify the return value for this keyword. Multiple values can be used.");
builder.put(SettingTarget.GENERAL, "library", "");
builder.put(SettingTarget.GENERAL, "resource", "");
builder.put(SettingTarget.GENERAL, "variables", "");
builder.put(SettingTarget.GENERAL, "documentation", "");
builder.put(SettingTarget.GENERAL, "metadata", "");
builder.put(SettingTarget.GENERAL, "suite setup", "");
builder.put(SettingTarget.GENERAL, "suite teardown", "");
builder.put(SettingTarget.GENERAL, "force tags", "");
builder.put(SettingTarget.GENERAL, "default tags", "");
builder.put(SettingTarget.GENERAL, "test setup", "");
builder.put(SettingTarget.GENERAL, "test teardown", "");
builder.put(SettingTarget.GENERAL, "test template", "");
builder.put(SettingTarget.GENERAL, "test timeout", "");
DESCRIBED_SETTINGS = builder.build();
}
public static boolean isSetting(final SettingTarget target, final String label) {
return label != null && DESCRIBED_SETTINGS.contains(target, label.toLowerCase());
}
public static String getSettingDescription(final SettingTarget target, final String settingName,
final String additionalArgument) {
final String arg = additionalArgument.isEmpty() ? "given in first argument" : additionalArgument;
return String.format(DESCRIBED_SETTINGS.get(target, settingName.toLowerCase()), arg);
}
private final SettingTarget target;
private final ProposalMatcher matcher;
public RedSettingProposals(final SettingTarget target) {
this(target, ProposalMatchers.prefixesMatcher());
}
public RedSettingProposals(final SettingTarget target, final ProposalMatcher matcher) {
this.target = target;
this.matcher = matcher;
}
public List<? extends AssistProposal> getSettingsProposals(final String userContent) {
return getSettingsProposals(userContent, sortedByLabels());
}
public List<? extends AssistProposal> getSettingsProposals(final String userContent,
final Comparator<? super RedSettingProposal> comparator) {
final List<RedSettingProposal> proposals = new ArrayList<>();
for (final String settingName : DESCRIBED_SETTINGS.row(target).keySet()) {
final Optional<ProposalMatch> match = matcher.matches(userContent, settingName);
if (match.isPresent()) {
final String name = toCanonicalName(settingName);
proposals.add(AssistProposals.createSettingProposal(name, target, match.get()));
}
}
proposals.sort(comparator);
return proposals;
}
private String toCanonicalName(final String settingName) {
switch (target) {
case GENERAL:
final Iterable<String> upperCased = transform(Splitter.on(' ').split(settingName),
new Function<String, String>() {
@Override
public String apply(final String elem) {
return CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, elem);
}
});
return Joiner.on(' ').join(upperCased);
case TEST_CASE:
case KEYWORD:
final char firstLetter = settingName.charAt(1);
return settingName.replaceAll("\\[" + firstLetter, "[" + Character.toUpperCase(firstLetter));
default:
throw new IllegalStateException("Unknown target value: " + target);
}
}
public enum SettingTarget {
TEST_CASE,
KEYWORD,
GENERAL
}
}