summaryrefslogtreecommitdiff
path: root/src/cz/crcs/ectester/common/cli/TreeParser.java
blob: 23f59b16a441c21782cc742a3e775a41194fb65e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package cz.crcs.ectester.common.cli;

import org.apache.commons.cli.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Jan Jancar johny@neuromancer.sk
 */
public class TreeParser implements CommandLineParser {
    private Map<String, ParserOptions> parsers;
    private boolean required;
    private List<Argument> args = Collections.emptyList();

    public TreeParser(Map<String, ParserOptions> parsers, boolean required) {
        this.parsers = parsers;
        this.required = required;
    }

    public TreeParser(Map<String, ParserOptions> parsers, boolean required, List<Argument> args) {
        this(parsers, required);
        this.args = args;
    }

    public Map<String, ParserOptions> getParsers() {
        return Collections.unmodifiableMap(parsers);
    }

    public boolean isRequired() {
        return required;
    }

    public List<Argument> getArgs() {
        return Collections.unmodifiableList(args);
    }

    @Override
    public TreeCommandLine parse(Options options, String[] arguments) throws ParseException {
        return this.parse(options, arguments, null);
    }

    public TreeCommandLine parse(Options options, String[] arguments, Properties properties) throws ParseException {
        return this.parse(options, arguments, properties, false);
    }

    @Override
    public TreeCommandLine parse(Options options, String[] arguments, boolean stopAtNonOption) throws ParseException {
        return this.parse(options, arguments, null, stopAtNonOption);
    }

    public TreeCommandLine parse(Options options, String[] arguments, Properties properties, boolean stopAtNonOption) throws ParseException {
        DefaultParser thisParser = new DefaultParser();
        CommandLine cli = thisParser.parse(options, arguments, properties, true);

        CommandLine subCli = null;
        String[] cliArgs = cli.getArgs();
        String sub = null;
        if (cliArgs.length != 0) {
            sub = cliArgs[0];

            List<String> matches = new LinkedList<>();
            String finalSub = sub;
            for (Map.Entry<String, ParserOptions> entry : parsers.entrySet()) {
                if (entry.getKey().equalsIgnoreCase(finalSub)) {
                    matches.clear();
                    matches.add(finalSub);
                    break;
                } else if (entry.getKey().startsWith(finalSub)) {
                    matches.add(entry.getKey());
                }
            }

            if (matches.size() == 1) {
                sub = matches.get(0);
                ParserOptions subparser = parsers.get(sub);
                String[] remainingArgs = new String[cliArgs.length - 1];
                System.arraycopy(cliArgs, 1, remainingArgs, 0, cliArgs.length - 1);
                subCli = subparser.getParser().parse(subparser.getOptions(), remainingArgs, true);
            } else if (matches.size() > 1) {
                throw new AmbiguousOptionException(sub, matches);
            }
        } else {
            if (required) {
                throw new MissingOptionException(new ArrayList<>(parsers.keySet()));
            }
        }

        int maxArgs = args.size();
        long requiredArgs = args.stream().filter(Argument::isRequired).count();
        String reqArgs = String.join(" ", args.stream().filter(Argument::isRequired).map(Argument::getName).collect(Collectors.toList()));

        if (subCli instanceof TreeCommandLine) {
            TreeCommandLine subTreeCli = (TreeCommandLine) subCli;

            TreeCommandLine lastCli = subTreeCli;
            while (lastCli.getNext() != null) {
                lastCli = lastCli.getNext();
            }

            if (lastCli.getArgs().length < requiredArgs) {
                throw new MissingArgumentException("Not enough arguments: " + reqArgs);
            } else if (lastCli.getArgs().length > maxArgs) {
                throw new MissingArgumentException("Too many arguments.");
            }

            subTreeCli.setName(sub);
            return new TreeCommandLine(cli, subTreeCli);
        } else if (subCli != null) {
            if (subCli.getArgs().length < requiredArgs) {
                throw new MissingArgumentException("Not enough arguments: " + reqArgs);
            } else if (subCli.getArgs().length > maxArgs) {
                throw new MissingArgumentException("Too many arguments.");
            }

            TreeCommandLine subTreeCli = new TreeCommandLine(sub, subCli, null);
            return new TreeCommandLine(cli, subTreeCli);
        } else {
            if (cliArgs.length < requiredArgs) {
                throw new MissingArgumentException("Not enough arguments: " + reqArgs);
            } else if (cliArgs.length > maxArgs) {
                throw new MissingArgumentException("Too many arguments.");
            }

            return new TreeCommandLine(cli, null);
        }
    }
}