Skip to content
Snippets Groups Projects
Commit 5e18f994 authored by dgelessus's avatar dgelessus
Browse files

Move parameter splitting and validation code into separate objects

This allows freely combining splitting, repeating and validation
behaviors without having to define a new PositionalParameter subclass
for each one.
parent 256b244c
No related branches found
No related tags found
No related merge requests found
...@@ -108,7 +108,7 @@ public final class CommandUtils { ...@@ -108,7 +108,7 @@ public final class CommandUtils {
break; break;
} }
final Parameter.SplitResult splitSingleArg = param.split(remainingArgs); final Parameter.SplitResult splitSingleArg = param.getSplitter().split(remainingArgs);
splitArgs.add(param, splitSingleArg.getSplitArg()); splitArgs.add(param, splitSingleArg.getSplitArg());
remainingArgs = splitSingleArg.getRemainingArgString(); remainingArgs = splitSingleArg.getRemainingArgString();
...@@ -121,7 +121,7 @@ public final class CommandUtils { ...@@ -121,7 +121,7 @@ public final class CommandUtils {
} }
private static <T> void validateSplitParameter(final @NotNull ParsedArguments parsed, final @NotNull SplitArguments splitArgs, final @NotNull Parameter<T> param) { private static <T> void validateSplitParameter(final @NotNull ParsedArguments parsed, final @NotNull SplitArguments splitArgs, final @NotNull Parameter<T> param) {
parsed.put(param, param.validate(splitArgs.get(param))); parsed.put(param, param.getValidator().validate(param, splitArgs.get(param)));
} }
public static @NotNull ParsedArguments validateSplitArgs(final @NotNull Parameters parameters, final SplitResult split) { public static @NotNull ParsedArguments validateSplitArgs(final @NotNull Parameters parameters, final SplitResult split) {
......
package de.prob2.jupyter; package de.prob2.jupyter;
import java.util.List; import java.util.List;
import java.util.Optional;
import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects;
...@@ -27,28 +28,82 @@ public abstract class Parameter<T> { ...@@ -27,28 +28,82 @@ public abstract class Parameter<T> {
} }
} }
public interface Splitter {
public static final @NotNull Parameter.Splitter REGULAR = argString -> {
final String[] split = CommandUtils.ARG_SPLIT_PATTERN.split(argString, 2);
return new SplitResult(split[0], split.length > 1 ? split[1] : "");
};
public static final @NotNull Parameter.Splitter REMAINDER = argString -> new SplitResult(argString, "");
public abstract Parameter.SplitResult split(final @NotNull String argString);
}
public interface Validator<T> {
public static final @NotNull Parameter.Validator<@NotNull String> EXACTLY_ONE = (param, argValues) -> {
if (argValues.isEmpty()) {
throw new UserErrorException("Missing required parameter " + param.getIdentifier());
} else if (argValues.size() > 1) {
throw new UserErrorException("Non-repeating parameter " + param.getIdentifier() + " cannot appear more than once");
}
return argValues.get(0);
};
public static final @NotNull Parameter.Validator<@NotNull Optional<String>> ZERO_OR_ONE = (param, argValues) -> {
if (argValues.size() > 1) {
throw new UserErrorException("Non-repeating parameter " + param.getIdentifier() + " cannot appear more than once");
}
return argValues.stream().findAny();
};
public static final @NotNull Parameter.Validator<@NotNull List<@NotNull String>> ONE_OR_MORE = (param, argValues) -> {
if (argValues.isEmpty()) {
throw new UserErrorException("Missing required parameter " + param.getIdentifier());
}
return argValues;
};
public static final @NotNull Parameter.Validator<@NotNull List<@NotNull String>> ZERO_OR_MORE = (param, argValues) -> argValues;
public abstract T validate(final @NotNull Parameter<T> param, final @NotNull List<@NotNull String> argValues);
}
private final @NotNull String identifier; private final @NotNull String identifier;
private final boolean repeating;
private final @NotNull Parameter.Splitter splitter;
private final @NotNull Parameter.Validator<T> validator;
protected Parameter(final @NotNull String identifier) { protected Parameter(final @NotNull String identifier, final boolean repeating, final @NotNull Parameter.Splitter splitter, final @NotNull Parameter.Validator<T> validator) {
super(); super();
this.identifier = identifier; this.identifier = identifier;
this.repeating = repeating;
this.splitter = splitter;
this.validator = validator;
} }
public @NotNull String getIdentifier() { public @NotNull String getIdentifier() {
return this.identifier; return this.identifier;
} }
public abstract boolean isRepeating(); public boolean isRepeating() {
return this.repeating;
}
public abstract Parameter.SplitResult split(final @NotNull String argString); public @NotNull Parameter.Splitter getSplitter() {
return this.splitter;
}
public abstract T validate(final @NotNull List<@NotNull String> argValues); public @NotNull Parameter.Validator<T> getValidator() {
return this.validator;
}
@Override @Override
public String toString() { public String toString() {
return MoreObjects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.add("identifier", this.getIdentifier()) .add("identifier", this.getIdentifier())
.add("repeating", this.isRepeating())
.add("splitter", this.getSplitter())
.add("validator", this.getValidator())
.toString(); .toString();
} }
} }
...@@ -5,146 +5,44 @@ import java.util.Optional; ...@@ -5,146 +5,44 @@ import java.util.Optional;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public abstract class PositionalParameter<T> extends Parameter<T> { public class PositionalParameter<T> extends Parameter<T> {
public abstract static class ExactlyOne extends PositionalParameter<@NotNull String> { public static final class RequiredSingle extends PositionalParameter<@NotNull String> {
protected ExactlyOne(final @NotNull String identifier) {
super(identifier);
}
@Override
public boolean isRepeating() {
return false;
}
@Override
public @NotNull String validate(final @NotNull List<@NotNull String> argValues) {
if (argValues.isEmpty()) {
throw new UserErrorException("Missing required parameter " + this.getIdentifier());
} else if (argValues.size() > 1) {
throw new AssertionError("Regular (single) required parameter " + this.getIdentifier() + " has more than one value, this should never happen!");
}
return argValues.get(0);
}
}
public abstract static class ZeroOrOne extends PositionalParameter<@NotNull Optional<String>> {
protected ZeroOrOne(final @NotNull String identifier) {
super(identifier);
}
@Override
public boolean isRepeating() {
return false;
}
@Override
public @NotNull Optional<String> validate(final @NotNull List<@NotNull String> argValues) {
if (argValues.size() > 1) {
throw new AssertionError("Regular (single) optional parameter " + this.getIdentifier() + " has more than one value, this should never happen!");
}
return argValues.stream().findAny();
}
}
public static final class RequiredSingle extends PositionalParameter.ExactlyOne {
public RequiredSingle(final @NotNull String identifier) { public RequiredSingle(final @NotNull String identifier) {
super(identifier); super(identifier, false, Parameter.Splitter.REGULAR, Parameter.Validator.EXACTLY_ONE);
}
@Override
public @NotNull Parameter.SplitResult split(final @NotNull String argString) {
return splitOnce(argString);
} }
} }
public static final class OptionalSingle extends PositionalParameter.ZeroOrOne { public static final class OptionalSingle extends PositionalParameter<@NotNull Optional<String>> {
public OptionalSingle(final @NotNull String identifier) { public OptionalSingle(final @NotNull String identifier) {
super(identifier); super(identifier, false, Parameter.Splitter.REGULAR, Parameter.Validator.ZERO_OR_ONE);
}
@Override
public @NotNull Parameter.SplitResult split(final @NotNull String argString) {
return splitOnce(argString);
} }
} }
public static final class RequiredMultiple extends PositionalParameter<@NotNull List<@NotNull String>> { public static final class RequiredMultiple extends PositionalParameter<@NotNull List<@NotNull String>> {
public RequiredMultiple(final @NotNull String identifier) { public RequiredMultiple(final @NotNull String identifier) {
super(identifier); super(identifier, true, Parameter.Splitter.REGULAR, Parameter.Validator.ONE_OR_MORE);
}
@Override
public boolean isRepeating() {
return true;
}
@Override
public @NotNull Parameter.SplitResult split(final @NotNull String argString) {
return splitOnce(argString);
}
@Override
public @NotNull List<@NotNull String> validate(final @NotNull List<@NotNull String> argValues) {
if (argValues.isEmpty()) {
throw new UserErrorException("Missing required parameter " + this.getIdentifier());
}
return argValues;
} }
} }
public static final class OptionalMultiple extends PositionalParameter<@NotNull List<@NotNull String>> { public static final class OptionalMultiple extends PositionalParameter<@NotNull List<@NotNull String>> {
public OptionalMultiple(final @NotNull String identifier) { public OptionalMultiple(final @NotNull String identifier) {
super(identifier); super(identifier, true, Parameter.Splitter.REGULAR, Parameter.Validator.ZERO_OR_MORE);
} }
@Override
public boolean isRepeating() {
return true;
} }
@Override public static final class RequiredRemainder extends PositionalParameter<@NotNull String> {
public @NotNull Parameter.SplitResult split(final @NotNull String argString) {
return splitOnce(argString);
}
@Override
public @NotNull List<@NotNull String> validate(final @NotNull List<@NotNull String> argValues) {
return argValues;
}
}
public static final class RequiredRemainder extends PositionalParameter.ExactlyOne {
public RequiredRemainder(final @NotNull String identifier) { public RequiredRemainder(final @NotNull String identifier) {
super(identifier); super(identifier, false, Parameter.Splitter.REMAINDER, Parameter.Validator.EXACTLY_ONE);
}
@Override
public @NotNull Parameter.SplitResult split(final @NotNull String argString) {
return new Parameter.SplitResult(argString, "");
} }
} }
public static final class OptionalRemainder extends PositionalParameter.ZeroOrOne { public static final class OptionalRemainder extends PositionalParameter<@NotNull Optional<String>> {
public OptionalRemainder(final @NotNull String identifier) { public OptionalRemainder(final @NotNull String identifier) {
super(identifier); super(identifier, false, Parameter.Splitter.REMAINDER, Parameter.Validator.ZERO_OR_ONE);
}
@Override
public @NotNull Parameter.SplitResult split(final @NotNull String argString) {
return new Parameter.SplitResult(argString, "");
} }
} }
protected PositionalParameter(final @NotNull String identifier) { public PositionalParameter(final @NotNull String identifier, final boolean repeating, final @NotNull Parameter.Splitter splitter, final @NotNull Parameter.Validator<T> validator) {
super(identifier); super(identifier, repeating, splitter, validator);
}
@NotNull
static Parameter.SplitResult splitOnce(final @NotNull String argString) {
final String[] split = CommandUtils.ARG_SPLIT_PATTERN.split(argString, 2);
return new Parameter.SplitResult(split[0], split.length > 1 ? split[1] : "");
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment