
com.chutneytesting.design.domain.scenario.compose.ComposableStep Maven / Gradle / Ivy
package com.chutneytesting.design.domain.scenario.compose;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.unmodifiableList;
import static java.util.Collections.unmodifiableMap;
import static java.util.Optional.empty;
import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.toMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
public class ComposableStep {
public final String id;
public final String name;
public final List steps;
public final Map defaultParameters; // default parameters defined when editing the component alone
public final Optional implementation;
public final Strategy strategy;
public final Map executionParameters; // override default parameters values when the component is used inside another component
public final List tags;
private ComposableStep(String id,
String name,
List steps,
Map defaultParameters,
Optional implementation,
Strategy strategy,
Map executionParameters,
List tags) {
this.id = id;
this.name = name;
this.steps = steps;
this.defaultParameters = defaultParameters;
this.implementation = implementation;
this.strategy = strategy;
this.executionParameters = executionParameters;
this.tags = tags;
}
public boolean hasCyclicDependencies() {
return checkCyclicDependency(this, new ArrayList<>());
}
private boolean checkCyclicDependency(ComposableStep composableStep, List parentsAcc) {
if (composableStep.steps.isEmpty()) {
return false;
}
parentsAcc.add(composableStep.id);
List childrenIds = composableStep.steps.stream()
.map(cs -> cs.id)
.collect(Collectors.toList());
if (!Collections.disjoint(childrenIds, parentsAcc)) {
return true;
}
return composableStep.steps.stream()
.anyMatch(cs -> checkCyclicDependency(cs, new ArrayList<>(parentsAcc)));
}
public Map getEmptyExecutionParameters() {
return executionParameters.entrySet().stream()
.filter(e -> StringUtils.isBlank(e.getValue()))
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> "", LinkedHashMap::new));
}
public Map getChildrenEmptyParam() {
return steps.stream()
.flatMap(s -> s.getEmptyExecutionParameters().entrySet().stream())
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> ""));
}
public ComposableStep usingExecutionParameters(Map executionParameters) {
return builder().from(this).withExecutionParameters(executionParameters).build();
}
@Override
public String toString() {
return "ComposableStep{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", steps=" + steps +
", defaultParameters=" + defaultParameters +
", implementation=" + implementation +
", strategy=" + strategy.toString() +
", executionParameters=" + executionParameters +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ComposableStep that = (ComposableStep) o;
return Objects.equals(id, that.id) &&
Objects.equals(name, that.name) &&
Objects.equals(steps, that.steps) &&
Objects.equals(defaultParameters, that.defaultParameters) &&
Objects.equals(implementation, that.implementation) &&
Objects.equals(strategy, that.strategy) &&
Objects.equals(executionParameters, that.executionParameters)
;
}
@Override
public int hashCode() {
return Objects.hash(id, name, steps, defaultParameters, implementation, strategy, executionParameters);
}
public static ComposableStepBuilder builder() {
return new ComposableStepBuilder();
}
public static class ComposableStepBuilder {
private String id;
private String name;
private List steps;
private Map defaultParameters;
private Optional implementation = empty();
private Strategy strategy;
private List tags = new ArrayList<>();
private Map overrideExecutionParameters;
private ComposableStepBuilder() {}
public ComposableStep build() {
defaultParameters = unmodifiableMap(ofNullable(defaultParameters).orElse(emptyMap()));
steps = unmodifiableList(ofNullable(steps).orElse(emptyList()));
ComposableStep composableStep = new ComposableStep(
ofNullable(id).orElse(""),
ofNullable(name).orElse(""),
steps,
defaultParameters,
implementation,
ofNullable(strategy).orElse(Strategy.DEFAULT),
resolveExecutionParameters(),
unmodifiableList(ofNullable(tags).orElse(emptyList()))
);
if (composableStep.hasCyclicDependencies()) {
throw new ComposableStepCyclicDependencyException(composableStep.id, composableStep.name);
}
return composableStep;
}
private Map resolveExecutionParameters() {
Map emptyChildrenParameters = steps.stream()
.flatMap(s -> s.getEmptyExecutionParameters().entrySet().stream())
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> "", LinkedHashMap::new));
Map executionParameters = new LinkedHashMap<>();
executionParameters.putAll(emptyChildrenParameters);
executionParameters.putAll(defaultParameters);
executionParameters.putAll(ofNullable(this.overrideExecutionParameters).orElse(emptyMap()));
return executionParameters;
}
public ComposableStepBuilder withId(String id) {
this.id = id;
return this;
}
public ComposableStepBuilder withName(String name) {
this.name = name;
return this;
}
public ComposableStepBuilder withSteps(List steps) {
this.steps = steps;
return this;
}
public ComposableStepBuilder withDefaultParameters(Map defaultParameters) {
this.defaultParameters = defaultParameters;
return this;
}
public ComposableStepBuilder withExecutionParameters(Map executionParameters) {
this.overrideExecutionParameters = executionParameters;
return this;
}
public ComposableStepBuilder withImplementation(String implementation) {
this.implementation = ofNullable(implementation);
return this;
}
public ComposableStepBuilder withStrategy(Strategy strategy) {
this.strategy = strategy;
return this;
}
public ComposableStepBuilder withTags(List tags) {
this.tags = tags;
return this;
}
public final ComposableStepBuilder from(ComposableStep instance) {
this.id = instance.id;
this.name = instance.name;
this.steps = instance.steps;
this.defaultParameters = instance.defaultParameters;
this.implementation = instance.implementation;
this.strategy = instance.strategy;
return this;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy