com.github.dakusui.jcunit8.factorspace.Parameter Maven / Gradle / Ivy
package com.github.dakusui.jcunit8.factorspace;
import com.github.dakusui.jcunit.core.tuples.Tuple;
import com.github.dakusui.jcunit.exceptions.InvalidTestException;
import com.github.dakusui.jcunit.fsm.FiniteStateMachine;
import com.github.dakusui.jcunit.fsm.spec.FsmSpec;
import com.github.dakusui.jcunit.regex.Expr;
import com.github.dakusui.jcunit.regex.Parser;
import com.github.dakusui.jcunit.regex.RegexComposer;
import com.github.dakusui.jcunit8.core.Utils;
import com.github.dakusui.jcunit8.factorspace.fsm.FsmComposer;
import com.github.dakusui.jcunit8.factorspace.fsm.FsmDecomposer;
import com.github.dakusui.jcunit8.factorspace.fsm.Scenario;
import com.github.dakusui.jcunit8.factorspace.regex.RegexDecomposer;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
import static com.github.dakusui.jcunit8.exceptions.TestDefinitionException.checkValue;
import static java.util.Collections.*;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toList;
/**
* A user level factor.
*
* @param Type of values held by this class.
*/
public interface Parameter {
String getName();
FactorSpace toFactorSpace();
T composeValue(Tuple tuple);
Optional decomposeValue(T value);
List getKnownValues();
abstract class Base implements Parameter {
protected final String name;
private final List knownValues;
protected Base(String name, List knownValues) {
this.name = requireNonNull(name);
this.knownValues = unmodifiableList(requireNonNull(knownValues));
}
@Override
public String getName() {
return this.name;
}
@Override
public FactorSpace toFactorSpace() {
return FactorSpace.create(decompose(), generateConstraints());
}
@Override
public List getKnownValues() {
return this.knownValues;
}
protected abstract List decompose();
protected abstract List generateConstraints();
static Optional _decomposeValue(V value, Stream tuples, Function valueComposer, Predicate constraints) {
AtomicReference> fallback = new AtomicReference<>(Optional.empty());
return tuples.filter(
(Tuple tuple) -> {
return value.equals(valueComposer.apply(tuple));
}
).filter(
constraints
).findFirst(
);
}
}
interface Factory {
> F addActualValue(T actualValue);
> F addActualValues(List actualValues);
Parameter create(String name);
abstract class Base implements Factory {
protected final List knownValues = new LinkedList<>();
@SuppressWarnings("unchecked")
@Override
public > F addActualValue(T actualValue) {
knownValues.add(actualValue);
return (F) this;
}
@SuppressWarnings("unchecked")
@Override
public > F addActualValues(List actualValues) {
actualValues.forEach(this::addActualValue);
return (F) this;
}
}
}
interface Simple extends Parameter {
class Impl extends Base implements Simple {
final Factor factor;
public Impl(String name, List allLevels) {
super(name, allLevels);
this.factor = Factor.create(name, allLevels.toArray());
}
@Override
protected List decompose() {
return singletonList(factor);
}
@Override
protected List generateConstraints() {
return emptyList();
}
@SuppressWarnings("unchecked")
@Override
public T composeValue(Tuple tuple) {
return (T) tuple.get(getName());
}
@Override
public Optional decomposeValue(T value) {
return Optional.of(Tuple.builder().put(name, value).build());
}
@Override
public String toString() {
return String.format("Simple:%s:%s", factor.getName(), factor.getLevels());
}
}
class Factory extends Parameter.Factory.Base {
private Factory() {
}
public static Factory of(List actualValues) {
return new Factory().addActualValues(actualValues);
}
@Override
public Parameter create(String name) {
return new Impl<>(name, this.knownValues);
}
}
}
interface Regex extends Parameter> {
class Impl extends Parameter.Base> implements Regex {
private final FactorSpace factorSpace;
private final RegexComposer regexComposer;
private final Function func;
public Impl(String name, String regex, List> knownValues, Function func) {
super(name, knownValues);
Expr expr = new Parser().parse(regex);
RegexDecomposer translator = new RegexDecomposer(name, expr);
this.func = func;
this.regexComposer = new RegexComposer(name, expr);
this.factorSpace = translator.decompose();
}
public Optional decomposeValue(List value) {
return _decomposeValue(
value,
this.factorSpace.stream(),
this.regexComposer::compose,
Utils.conjunct(this.factorSpace.getConstraints())
);
}
@Override
public List composeValue(Tuple tuple) {
return composeStringValueFrom(tuple).stream().map(func).collect(toList());
}
@Override
protected List decompose() {
return factorSpace.getFactors();
}
@Override
protected List generateConstraints() {
return factorSpace.getConstraints();
}
private List composeStringValueFrom(Tuple tuple) {
return regexComposer.compose(tuple);
}
}
class Factory extends Parameter.Factory.Base> {
private final String regex;
private final Function func;
@Override
public Regex create(String name) {
return create(name, regex, knownValues, func);
}
public static Factory of(String regex, Function func) {
return new Factory<>(regex, func);
}
public static Factory of(String regex) {
return new Factory<>(regex, s -> s);
}
private Factory(String regex, Function func) {
this.regex = requireNonNull(regex);
this.func = requireNonNull(func);
}
private static Regex create(String name, String regex, List> knownValues, Function func) {
return new Impl<>(name, regex, knownValues, func);
}
}
}
interface Fsm extends Parameter> {
class Impl extends Parameter.Base> implements Fsm {
private final FsmComposer composer;
private final FactorSpace factorSpace;
Impl(String name, FiniteStateMachine model, List> knownValues, int scenarioLength) {
super(name, knownValues);
FsmDecomposer decomposer = new FsmDecomposer<>(name, model, scenarioLength);
this.composer = new FsmComposer<>(name, model, scenarioLength);
this.factorSpace = FactorSpace.create(decomposer.getFactors(), decomposer.getConstraints());
}
@Override
public Optional decomposeValue(Scenario value) {
return _decomposeValue(
value,
this.factorSpace.stream(),
tuple -> {
try {
return this.composer.composeValueFrom(tuple);
} catch (InvalidTestException e) {
return false;
}
},
Utils.conjunct(this.factorSpace.getConstraints())
);
}
@Override
public Scenario composeValue(Tuple tuple) {
return composer.composeValueFrom(tuple);
}
@Override
protected List decompose() {
return factorSpace.getFactors();
}
@Override
protected List generateConstraints() {
return factorSpace.getConstraints();
}
}
class Factory extends Parameter.Factory.Base> {
private final Class extends FsmSpec> fsmSpecClass;
private int scenarioLength;
@Override
public Fsm create(String name) {
return new Impl<>(
name,
new FiniteStateMachine.Impl<>(name, this.fsmSpecClass),
knownValues,
scenarioLength
);
}
public Factory(Class extends FsmSpec> fsmSpecClass, int scenarioLength) {
this.fsmSpecClass = requireNonNull(fsmSpecClass);
this.scenarioLength = checkValue(scenarioLength, (Integer value) -> value > 0);
}
public static Factory of(Class extends FsmSpec> fsmSpecClass, int scenarioLength) {
return new Factory<>(fsmSpecClass, scenarioLength);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy