MATSIM
Config.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * Config.java
4  * *
5  * *********************************************************************** *
6  * *
7  * copyright : (C) 2007 by the members listed in the COPYING, *
8  * LICENSE and WARRANTY file. *
9  * email : info at matsim dot org *
10  * *
11  * *********************************************************************** *
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * See also COPYING, LICENSE and WARRANTY file *
18  * *
19  * *********************************************************************** */
20 
21 package org.matsim.core.config;
22 
23 import java.net.MalformedURLException;
24 import java.net.URL;
25 import java.nio.file.Paths;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.TreeMap;
31 import org.apache.logging.log4j.LogManager;
32 import org.apache.logging.log4j.Logger;
64 
73 public final class Config implements MatsimExtensionPoint {
74 
75  // ////////////////////////////////////////////////////////////////////
76  // member variables
77  // ////////////////////////////////////////////////////////////////////
78 
80  private final TreeMap<String, ConfigGroup> modules = new TreeMap<>();
81 
82  /*
83  * the following members are for the direct access to the core config
84  * groups.
85  */
86 
87  // config groups that are in org.matsim.core.config.groups:
88 
89 
90  private final List<ConfigConsistencyChecker> consistencyCheckers = new ArrayList<>();
91 
93  private static final Logger log = LogManager.getLogger(Config.class);
94 
95  private boolean locked = false;
96  private URL context;
97 
98 
99  // ////////////////////////////////////////////////////////////////////
100  // constructor
101  // ////////////////////////////////////////////////////////////////////
102 
103  public Config() {
104  try {
105  URL currentDir = Paths.get("").toUri().toURL();
106  setContext(currentDir);
107  } catch (MalformedURLException e) {
108  throw new RuntimeException(e);
109  }
110  }
111 
117  public void addCoreModules() {
118  this.modules.put(GlobalConfigGroup.GROUP_NAME, new GlobalConfigGroup());
119 
120  this.modules.put(ControllerConfigGroup.GROUP_NAME, new ControllerConfigGroup());
121 
122  this.modules.put(QSimConfigGroup.GROUP_NAME, new QSimConfigGroup());
123 
124  this.modules.put(CountsConfigGroup.GROUP_NAME, new CountsConfigGroup());
125  this.modules.put(ScoringConfigGroup.GROUP_NAME, new ScoringConfigGroup());
126 
127  this.modules.put(NetworkConfigGroup.GROUP_NAME, new NetworkConfigGroup());
128 
129  this.modules.put(PlansConfigGroup.GROUP_NAME, new PlansConfigGroup());
130 
131  this.modules.put(HouseholdsConfigGroup.GROUP_NAME, new HouseholdsConfigGroup());
132 
134 
135  this.modules.put(FacilitiesConfigGroup.GROUP_NAME, new FacilitiesConfigGroup());
136 
137  this.modules.put(ReplanningConfigGroup.GROUP_NAME, new ReplanningConfigGroup());
138 
140 
141  this.modules.put(ScenarioConfigGroup.GROUP_NAME, new ScenarioConfigGroup());
142 
143  this.modules.put(RoutingConfigGroup.GROUP_NAME, new RoutingConfigGroup());
144 
146 
148 
149 
150  this.modules.put(TransitConfigGroup.GROUP_NAME, new TransitConfigGroup());
151 
152  this.modules.put(LinkStatsConfigGroup.GROUP_NAME, new LinkStatsConfigGroup());
153 
155 
157 
158  this.modules.put( VehiclesConfigGroup.GROUP_NAME , new VehiclesConfigGroup() ) ;
159 
161 
163  // only to provide error messages. kai, may'16
164 
165  this.modules.put(HermesConfigGroup.NAME, new HermesConfigGroup());
166 
168 
170 
174  }
175 
180  public void checkConsistency() {
181  for (ConfigGroup m : this.modules.values()) {
182  m.checkConsistency(this);
183  }
184  for (ConfigConsistencyChecker c : this.consistencyCheckers) {
185  c.checkConsistency(this);
186  }
187 // for (Module m : this.modules.values()) {
188 // if (m.getClass() == Module.class) {
189 // throw new RuntimeException("Config group " + m.getName() + " is present, but has never been read." +
190 // "This is probably an error: You may be expecting functionality which is not available." +
191 // "Maybe you need to add something to the Controler?");
192 // }
193 // }
194  }
195 
196  // ////////////////////////////////////////////////////////////////////
197  // add / set methods
198  // ////////////////////////////////////////////////////////////////////
199 
210  public final ConfigGroup createModule(final String name) {
211  if (this.modules.containsKey(name)) {
212  throw new IllegalArgumentException("Module " + name + " exists already.");
213  }
214  ConfigGroup m = new ConfigGroup(name);
215  this.modules.put(name, m);
216  return m;
217  }
218 
229  public final void addModule(final ConfigGroup specializedConfigModule) {
230  String name = specializedConfigModule.getName();
231  if (name == null || name.isEmpty()) {
232  throw new RuntimeException("cannot insert module with empty name") ;
233  }
234  // The logic is as follows:
235  // (1) assume that module is some SpecializedConfigModule that extends Module
236 
237  // (2) it is presumably found here from parsing, but as a general Module:
238  ConfigGroup m = this.modules.get(name);
239 
240  if (m != null) {
241  // (3) this is the corresponding test: m is general, module is specialized:
242  if (m.getClass() == ConfigGroup.class && specializedConfigModule.getClass() != ConfigGroup.class) {
243  // (4) go through everything in m (from parsing) and add it to module:
244  copyTo(m, specializedConfigModule);
245 
246  // (5) register the resulting module under "name" (which will over-write m):
247  this.modules.put(name, specializedConfigModule);
248  } else {
249  throw new IllegalArgumentException("Module " + name + " exists already.");
250  }
251  }
252  this.modules.put(name, specializedConfigModule);
253  }
254 
255  private static void copyTo(ConfigGroup source, ConfigGroup destination) {
256  for (Map.Entry<String, String> e : source.getParams().entrySet()) {
257  destination.addParam(e.getKey(), e.getValue());
258  }
259 
260  for (Collection<? extends ConfigGroup> sourceSets : source.getParameterSets().values()) {
261  for (ConfigGroup sourceSet : sourceSets) {
262  ConfigGroup destinationSet = destination.createParameterSet(sourceSet.getName());
263  copyTo(sourceSet, destinationSet);
264  destination.addParameterSet(destinationSet);
265  }
266  }
267  }
268 
276  public final void removeModule(final String name) {
277  if (this.modules.containsKey(name)) {
278  this.modules.remove(name);
279  log.warn("Module \"" + name + "\" is removed manually from config");
280 
281  }
282  }
283 
284  // ////////////////////////////////////////////////////////////////////
285  // get methods
286  // ////////////////////////////////////////////////////////////////////
287 
288  public final TreeMap<String, ConfigGroup> getModules() {
289  return this.modules;
290  }
291 
300  @Deprecated // please try to use the "typed" access structures. kai, nov'16
301  public final ConfigGroup getModule(final String moduleName) {
302  return this.modules.get(moduleName);
303  }
304 
317  @Deprecated // use "typed" config group instead
318  public final String getParam(final String moduleName, final String paramName) {
319  ConfigGroup m = this.modules.get(moduleName);
320  if (m == null) {
321  log.error("Module \"" + moduleName + "\" is not known.");
322  throw new IllegalArgumentException("Module \"" + moduleName + "\" is not known.");
323  }
324  String str = m.getValue(paramName);
325  if (str == null) {
326  String message = "Parameter \"" + paramName + "\" of module \"" + moduleName + "\" is not known";
327  log.error(message);
328  throw new IllegalArgumentException(message);
329  }
330  return str;
331  }
332 
345  @Deprecated // use "typed" config group instead
346  public final String findParam(final String moduleName, final String paramName) {
347  ConfigGroup m = this.modules.get(moduleName);
348  if (m == null) {
349  return null;
350  }
351  try {
352  String str = m.getValue(paramName);
353  return str;
354  } catch (IllegalArgumentException e) {
355  return null;
356  }
357  }
358 
359  // ////////////////////////////////////////////////////////////////////
360  // print methods
361  // ////////////////////////////////////////////////////////////////////
362 
363  @Override
364  public final String toString() {
365  return "[nof_modules=" + this.modules.size() + "]";
366  }
367 
368  // ////////////////////////////////////////////////////////////////////
369  // is used for using Config without a config-file given
370  // ////////////////////////////////////////////////////////////////////
380  @Deprecated // use "typed" config group instead
381  public final void setParam(final String moduleName, final String paramName, final String value) {
382  checkIfLocked();
383  ConfigGroup m = this.modules.get(moduleName);
384  if (m == null) {
385  m = createModule(moduleName);
386  log.info("module \"" + moduleName + "\" added.");
387  }
388  m.addParam(paramName, value);
389  }
390 
391  // ////////////////////////////////////////////////////////////////////
392  // direct access to modules / groups
393  // ////////////////////////////////////////////////////////////////////
394 
395  public final GlobalConfigGroup global() {
397  }
398 
401  }
402 
403  public final CountsConfigGroup counts() {
405  }
406 
407  public final ScoringConfigGroup scoring() {
409  }
410 
411  public final NetworkConfigGroup network() {
413  }
414 
415  public final PlansConfigGroup plans() {
417  }
418 
421  }
422 
425  }
426 
429  }
430 
433  }
434 
437  }
438 
441  }
442 
445  }
446 
449  }
450 
453  }
454 
457  }
458 
461  }
462 
465  }
466 
469  }
470 
473  }
474 
477  }
478 
481  }
482 
485  }
486 
489  }
490 
491  // other:
492 
494  boolean alreadyExists = false;
495  for (ConfigConsistencyChecker ch : consistencyCheckers) {
496  if (ch.getClass().equals(checker.getClass())) {
497  alreadyExists = true;
498  }
499  }
500  if ( !alreadyExists ) {
501  this.consistencyCheckers.add(checker);
502  } else {
503  log.info( "ConfigConsistencyChecker with runtime type=" + checker.getClass() + " was already added; not adding it a second time" ) ;
504  }
505  }
506 
507  public void removeConfigConsistencyChecker( final Class clazz ) {
508  // I am not saying that I like this. But I would like to be able to check config consistency before the iterator is created, but by then we still have
509  // unmaterialized config groups, and so I need to remove that checker at that point. Maybe we can sort this in some different way ...
510  consistencyCheckers.removeIf( ch -> ch.getClass().equals( clazz ) );
511  }
512 
513  public final boolean isLocked() {
514  return this.locked;
515  }
516 
517  public final void setLocked(boolean locked) {
518  this.locked = locked;
519  }
520 
521  private void checkIfLocked() {
522  if ( this.isLocked() ) {
523  log.error("too late in execution sequence to set config items. Use");
524  log.error(" Config config = ConfigUtils.loadConfig(filename); ");
525  log.error(" config.xxx().setYyy(...); ");
526  log.error(" Controler ctrl = new Controler( config );");
527  log.error("or") ;
528  log.error(" Config config = ConfigUtils.loadConfig(filename); ");
529  log.error(" config.xxx().setYyy(...); ");
530  log.error(" Scenario scenario = ScenarioUtils.loadScenario(config);") ;
531  log.error(" // do something with scenario") ;
532  log.error(" Controler ctrl = new Controler( scenario );");
533  log.error("This will be changed to an abortive error in the future."); // kai, feb'13
534  }
535  }
536 
537  public final VehiclesConfigGroup vehicles() {
539  }
540 
541  public void setContext(URL context) {
542  if ( this.context==null || !(context.toString().equals( this.context.toString() ) ) ) {
543  log.info("setting context to [" + context + "]");
544  // ConfigUtils.createConfig() is used at several places, e.g. when generating an empty
545  // scenario to obtain the default factories. This will evidently produce output here,
546  // and in some sense the wrong output, since the relevant context is probably set from
547  // some config file path and in fact _not_ changed since this here will be a different
548  // ``throwaway'' config instance. :-( kai, jun'18
549  }
550  this.context = context;
551  }
552 
553  public URL getContext() {
554  return context;
555  }
556 }
ConfigGroup createParameterSet(final String type)
final void setParam(final String moduleName, final String paramName, final String value)
Definition: Config.java:381
final String getParam(final String moduleName, final String paramName)
Definition: Config.java:318
Map< String, String > getParams()
void removeConfigConsistencyChecker(final Class clazz)
Definition: Config.java:507
final VehiclesConfigGroup vehicles()
Definition: Config.java:537
final boolean isLocked()
Definition: Config.java:513
void addParameterSet(final ConfigGroup set)
static void copyTo(ConfigGroup source, ConfigGroup destination)
Definition: Config.java:255
LinkStatsConfigGroup linkStats()
Definition: Config.java:459
final NetworkConfigGroup network()
Definition: Config.java:411
EventsManagerConfigGroup eventsManager()
Definition: Config.java:467
ReplanningAnnealerConfigGroup replanningAnnealer()
Definition: Config.java:483
TransitRouterConfigGroup transitRouter()
Definition: Config.java:455
final Collection<? extends ConfigGroup > getParameterSets(final String type)
final ScoringConfigGroup scoring()
Definition: Config.java:407
final CountsConfigGroup counts()
Definition: Config.java:403
final String findParam(final String moduleName, final String paramName)
Definition: Config.java:346
final void removeModule(final String name)
Definition: Config.java:276
final FacilitiesConfigGroup facilities()
Definition: Config.java:423
HermesConfigGroup hermes()
Definition: Config.java:479
TravelTimeCalculatorConfigGroup travelTimeCalculator()
Definition: Config.java:431
VspExperimentalConfigGroup vspExperimental()
Definition: Config.java:443
final void setLocked(boolean locked)
Definition: Config.java:517
void addConfigConsistencyChecker(final ConfigConsistencyChecker checker)
Definition: Config.java:493
final void addModule(final ConfigGroup specializedConfigModule)
Definition: Config.java:229
TransitConfigGroup transit()
Definition: Config.java:451
TimeAllocationMutatorConfigGroup timeAllocationMutator()
Definition: Config.java:463
final PlansConfigGroup plans()
Definition: Config.java:415
QSimConfigGroup qsim()
Definition: Config.java:447
RoutingConfigGroup routing()
Definition: Config.java:439
ScenarioConfigGroup scenario()
Definition: Config.java:435
SubtourModeChoiceConfigGroup subtourModeChoice()
Definition: Config.java:471
void setContext(URL context)
Definition: Config.java:541
PlanInheritanceConfigGroup planInheritance()
Definition: Config.java:487
String getValue(final String paramName)
final TreeMap< String, ConfigGroup > getModules()
Definition: Config.java:288
final ConfigGroup createModule(final String name)
Definition: Config.java:210
ChangeModeConfigGroup changeMode()
Definition: Config.java:475
final ReplanningConfigGroup replanning()
Definition: Config.java:427
static final Logger log
Definition: Config.java:93
final ControllerConfigGroup controller()
Definition: Config.java:399
final ConfigGroup getModule(final String moduleName)
Definition: Config.java:301
final List< ConfigConsistencyChecker > consistencyCheckers
Definition: Config.java:90
final HouseholdsConfigGroup households()
Definition: Config.java:419
final GlobalConfigGroup global()
Definition: Config.java:395
void addParam(final String paramName, final String value)
final TreeMap< String, ConfigGroup > modules
Definition: Config.java:80