Test Failed
Pull Request — master (#172)
by Vincent
09:48
created

help(Command,A,HelpFormatter)   C

Complexity

Conditions 9

Size

Total Lines 40
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 21
dl 0
loc 40
rs 6.6666
c 0
b 0
f 0
1
/*
2
 * This file is part of Araknemu.
3
 *
4
 * Araknemu is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU Lesser General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * Araknemu is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public License
15
 * along with Araknemu.  If not, see <https://www.gnu.org/licenses/>.
16
 *
17
 * Copyright (c) 2017-2021 Vincent Quatrevieux
18
 */
19
20
package fr.quatrevieux.araknemu.game.admin.executor.argument;
21
22
import fr.quatrevieux.araknemu.game.admin.Command;
23
import fr.quatrevieux.araknemu.game.admin.CommandParser;
24
import fr.quatrevieux.araknemu.game.admin.executor.argument.handler.DurationOptionHandler;
25
import fr.quatrevieux.araknemu.game.admin.executor.argument.handler.IpAddressStringHandler;
26
import fr.quatrevieux.araknemu.game.admin.executor.argument.handler.LocalTimeHandler;
27
import fr.quatrevieux.araknemu.game.admin.executor.argument.type.SubArguments;
28
import fr.quatrevieux.araknemu.game.admin.formatter.HelpFormatter;
29
import inet.ipaddr.IPAddressString;
30
import org.kohsuke.args4j.CmdLineParser;
31
import org.kohsuke.args4j.OptionHandlerRegistry;
32
import org.kohsuke.args4j.ParserProperties;
33
import org.kohsuke.args4j.spi.OptionHandler;
34
import org.kohsuke.args4j.spi.SubCommandHandler;
35
36
import java.io.ByteArrayOutputStream;
37
import java.time.Duration;
38
import java.time.LocalTime;
39
import java.util.HashMap;
40
import java.util.Map;
41
42
/**
43
 * Hydrator using {@link org.kohsuke.args4j.CmdLineParser} parser for fill arguments
44
 * This is the default hydrator
45
 */
46
public final class AnnotationHydrator implements ArgumentsHydrator {
47
    private final ParserProperties parserProperties = ParserProperties.defaults().withAtSyntax(false);
48
49
    public AnnotationHydrator() {
50
        OptionHandlerRegistry.getRegistry().registerHandler(Duration.class, DurationOptionHandler::new);
51
        OptionHandlerRegistry.getRegistry().registerHandler(IPAddressString.class, IpAddressStringHandler::new);
52
        OptionHandlerRegistry.getRegistry().registerHandler(LocalTime.class, LocalTimeHandler::new);
53
        OptionHandlerRegistry.getRegistry().registerHandler(SubArguments.class, SubCommandHandler::new);
54
    }
55
56
    @Override
57
    public <A> A hydrate(Command<A> command, A commandArguments, CommandParser.Arguments parsedArguments) throws Exception {
58
        final CmdLineParser parser = new CmdLineParser(commandArguments, parserProperties);
59
60
        // @todo handle custom properties
0 ignored issues
show
introduced by
Comment matches to-do format '(TODO:)|(@todo )'.
Loading history...
61
        parser.parseArgument(parsedArguments.arguments().subList(1, parsedArguments.arguments().size()));
62
63
        return commandArguments;
64
    }
65
66
    @Override
67
    public <A> HelpFormatter help(Command<A> command, A commandArguments, HelpFormatter help) {
68
        final CmdLineParser parser = new CmdLineParser(commandArguments, parserProperties);
69
        final Map<String, String> defaultOptionValues = new HashMap<>();
70
71
        for (OptionHandler argument : parser.getArguments()) {
72
            final String argumentName = argument.getNameAndMeta(null);
73
74
            if (!argument.option.usage().isEmpty()) {
75
                help.defaultOption(argumentName, argument.option.usage());
76
            }
77
78
            if (!argument.option.required()) {
79
                final String defaultValue = argument.printDefaultValue();
80
81
                if (!isEmptyDefault(defaultValue)) {
82
                    defaultOptionValues.put(argumentName, defaultValue);
83
                }
84
            }
85
        }
86
87
        for (OptionHandler option : parser.getOptions()) {
88
            if (!option.option.usage().isEmpty()) {
89
                help.defaultOption(option.option.toString(), option.option.usage());
90
            }
91
92
            if (!option.option.required()) {
93
                final String defaultValue = option.printDefaultValue();
94
95
                if (!isEmptyDefault(defaultValue)) {
96
                    defaultOptionValues.put(option.option.toString(), defaultValue);
97
                }
98
            }
99
        }
100
101
        help.defaultSynopsis(generateSynopsis(command, parser, defaultOptionValues));
102
103
        // @todo handle default value on synopsis ?
0 ignored issues
show
introduced by
Comment matches to-do format '(TODO:)|(@todo )'.
Loading history...
104
105
        return help;
106
    }
107
108
    @Override
109
    public <A> boolean supports(Command<A> command, A commandArguments) {
110
        return commandArguments != null;
111
    }
112
113
    private String generateSynopsis(Command command, CmdLineParser parser, Map<String, String> defaultsMap) {
114
        final ByteArrayOutputStream os = new ByteArrayOutputStream();
115
        parser.printSingleLineUsage(os);
116
117
        // @todo check
0 ignored issues
show
introduced by
Comment matches to-do format '(TODO:)|(@todo )'.
Loading history...
118
        String synopsis = command.name() + os;
119
120
        for (Map.Entry<String, String> mapping : defaultsMap.entrySet()) {
121
            synopsis = synopsis.replaceFirst("\\[(" + mapping.getKey() + ".*?)\\]", "[$1=" + mapping.getValue() + "]");
122
        }
123
124
        return synopsis;
125
    }
126
127
    private boolean isEmptyDefault(String defaultValue) {
128
        return defaultValue == null || defaultValue.isEmpty()
129
            || "false".equals(defaultValue) || "0".equals(defaultValue)
130
        ;
131
    }
132
}
133