Source:
public Module getModule(Configuration configuration) { return new AbstractModule() { @Override protected void configure() { Configuration databasesSectionConfiguration = configuration.getSubconfiguration("databases"); Set<String> databaseNames = databasesSectionConfiguration.listKeyPrefixes(1); Map<String, ? extends Class<? extends TableManager>> tableManagerClasses = getTableManagerClassesByType(); for (String database : databaseNames) { Configuration databaseConfiguration = databasesSectionConfiguration.getSubconfiguration(database); String tableManagerType = databaseConfiguration.getString("table_manager_type").orElse("read_only"); checkArgument(tableManagerClasses.containsKey(tableManagerType), "unknown table manager type %s for database %s; expecting one of %s", tableManagerType, database, tableManagerClasses.keySet()); Class<? extends TableManager> tableManagerClass = tableManagerClasses.get(tableManagerType.toLowerCase()); Key<TableManager> tableManagerKey = Key.get(TableManager.class, named(database)); PrivateModule tableManagerPrivateModule = new PrivateModule() { @Override protected void configure() { bind(QueryExecutor.class).to(Key.get(QueryExecutor.class, named(database))); bind(Key.get(String.class, named("databaseName"))).toInstance(database); bind(tableManagerKey).to(tableManagerClass); expose(tableManagerKey); } }; install(tableManagerPrivateModule); newMapBinder(binder(), String.class, TableManager.class).addBinding(database).to(tableManagerKey); } } private Map<String, ? extends Class<? extends TableManager>> getTableManagerClassesByType() { return getAnnotatedSubTypesOf(TableManager.class, TableManager.Descriptor.class).stream() .collect(toMap( tableManagerClass -> tableManagerClass.getAnnotation(TableManager.Descriptor.class).type().toLowerCase(), tableManagerClass -> tableManagerClass)); } @Inject() @Provides public TableManagerDispatcher defaultTableManagerDispatcher(Map<String, TableManager> tableManagers) { return new DefaultTableManagerDispatcher(tableManagers); } }; }

Target:
public Module getModule(Configuration configuration) { return new AbstractModule() { @Override protected void configure() { Configuration databasesSectionConfiguration = configuration.getSubconfiguration("databases"); Set<String> databaseNames = databasesSectionConfiguration.listKeyPrefixes(1); if (databaseNames.isEmpty()) { bind(new TypeLiteral<Map<String, TableManager>>() {}).toInstance(emptyMap()); bind(new TypeLiteral<Map<String, QueryExecutor>>() {}).toInstance(emptyMap()); return; } Map<String, ? extends Class<? extends TableManager>> tableManagerClasses = getTableManagerClassesByType(); for (String database : databaseNames) { Configuration databaseConfiguration = databasesSectionConfiguration.getSubconfiguration(database); String tableManagerType = databaseConfiguration.getString("table_manager_type").orElse(ReadOnlyTableManager.TYPE.toLowerCase()); checkArgument(tableManagerClasses.containsKey(tableManagerType), "unknown table manager type %s for database %s; expecting one of %s", tableManagerType, database, tableManagerClasses.keySet()); Class<? extends TableManager> tableManagerClass = tableManagerClasses.get(tableManagerType.toLowerCase()); Key<TableManager> tableManagerKey = Key.get(TableManager.class, named(database)); PrivateModule tableManagerPrivateModule = new PrivateModule() { @Override protected void configure() { bind(QueryExecutor.class).to(Key.get(QueryExecutor.class, named(database))); bind(Key.get(String.class, named("databaseName"))).toInstance(database); bind(tableManagerKey).to(tableManagerClass); expose(tableManagerKey); } }; install(tableManagerPrivateModule); newMapBinder(binder(), String.class, TableManager.class).addBinding(database).to(tableManagerKey); } } private Map<String, ? extends Class<? extends TableManager>> getTableManagerClassesByType() { return getAnnotatedSubTypesOf(TableManager.class, TableManager.Descriptor.class).stream() .collect(toMap( tableManagerClass -> tableManagerClass.getAnnotation(TableManager.Descriptor.class).type().toLowerCase(), tableManagerClass -> tableManagerClass)); } @Inject @Provides public TableManagerDispatcher defaultTableManagerDispatcher(Map<String, TableManager> tableManagers) { return new DefaultTableManagerDispatcher(tableManagers); } }; }