MATSIM
Injector.java
Go to the documentation of this file.
1 /*
2  * *********************************************************************** *
3  * * project: org.matsim.*
4  * * Injector.java
5  * * *
6  * * *********************************************************************** *
7  * * *
8  * * copyright : (C) 2014 by the members listed in the COPYING, *
9  * * LICENSE and WARRANTY file. *
10  * * email : info at matsim dot org *
11  * * *
12  * * *********************************************************************** *
13  * * *
14  * * This program is free software; you can redistribute it and/or modify *
15  * * it under the terms of the GNU General Public License as published by *
16  * * the Free Software Foundation; either version 2 of the License, or *
17  * * (at your option) any later version. *
18  * * See also COPYING, LICENSE and WARRANTY file *
19  * * *
20  * * ***********************************************************************
21  */
22 
23 package org.matsim.core.controler;
24 
25 import java.lang.annotation.Annotation;
26 import java.util.*;
27 
28 import com.google.inject.spi.LinkedKeyBinding;
29 import org.apache.logging.log4j.Level;
30 import org.apache.logging.log4j.LogManager;
31 import org.apache.logging.log4j.Logger;
32 import org.matsim.api.core.v01.Scenario;
33 import org.matsim.core.config.Config;
38 
39 import com.google.inject.Binder;
40 import com.google.inject.Binding;
41 import com.google.inject.Guice;
42 import com.google.inject.Key;
43 import com.google.inject.Module;
44 import com.google.inject.internal.BindingImpl;
45 import com.google.inject.multibindings.MapBinder;
46 import com.google.inject.name.Names;
47 import com.google.inject.spi.DefaultElementVisitor;
48 import com.google.inject.spi.Element;
49 import com.google.inject.spi.Elements;
50 import com.google.inject.util.Modules;
52 
53 public final class Injector {
54  private Injector(){} // namespace only, do not instantiate
55 
56  private static final Logger logger = LogManager.getLogger(Injector.class);
57 
58  public static com.google.inject.Injector createInjector(final Config config, Module... modules) {
59  com.google.inject.Injector bootstrapInjector = Guice.createInjector(new Module() {
60  @Override
61  public void configure(Binder binder) {
62  binder.requireExplicitBindings(); // For now, we are conservative and disable this kind of magic.
63  binder.install(new ExplodedConfigModule(config));
64  }
65  });
66  // A MATSim module needs the config at configuration time in order to decide what
67  // features to provide. So we create a bootstrapInjector which already has the config
68  // and provides it to the MATSim modules.
69  List<com.google.inject.Module> guiceModules = new ArrayList<>();
70  for (Module module : modules) {
71  bootstrapInjector.injectMembers(module);
72  guiceModules.add(module);
73  }
74  com.google.inject.Injector realInjector = bootstrapInjector.createChildInjector(insertMapBindings(guiceModules));
75  printInjector(realInjector, logger);
76  return realInjector;
77  }
78 
79  public static void printInjector(com.google.inject.Injector injector, Logger log) {
80  Level level = Level.DEBUG ;
81  log.log(level,"=== printInjector start ===") ;
82  for (Map.Entry<Key<?>, Binding<?>> entry : injector.getBindings().entrySet()) {
83  if ( entry.getKey().toString().contains("type=org.matsim") ) {
84  Annotation annotation = entry.getKey().getAnnotation();
85  log.log( level, entry.getKey().getTypeLiteral() + " " + (annotation != null ? annotation.toString() : ""));
86  log.log(level, " --> provider: " + entry.getValue().getProvider());
87  log.log(level, " --> source: " + entry.getValue().getSource() );
88  if ( entry.getValue() instanceof BindingImpl ) {
89  log.log( level, " --> scope: " + ((BindingImpl<?>)entry.getValue()).getScoping() ) ;
90  }
91  if ( entry.getValue() instanceof LinkedKeyBinding) {
92  log.log( level, " --> target: " + ((LinkedKeyBinding) entry.getValue()).getLinkedKey() ) ;
93  }
94  log.log(level, " ==full==> " + entry.getValue() );
95  // yy could probably format the above in a better way. kai, may'16
96  log.log(level, "" );
97  }
98  }
99  log.log(level,"=== printInjector end ===") ;
100  }
101 
102  private static Module insertMapBindings(List<Module> guiceModules) {
103  com.google.inject.AbstractModule routingModuleBindings = createMapBindingsForType(guiceModules, RoutingModule.class);
104  com.google.inject.AbstractModule travelTimeBindings = createMapBindingsForType(guiceModules, TravelTime.class);
105  com.google.inject.AbstractModule travelDisutilityFactoryBindings = createMapBindingsForType(guiceModules, TravelDisutilityFactory.class);
106  return Modules.combine(Modules.combine(guiceModules), routingModuleBindings, travelTimeBindings, travelDisutilityFactoryBindings);
107  }
108 
109  private static <T> com.google.inject.AbstractModule createMapBindingsForType(List<Module> guiceModules, final Class<T> aClass) {
110  final Set<String> modes = new HashSet<>();
111  for (Element element : Elements.getElements(guiceModules)) {
112  element.acceptVisitor(new DefaultElementVisitor<Object>() {
113  @Override
114  public <T> Object visit(Binding<T> binding) {
115  if (binding.getKey().getTypeLiteral().getRawType().equals(aClass)) {
116  if (binding.getKey().getAnnotation() instanceof com.google.inject.name.Named) {
117  modes.add(((com.google.inject.name.Named) binding.getKey().getAnnotation()).value());
118  }
119  }
120  return null;
121  }
122  });
123  }
124  return new com.google.inject.AbstractModule() {
125  @Override
126  protected void configure() {
127  MapBinder<String, T> routingModuleMultibinder = MapBinder.newMapBinder(binder(), String.class, aClass);
128  for (String mode : modes) {
129  routingModuleMultibinder.addBinding(mode).to(Key.get(aClass, Names.named(mode)));
130  }
131  }
132  };
133  }
134 
140  public static com.google.inject.Injector createMinimalMatsimInjector( Config config, Scenario scenario, Module... modules ){
141 
142  final Collection<Module> theModules = new ArrayList<>();
143  theModules.add( new AbstractModule(){
144  @Override
145  public void install(){
146  install( new NewControlerModule() );
147  install( new ControlerDefaultCoreListenersModule() );
148  install( new ControlerDefaultsModule() );
149  install( new ScenarioByInstanceModule( scenario ) );
150  }
151  });
152  theModules.addAll( Arrays.asList( modules ) );
153 
154  return Injector.createInjector( config, theModules.toArray(new Module[0]) );
155  }
156 
157 
158 }
static void printInjector(com.google.inject.Injector injector, Logger log)
Definition: Injector.java:79
static com.google.inject.Injector createMinimalMatsimInjector(Config config, Scenario scenario, Module... modules)
Definition: Injector.java:140
static final Logger logger
Definition: Injector.java:56
static com.google.inject.Injector createInjector(final Config config, Module... modules)
Definition: Injector.java:58
static Module insertMapBindings(List< Module > guiceModules)
Definition: Injector.java:102
static< T > com.google.inject.AbstractModule createMapBindingsForType(List< Module > guiceModules, final Class< T > aClass)
Definition: Injector.java:109