22 package org.matsim.core.config;
24 import java.util.ArrayDeque;
25 import java.util.Arrays;
26 import java.util.Collection;
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.LinkedList;
31 import java.util.List;
33 import java.util.Optional;
35 import java.util.stream.Collectors;
37 import org.apache.logging.log4j.LogManager;
38 import org.apache.logging.log4j.Logger;
138 final private Map<String, String>
options =
new HashMap<>();
152 final private Set<String> allowedPrefixes =
new HashSet<>(Collections.singleton(CONFIG_PREFIX));
153 final private Set<String> allowedOptions =
new HashSet<>();
154 final private Set<String> requiredOptions =
new HashSet<>();
156 private boolean positionalArgumentsAllowed =
true;
157 private boolean allowAnyOption =
false;
167 this.arguments = Arrays.asList(args);
168 for( String argument : this.arguments ){
169 if ( argument==null) {
170 throw new RuntimeException(
"one of the entries in args is null; this will not work ..." ) ;
180 positionalArgumentsAllowed = allow;
190 allowAnyOption = allow;
200 allowedOptions.addAll(options);
217 allowedOptions.addAll(options);
218 requiredOptions.addAll(options);
237 allowedPrefixes.addAll(prefixes);
271 positionalArgumentsAllowed, allowAnyOption);
272 commandLine.
process(arguments);
277 private CommandLine(Set<String> allowedOptions, Set<String> requiredOptions, Set<String> allowedPrefixes,
278 boolean positionalArgumentsAllowed,
boolean allowAnyOption) {
293 return positionalArguments.size();
301 return Collections.unmodifiableList(positionalArguments);
309 return index < positionalArguments.size() ? Optional.of(positionalArguments.get(index)) : Optional.empty();
319 if (index < positionalArguments.size()) {
320 return positionalArguments.get(index);
323 "Requested positional command line argument with index %d, but only %d arguments are available",
324 index, positionalArguments.size()));
334 return Collections.unmodifiableCollection(options.keySet());
341 return options.containsKey(option);
348 return options.containsKey(option) ? Optional.of(options.get(option)) : Optional.empty();
358 if (options.containsKey(option)) {
359 return options.get(option);
362 String.format(
"Requested command line option '%s' is not available", option));
375 positionalArguments.clear();
377 String currentOption = null;
379 for (String token : arguments) {
380 if (token.startsWith(
"--")) {
381 if (currentOption != null) {
385 currentOption = token.substring(2);
387 if (currentOption != null) {
393 currentOption = null;
397 if (currentOption != null) {
418 List<String> flatArguments =
new LinkedList<>();
420 for (String argument : args) {
421 int index = argument.lastIndexOf(
'=');
422 int bracketIndex = argument.lastIndexOf(
']');
424 if (bracketIndex > index) {
425 index = argument.indexOf(
'=', bracketIndex);
429 flatArguments.add(argument.substring(0, index));
430 flatArguments.add(argument.substring(index + 1));
432 flatArguments.add(argument);
436 return flatArguments;
445 if (!positionalArgumentsAllowed) {
449 positionalArguments.add(value);
458 if (!allowAnyOption && !allowedOptions.contains(option)) {
459 String[] parts = option.split(
":");
461 if (!allowedPrefixes.contains(parts[0])) {
466 options.put(option, value);
475 List<String> missingOptions =
new LinkedList<>();
477 for (String option : requiredOptions) {
478 if (!options.containsKey(option)) {
479 missingOptions.add(option);
483 if (missingOptions.size() > 0) {
484 throw new ConfigurationException(
485 String.format(
"The following options are missing: %s", missingOptions.toString()));
498 List<String> configOptions = options.keySet().stream().filter(o -> o.startsWith(CONFIG_PREFIX +
":"))
499 .collect(Collectors.toList());
501 for (String option : configOptions) {
511 logger.info(String.format(
"Received %d positional command line arguments:", positionalArguments.size()));
512 logger.info(
" " + String.join(
" , ", positionalArguments));
514 Map<String, List<String>> prefixedOptions =
new HashMap<>();
515 List<String> nonPrefixedOptions =
new LinkedList<>();
517 for (String option : options.keySet()) {
518 int separatorIndex = option.indexOf(
':');
520 if (separatorIndex > -1) {
521 String prefix = option.substring(0, separatorIndex);
522 option = option.substring(separatorIndex + 1);
524 if (!prefixedOptions.containsKey(prefix)) {
525 prefixedOptions.put(prefix,
new LinkedList<>());
528 prefixedOptions.get(prefix).add(option);
530 nonPrefixedOptions.add(option);
534 logger.info(String.format(
"Received %d command line options with %d prefixes:", options.size(),
535 prefixedOptions.size()));
537 Collections.sort(nonPrefixedOptions);
538 for (String option : nonPrefixedOptions) {
539 logger.info(String.format(
" %s = %s", option, options.get(option)));
542 List<String> orderedPrefixes =
new LinkedList<>(prefixedOptions.keySet());
543 Collections.sort(orderedPrefixes);
545 for (String prefix : orderedPrefixes) {
546 logger.info(String.format(
" Prefix %s:", prefix));
548 for (String option : prefixedOptions.get(prefix)) {
549 logger.info(String.format(
" %s = %s", option, options.get(prefix +
":" + option)));
555 int separatorIndex = remainder.indexOf(
'.');
557 if (separatorIndex > -1) {
558 String module = remainder.substring(0, separatorIndex);
559 String newRemainder = remainder.substring(separatorIndex + 1);
561 module = this.configAliases.
resolveAlias(module,
new ArrayDeque<>());
563 if (config.getModules().containsKey(module)) {
564 processParameter(option, module, config.getModules().get(module), newRemainder);
567 String.format(
"Invalid MATSim option: '%s'. Module '%s' does not exist.", remainder, module));
571 String.format(
"Malformatted MATSim option: '%s'. Expected MODULE.*", remainder));
577 if (remainder.contains(
"[")) {
578 int selectorStartIndex = remainder.indexOf(
'[');
579 int selectorEndIndex = remainder.indexOf(
']');
580 int equalIndex = remainder.indexOf(
'=');
582 if (selectorStartIndex > -1 && selectorEndIndex > -1 && equalIndex > -1) {
583 if (selectorStartIndex < equalIndex && equalIndex < selectorEndIndex) {
584 String parameterSetType = remainder.substring(0, selectorStartIndex);
585 String selectionParameter = remainder.substring(selectorStartIndex + 1, equalIndex);
586 String selectionValue = remainder.substring(equalIndex + 1, selectorEndIndex);
588 String newRemainder = remainder.substring(selectorEndIndex + 1);
590 if (newRemainder.startsWith(
".")) {
591 newRemainder = newRemainder.substring(1);
593 String newPath = String.format(
"%s.%s[%s=%s]", path, parameterSetType, selectionParameter,
596 Collection<? extends ConfigGroup> parameterSets = configGroup
597 .getParameterSets(parameterSetType);
600 final boolean changeValueInAllSets = selectionParameter.equals(
"*") && selectionValue.equals(
"*");
602 if (!parameterSets.isEmpty()) {
604 if (changeValueInAllSets || parameterSet.getParams().containsKey(selectionParameter)) {
605 String comparisonValue = parameterSet.getParams().get(selectionParameter);
607 if (changeValueInAllSets || comparisonValue.equals(selectionValue)) {
609 if (!changeValueInAllSets) {
616 if (parameterSetType.equals(
ScoringParameterSet.
SET_TYPE) && selectionParameter.equals(
"subpopulation") && selectionValue.equals(
"null")) {
624 if (changeValueInAllSets) {
628 String.format(
"Parameter set '%s' with %s=%s for %s is not available in %s",
629 parameterSetType, selectionParameter, selectionValue, path, option));
633 String.format(
"Parameter set of type '%s' for %s is not available in %s",
634 parameterSetType, path, option));
641 "Malformatted parameter set selector: '%s' in %s. Expected %s.SET_TYPE[PARAM=VALUE].*", remainder,
644 if (configGroup.getParams().containsKey(remainder)) {
645 String value = options.get(option);
646 configGroup.addParam(remainder, value);
647 logger.info(String.format(
"Setting %s to %s", option, value));
661 private static final long serialVersionUID = 8427111111975754721L;
String resolveAlias(String oldName, Deque< String > pathStack)
String getPositionalArgumentStrict(int index)
void processParameter(String option, String path, ConfigGroup configGroup, String remainder)
final Set< String > requiredOptions
String getOptionStrict(String option)
Optional< String > getOption(String option)
final static Logger logger
void applyConfiguration(Config config)
final Set< String > allowedOptions
Builder allowOptions(Collection< String > options)
Optional< String > getPositionalArgument(int index)
Builder allowPrefixes(String... prefixes)
final boolean positionalArgumentsAllowed
final List< String > arguments
ConfigurationException(String message)
final Map< String, String > options
final ConfigAliases configAliases
Builder requireOptions(String... options)
final Set< String > requiredOptions
int getNumberOfPositionalArguments()
CommandLine(Set< String > allowedOptions, Set< String > requiredOptions, Set< String > allowedPrefixes, boolean positionalArgumentsAllowed, boolean allowAnyOption)
boolean hasOption(String option)
void processConfigOption(Config config, String option, String remainder)
Builder allowPositionalArguments(boolean allow)
final Set< String > allowedPrefixes
Builder requireOptions(Collection< String > options)
List< String > flattenArguments(List< String > args)
Builder allowOptions(String... options)
static final String SET_TYPE
final boolean allowAnyOption
void addOption(String option, String value)
Collection< String > getAvailableOptions()
final Set< String > allowedOptions
void process(List< String > args)
final static String FLAG_VALUE
Builder allowAnyOption(boolean allow)
final static String CONFIG_PREFIX
Builder allowPrefixes(Collection< String > prefixes)
void addPositionalArgument(String value)
final Set< String > allowedPrefixes
boolean positionalArgumentsAllowed
final List< String > positionalArguments
void checkRequiredOptions()
List< String > getPositionalArguments()