Убедитесь, что аргументы командной строки передаются в правильном порядке

Мне нужно проверить, передаются ли аргументы командной строки java в следующем порядке:

-shape  (optional - default polygon)
-color  (optional - default green)
-repeat (optional - default 5)
-name   (required)

и не используются неопределенные аргументы.

Если необязательный параметр не передан, используется значение по умолчанию.

Действительный:

java Game -shape triangle -color black -repeat 10 -name Tom
java Game -shape triangle -repeat 7 -name Jerry
java Game -repeat 11 -name Boby
java Game -name Pipy

Недействительный:

java Game -shape triangle -x sth -name Tom (invalid argument: -x)
java Game -shape triangle (-name is required)
java Game -color white -shape triangle (wrong order: -shape must be before -color)

Есть предложения по элегантному решению?


person one_2_three    schedule 15.08.2016    source источник
comment
@ Блобонат на чем? На String[]?   -  person fabian    schedule 15.08.2016
comment
@fabian Он может подключить массив args к одной строке.   -  person Blobonat    schedule 15.08.2016


Ответы (1)


Вы можете сохранить все параметры в списке и просто пробовать их один за другим в аргументах командной строки, пока не найдете подходящий:

public static class OptionParser<T> implements ParameterParser {

    private final String option;

    public OptionParser(String option, Function<String, ? extends T> parser) {
        if (parser == null) {
            throw new IllegalArgumentException();
        }
        this.option = "-" + option;
        this.parser = parser;
    }

    public OptionParser(String option, Function<String, ? extends T> parser, T defaultValue) {
        this(option, parser);
        this.value = defaultValue;
    }

    private final Function<String, ? extends T> parser;

    private T value;

    @Override
    public int parse(String[] args, int index) {
        if (args.length < index + 2 || !option.equals(args[index])) {
            return index;
        } else {
            value = parser.apply(args[index + 1]);
            return index + 2;
        }
    }

    public T getValue() {
        return value;
    }

}

public static interface ParameterParser {


    /**
     * Tries parsing the parameter and returns the new index after the
     * operation.
     *
     * @param args the parameter list
     * @param index the index of the first String to use.
     * @return the index of the next String after parsing the parameter or the index,
     * if the parameter wasn't parsable with this ParameterParser.
     */
    public int parse(String[] args, int index);
}

public static void main(String[] args) {
    OptionParser<String> shape = new OptionParser<>("shape", Function.identity(), "polygon");
    OptionParser<String> color = new OptionParser<>("color", Function.identity(), "green");
    OptionParser<Integer> repeat = new OptionParser<>("repeat", Integer::valueOf, 5);
    OptionParser<String> name = new OptionParser("name", Function.identity());

    List<ParameterParser> parameters = Arrays.asList(
            shape,
            color,
            repeat,
            name
    );

    Iterator<ParameterParser> iterator = parameters.iterator();

    for (int i = 0; i < args.length;) {
        if (!iterator.hasNext()) {
            throw new IllegalArgumentException("could not parse option at index " + i + ": " + args[i]);
        }
        i = iterator.next().parse(args, i);
    }

    if (name.getValue() == null) {
        throw new IllegalArgumentException("-name is required");
    }

    System.out.println("shape="+shape.getValue());
    System.out.println("color="+color.getValue());
    System.out.println("repeat="+repeat.getValue());
    System.out.println("name="+name.getValue());
person fabian    schedule 15.08.2016
comment
Очень хорошо. Спасибо! - person one_2_three; 15.08.2016