[10899] | 1 | // License: GPL. For details, see LICENSE file.
|
---|
| 2 | package org.openstreetmap.josm.gui;
|
---|
| 3 |
|
---|
| 4 | import java.util.ArrayList;
|
---|
| 5 | import java.util.Collection;
|
---|
| 6 | import java.util.Collections;
|
---|
| 7 | import java.util.EnumMap;
|
---|
| 8 | import java.util.HashMap;
|
---|
| 9 | import java.util.List;
|
---|
| 10 | import java.util.Locale;
|
---|
| 11 | import java.util.Map;
|
---|
| 12 | import java.util.Optional;
|
---|
| 13 | import java.util.logging.Level;
|
---|
| 14 | import java.util.stream.Stream;
|
---|
| 15 |
|
---|
| 16 | import org.openstreetmap.josm.tools.Logging;
|
---|
| 17 |
|
---|
| 18 | import gnu.getopt.Getopt;
|
---|
| 19 | import gnu.getopt.LongOpt;
|
---|
| 20 |
|
---|
| 21 | /**
|
---|
[12633] | 22 | * This class holds the arguments passed on to {@link MainApplication#main}.
|
---|
[10899] | 23 | * @author Michael Zangl
|
---|
| 24 | * @since 10899
|
---|
| 25 | */
|
---|
| 26 | public class ProgramArguments {
|
---|
| 27 |
|
---|
| 28 | /**
|
---|
| 29 | * JOSM command line options.
|
---|
| 30 | * @see <a href="https://josm.openstreetmap.de/wiki/Help/CommandLineOptions">Help/CommandLineOptions</a>
|
---|
| 31 | */
|
---|
| 32 | public enum Option {
|
---|
| 33 | /** --help|-h Show this help */
|
---|
| 34 | HELP(false),
|
---|
| 35 | /** --version Displays the JOSM version and exits */
|
---|
| 36 | VERSION(false),
|
---|
| 37 | /** --debug Print debugging messages to console */
|
---|
| 38 | DEBUG(false),
|
---|
| 39 | /** --trace Print detailed debugging messages to console */
|
---|
| 40 | TRACE(false),
|
---|
| 41 | /** --language=<language> Set the language */
|
---|
| 42 | LANGUAGE(true),
|
---|
| 43 | /** --reset-preferences Reset the preferences to default */
|
---|
| 44 | RESET_PREFERENCES(false),
|
---|
| 45 | /** --load-preferences=<url-to-xml> Changes preferences according to the XML file */
|
---|
| 46 | LOAD_PREFERENCES(true),
|
---|
| 47 | /** --set=<key>=<value> Set preference key to value */
|
---|
| 48 | SET(true),
|
---|
| 49 | /** --geometry=widthxheight(+|-)x(+|-)y Standard unix geometry argument */
|
---|
| 50 | GEOMETRY(true),
|
---|
| 51 | /** --no-maximize Do not launch in maximized mode */
|
---|
| 52 | NO_MAXIMIZE(false),
|
---|
| 53 | /** --maximize Launch in maximized mode */
|
---|
| 54 | MAXIMIZE(false),
|
---|
| 55 | /** --download=minlat,minlon,maxlat,maxlon Download the bounding box <br>
|
---|
| 56 | * --download=<URL> Download the location at the URL (with lat=x&lon=y&zoom=z) <br>
|
---|
| 57 | * --download=<filename> Open a file (any file type that can be opened with File/Open) */
|
---|
| 58 | DOWNLOAD(true),
|
---|
| 59 | /** --downloadgps=minlat,minlon,maxlat,maxlon Download the bounding box as raw GPS <br>
|
---|
| 60 | * --downloadgps=<URL> Download the location at the URL (with lat=x&lon=y&zoom=z) as raw GPS */
|
---|
| 61 | DOWNLOADGPS(true),
|
---|
| 62 | /** --selection=<searchstring> Select with the given search */
|
---|
| 63 | SELECTION(true),
|
---|
| 64 | /** --offline=<osm_api|josm_website|all> Disable access to the given resource(s), delimited by comma */
|
---|
| 65 | OFFLINE(true),
|
---|
| 66 | /** --skip-plugins */
|
---|
| 67 | SKIP_PLUGINS(false);
|
---|
| 68 |
|
---|
| 69 | private final String name;
|
---|
| 70 | private final boolean requiresArg;
|
---|
| 71 |
|
---|
| 72 | Option(boolean requiresArgument) {
|
---|
| 73 | this.name = name().toLowerCase(Locale.ENGLISH).replace('_', '-');
|
---|
| 74 | this.requiresArg = requiresArgument;
|
---|
| 75 | }
|
---|
| 76 |
|
---|
| 77 | /**
|
---|
| 78 | * Replies the option name
|
---|
| 79 | * @return The option name, in lowercase
|
---|
| 80 | */
|
---|
| 81 | public String getName() {
|
---|
| 82 | return name;
|
---|
| 83 | }
|
---|
| 84 |
|
---|
| 85 | /**
|
---|
| 86 | * Determines if this option requires an argument.
|
---|
| 87 | * @return {@code true} if this option requires an argument, {@code false} otherwise
|
---|
| 88 | */
|
---|
| 89 | public boolean requiresArgument() {
|
---|
| 90 | return requiresArg;
|
---|
| 91 | }
|
---|
| 92 |
|
---|
| 93 | LongOpt toLongOpt() {
|
---|
| 94 | return new LongOpt(getName(), requiresArgument() ? LongOpt.REQUIRED_ARGUMENT : LongOpt.NO_ARGUMENT, null, 0);
|
---|
| 95 | }
|
---|
| 96 | }
|
---|
| 97 |
|
---|
| 98 | private final Map<Option, List<String>> argMap = new EnumMap<>(Option.class);
|
---|
| 99 |
|
---|
| 100 | /**
|
---|
| 101 | * Construct the program arguments object
|
---|
| 102 | * @param args The args passed to main.
|
---|
[10936] | 103 | * @since 10936
|
---|
[10899] | 104 | */
|
---|
[11747] | 105 | public ProgramArguments(String... args) {
|
---|
[10899] | 106 | Stream.of(Option.values()).forEach(o -> argMap.put(o, new ArrayList<>()));
|
---|
| 107 | buildCommandLineArgumentMap(args);
|
---|
| 108 | }
|
---|
| 109 |
|
---|
| 110 | /**
|
---|
| 111 | * Builds the command-line argument map.
|
---|
| 112 | * @param args command-line arguments array
|
---|
| 113 | */
|
---|
[11747] | 114 | private void buildCommandLineArgumentMap(String... args) {
|
---|
[12792] | 115 | LongOpt[] los = Stream.of(Option.values()).map(Option::toLongOpt).toArray(LongOpt[]::new);
|
---|
[10899] | 116 |
|
---|
| 117 | Getopt g = new Getopt("JOSM", args, "hv", los);
|
---|
| 118 |
|
---|
| 119 | int c;
|
---|
| 120 | while ((c = g.getopt()) != -1) {
|
---|
| 121 | Option opt;
|
---|
| 122 | switch (c) {
|
---|
| 123 | case 'h':
|
---|
| 124 | opt = Option.HELP;
|
---|
| 125 | break;
|
---|
| 126 | case 'v':
|
---|
| 127 | opt = Option.VERSION;
|
---|
| 128 | break;
|
---|
| 129 | case 0:
|
---|
| 130 | opt = Option.values()[g.getLongind()];
|
---|
| 131 | break;
|
---|
| 132 | default:
|
---|
| 133 | opt = null;
|
---|
| 134 | }
|
---|
| 135 | if (opt != null) {
|
---|
| 136 | addOption(opt, g.getOptarg());
|
---|
| 137 | } else
|
---|
[11986] | 138 | throw new IllegalArgumentException("Invalid option: "+ (char) c);
|
---|
[10899] | 139 | }
|
---|
| 140 | // positional arguments are a shortcut for the --download ... option
|
---|
| 141 | for (int i = g.getOptind(); i < args.length; ++i) {
|
---|
| 142 | addOption(Option.DOWNLOAD, args[i]);
|
---|
| 143 | }
|
---|
| 144 | }
|
---|
| 145 |
|
---|
| 146 | private void addOption(Option opt, String optarg) {
|
---|
| 147 | argMap.get(opt).add(optarg);
|
---|
| 148 | }
|
---|
| 149 |
|
---|
| 150 | /**
|
---|
| 151 | * Gets a single argument (the first) that was given for the given option.
|
---|
| 152 | * @param option The option to search
|
---|
| 153 | * @return The argument as optional value.
|
---|
| 154 | */
|
---|
| 155 | public Optional<String> getSingle(Option option) {
|
---|
| 156 | return get(option).stream().findFirst();
|
---|
| 157 | }
|
---|
| 158 |
|
---|
| 159 | /**
|
---|
| 160 | * Gets all values that are given for a given option
|
---|
| 161 | * @param option The option
|
---|
| 162 | * @return The values that were given. May be empty.
|
---|
| 163 | */
|
---|
| 164 | public Collection<String> get(Option option) {
|
---|
| 165 | return Collections.unmodifiableList(argMap.get(option));
|
---|
| 166 | }
|
---|
| 167 |
|
---|
| 168 | /**
|
---|
| 169 | * Test if a given option was used by the user.
|
---|
| 170 | * @param option The option to test for
|
---|
| 171 | * @return <code>true</code> if the user used it.
|
---|
| 172 | */
|
---|
| 173 | public boolean hasOption(Option option) {
|
---|
| 174 | return !get(option).isEmpty();
|
---|
| 175 | }
|
---|
| 176 |
|
---|
| 177 | /**
|
---|
| 178 | * Helper method to indicate if version should be displayed.
|
---|
| 179 | * @return <code>true</code> to display version
|
---|
| 180 | */
|
---|
| 181 | public boolean showVersion() {
|
---|
| 182 | return hasOption(Option.VERSION);
|
---|
| 183 | }
|
---|
| 184 |
|
---|
| 185 | /**
|
---|
| 186 | * Helper method to indicate if help should be displayed.
|
---|
| 187 | * @return <code>true</code> to display version
|
---|
| 188 | */
|
---|
| 189 | public boolean showHelp() {
|
---|
| 190 | return !get(Option.HELP).isEmpty();
|
---|
| 191 | }
|
---|
| 192 |
|
---|
| 193 | /**
|
---|
| 194 | * Get the log level the user wants us to use.
|
---|
| 195 | * @return The log level.
|
---|
| 196 | */
|
---|
| 197 | public Level getLogLevel() {
|
---|
| 198 | if (hasOption(Option.TRACE)) {
|
---|
| 199 | return Logging.LEVEL_TRACE;
|
---|
| 200 | } else if (hasOption(Option.DEBUG)) {
|
---|
| 201 | return Logging.LEVEL_DEBUG;
|
---|
| 202 | } else {
|
---|
| 203 | return Logging.LEVEL_INFO;
|
---|
| 204 | }
|
---|
| 205 | }
|
---|
| 206 |
|
---|
| 207 | /**
|
---|
| 208 | * Gets a map of all preferences the user wants to set.
|
---|
| 209 | * @return The preferences to set. It contains null values for preferences to unset
|
---|
| 210 | */
|
---|
| 211 | public Map<String, String> getPreferencesToSet() {
|
---|
| 212 | HashMap<String, String> map = new HashMap<>();
|
---|
| 213 | get(Option.SET).stream().map(i -> i.split("=", 2)).forEach(kv -> map.put(kv[0], getValue(kv)));
|
---|
| 214 | return map;
|
---|
| 215 | }
|
---|
| 216 |
|
---|
[11747] | 217 | private static String getValue(String... kv) {
|
---|
[10899] | 218 | if (kv.length < 2) {
|
---|
| 219 | return "";
|
---|
| 220 | } else if ("null".equals(kv[1])) {
|
---|
| 221 | return null;
|
---|
| 222 | } else {
|
---|
| 223 | return kv[1];
|
---|
| 224 | }
|
---|
| 225 | }
|
---|
| 226 | }
|
---|