// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.gui; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.EnumMap; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Optional; import java.util.logging.Level; import java.util.stream.Stream; import org.openstreetmap.josm.tools.I18n; import org.openstreetmap.josm.tools.Logging; import gnu.getopt.Getopt; import gnu.getopt.LongOpt; /** * This class holds the arguments passed on to {@link MainApplication#main}. * @author Michael Zangl * @since 10899 */ public class ProgramArguments { /** * JOSM command line options. * @see Help/CommandLineOptions */ public enum Option { /** --help|-h Show this help */ HELP(false), /** --version Displays the JOSM version and exits */ VERSION(false), /** --debug Print debugging messages to console */ DEBUG(false), /** --trace Print detailed debugging messages to console */ TRACE(false), /** --language=<language> Set the language */ LANGUAGE(true), /** --reset-preferences Reset the preferences to default */ RESET_PREFERENCES(false), /** --load-preferences=<url-to-xml> Changes preferences according to the XML file */ LOAD_PREFERENCES(true), /** --set=<key>=<value> Set preference key to value */ SET(true), /** --geometry=widthxheight(+|-)x(+|-)y Standard unix geometry argument */ GEOMETRY(true), /** --no-maximize Do not launch in maximized mode */ NO_MAXIMIZE(false), /** --maximize Launch in maximized mode */ MAXIMIZE(false), /** --download=minlat,minlon,maxlat,maxlon Download the bounding box
* --download=<URL> Download the location at the URL (with lat=x&lon=y&zoom=z)
* --download=<filename> Open a file (any file type that can be opened with File/Open) */ DOWNLOAD(true), /** --downloadgps=minlat,minlon,maxlat,maxlon Download the bounding box as raw GPS
* --downloadgps=<URL> Download the location at the URL (with lat=x&lon=y&zoom=z) as raw GPS */ DOWNLOADGPS(true), /** --selection=<searchstring> Select with the given search */ SELECTION(true), /** --offline=<osm_api|josm_website|all> Disable access to the given resource(s), delimited by comma */ OFFLINE(true), /** --skip-plugins */ SKIP_PLUGINS(false); private final String name; private final boolean requiresArg; Option(boolean requiresArgument) { this.name = name().toLowerCase(Locale.ENGLISH).replace('_', '-'); this.requiresArg = requiresArgument; } /** * Replies the option name * @return The option name, in lowercase */ public String getName() { return name; } /** * Determines if this option requires an argument. * @return {@code true} if this option requires an argument, {@code false} otherwise */ public boolean requiresArgument() { return requiresArg; } LongOpt toLongOpt() { return new LongOpt(getName(), requiresArgument() ? LongOpt.REQUIRED_ARGUMENT : LongOpt.NO_ARGUMENT, null, 0); } } private final Map> argMap = new EnumMap<>(Option.class); /** * Construct the program arguments object * @param args The args passed to main. * @since 10936 */ public ProgramArguments(String... args) { Stream.of(Option.values()).forEach(o -> argMap.put(o, new ArrayList<>())); buildCommandLineArgumentMap(args); } /** * Builds the command-line argument map. * @param args command-line arguments array */ private void buildCommandLineArgumentMap(String... args) { Getopt.setI18nHandler(I18n::tr); LongOpt[] los = Stream.of(Option.values()).map(Option::toLongOpt).toArray(LongOpt[]::new); Getopt g = new Getopt("JOSM", args, "hv", los); int c; while ((c = g.getopt()) != -1) { Option opt; switch (c) { case 'h': opt = Option.HELP; break; case 'v': opt = Option.VERSION; break; case 0: opt = Option.values()[g.getLongind()]; break; default: opt = null; } if (opt != null) { addOption(opt, g.getOptarg()); } else throw new IllegalArgumentException("Invalid option: "+ (char) c); } // positional arguments are a shortcut for the --download ... option for (int i = g.getOptind(); i < args.length; ++i) { addOption(Option.DOWNLOAD, args[i]); } } private void addOption(Option opt, String optarg) { argMap.get(opt).add(optarg); } /** * Gets a single argument (the first) that was given for the given option. * @param option The option to search * @return The argument as optional value. */ public Optional getSingle(Option option) { return get(option).stream().findFirst(); } /** * Gets all values that are given for a given option * @param option The option * @return The values that were given. May be empty. */ public Collection get(Option option) { return Collections.unmodifiableList(argMap.get(option)); } /** * Test if a given option was used by the user. * @param option The option to test for * @return true if the user used it. */ public boolean hasOption(Option option) { return !get(option).isEmpty(); } /** * Helper method to indicate if version should be displayed. * @return true to display version */ public boolean showVersion() { return hasOption(Option.VERSION); } /** * Helper method to indicate if help should be displayed. * @return true to display version */ public boolean showHelp() { return !get(Option.HELP).isEmpty(); } /** * Get the log level the user wants us to use. * @return The log level. */ public Level getLogLevel() { if (hasOption(Option.TRACE)) { return Logging.LEVEL_TRACE; } else if (hasOption(Option.DEBUG)) { return Logging.LEVEL_DEBUG; } else { return Logging.LEVEL_INFO; } } /** * Gets a map of all preferences the user wants to set. * @return The preferences to set. It contains null values for preferences to unset */ public Map getPreferencesToSet() { HashMap map = new HashMap<>(); get(Option.SET).stream().map(i -> i.split("=", 2)).forEach(kv -> map.put(kv[0], getValue(kv))); return map; } private static String getValue(String... kv) { if (kv.length < 2) { return ""; } else if ("null".equals(kv[1])) { return null; } else { return kv[1]; } } }