JsonAliasParser.java
- package org.jbehave.core.parsers;
- import static java.util.stream.Collectors.collectingAndThen;
- import static java.util.stream.Collectors.groupingBy;
- import static java.util.stream.Collectors.toList;
- import static org.apache.commons.lang3.Validate.isTrue;
- import java.lang.reflect.Type;
- import java.util.Collection;
- import java.util.Collections;
- import java.util.List;
- import java.util.Objects;
- import java.util.Set;
- import java.util.stream.Collectors;
- import com.google.gson.Gson;
- import com.google.gson.reflect.TypeToken;
- import org.jbehave.core.configuration.Keywords;
- import org.jbehave.core.model.Alias;
- import org.jbehave.core.model.AliasVariant;
- import org.jbehave.core.steps.StepType;
- public class JsonAliasParser implements AliasParser {
- private final Keywords keywords;
- public JsonAliasParser(Keywords keywords) {
- this.keywords = keywords;
- }
- @SuppressWarnings("unchecked")
- @Override
- public Collection<Alias> parse(Set<String> aliasesAsStrings) {
- if (aliasesAsStrings.isEmpty()) {
- return Collections.emptyList();
- }
- Gson gson = new Gson();
- Type aliasType = new TypeToken<List<AliasContainer>>() {}.getType();
- return aliasesAsStrings.stream()
- .map(json -> (List<AliasContainer>) gson.fromJson(json, aliasType))
- .flatMap(List::stream)
- .map(JsonAliasParser::validate)
- .collect(groupingBy(AliasContainer::getName, collectingAndThen(toList(),
- JsonAliasParser::mergeAliases)))
- .values()
- .stream()
- .map(this::convert)
- .collect(toList());
- }
- // https://github.com/google/gson/issues/61
- private static AliasContainer validate(AliasContainer alias) {
- isTrue(alias.getName() != null, "The 'name' property that identifies step must be set");
- Set<AliasEntry> aliases = alias.getAliases();
- isTrue(aliases != null, "The 'aliases' property must be set");
- aliases.forEach(entry -> isTrue(entry.getName() != null, "The 'name' property of alias must be set"));
- return alias;
- }
- private static AliasContainer mergeAliases(List<AliasContainer> aliases) {
- if (aliases.size() == 1) {
- return aliases.get(0);
- }
- return aliases.stream().reduce((l, r) -> {
- l.getAliases().addAll(r.getAliases());
- return l;
- }).get();
- }
- private Alias convert(AliasContainer container) {
- String name = container.getName();
- StepType stepType = keywords.stepTypeFor(name);
- List<AliasVariant> variants = container.getAliases().stream().map(alias -> {
- String aliasName = alias.getName();
- StepType aliasType = keywords.stepTypeFor(alias.getName());
- if (aliasType != stepType) {
- throw new InvalidAliasType(aliasName, stepType);
- }
- return keywords.stepWithoutStartingWord(aliasName, aliasType);
- }).map(AliasVariant::new).collect(Collectors.toList());
- return new Alias(keywords.stepWithoutStartingWord(name, stepType), stepType, variants);
- }
- @SuppressWarnings("unused")
- private static final class AliasContainer {
- private String name;
- private Set<AliasEntry> aliases;
- private String getName() {
- return name;
- }
- private void setName(String name) {
- this.name = name;
- }
- private Set<AliasEntry> getAliases() {
- return aliases;
- }
- private void setAliases(Set<AliasEntry> aliases) {
- this.aliases = aliases;
- }
- }
- @SuppressWarnings("unused")
- private static final class AliasEntry {
- private String name;
- private String getName() {
- return name;
- }
- private void setName(String name) {
- this.name = name;
- }
- @Override
- public int hashCode() {
- return Objects.hash(name);
- }
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof AliasEntry)) {
- return false;
- }
- AliasEntry other = (AliasEntry) obj;
- return Objects.equals(name, other.name);
- }
- }
- @SuppressWarnings("serial")
- public static class InvalidAliasType extends RuntimeException {
- public InvalidAliasType(String alias, StepType stepType) {
- super(String.format("The alias '%s' must be of type '%s'", alias, stepType));
- }
- }
- }