private Collection<RuntimeModule> collectUnique(Collection<BQModule> bqModules) { // TODO: looking up modules by java type limits the use of lambdas as modules. E.g. we loaded test // properties are dynamically created modules in a repeatedly called Lambda. This didn't work.. // So perhaps use provider name as a unique key? Map<Class<? extends Module>, RuntimeModule> map = new LinkedHashMap<>(); for (BQModule bqModule : bqModules) { RuntimeModule rm = new RuntimeModule(bqModule); RuntimeModule existing = map.putIfAbsent(rm.getModuleType(), rm); if (existing != null) { bootLogger.trace(() -> String.format( "Skipping module '%s' provided by '%s' (already provided by '%s')...", rm.getModuleName(), rm.getProviderName(), existing.getProviderName())); } } calcOverrideGraph(map); return map.values(); }
void checkCycles() { if (overriddenBy != null) { overriddenBy.checkCycles(this, new ArrayList<>()); } }
private Module fold(RuntimeModule rm) { RuntimeModule overriddenBy = rm.getOverriddenBy(); if (overriddenBy == null) { trace(rm.getBqModule(), null); return rm.getModule(); } trace(rm.getBqModule(), overriddenBy.getBqModule()); // WARN: using recursion because fold.. is there a realistic prospect of this blowing the stack? I haven't // seen overrides more than 2-4 levels deep. // fold must happen in this order (overriding starts from the tail). Otherwise the algorithm will not work. return Modules.override(rm.getModule()).with(fold(overriddenBy)); }
void setOverriddenBy(RuntimeModule module) { // no more than one override is allowed if (this.overriddenBy != null) { String message = String.format( "Module %s provided by %s is overridden twice by %s and %s", getModuleName(), getProviderName(), this.overriddenBy.getModuleName(), module.getModuleName()); throw new BootiqueException(1, message); } this.overriddenBy = module; } }
private void calcOverrideGraph(Map<Class<? extends Module>, RuntimeModule> modules) { for (RuntimeModule rm : modules.values()) { for(Class<? extends Module> override : rm.getBqModule().getOverrides()) { RuntimeModule rmn = modules.get(override); if(rmn != null) { rmn.setOverriddenBy(rm); rm.setOverridesOthers(true); } } } }
Class<? extends Module> getModuleType() { return getModule().getClass(); }
private void calcOverrideGraph(Map<Class<? extends Module>, RuntimeModule> modules) { for (RuntimeModule rm : modules.values()) { for(Class<? extends Module> override : rm.getBqModule().getOverrides()) { RuntimeModule rmn = modules.get(override); if(rmn != null) { rmn.setOverriddenBy(rm); rm.setOverridesOthers(true); } } } }
void setOverriddenBy(RuntimeModule module) { // no more than one override is allowed if (this.overriddenBy != null) { String message = String.format( "Module %s provided by %s is overridden twice by %s and %s", getModuleName(), getProviderName(), this.overriddenBy.getModuleName(), module.getModuleName()); throw new BootiqueException(1, message); } this.overriddenBy = module; } }
Class<? extends Module> getModuleType() { return getModule().getClass(); }
private Collection<RuntimeModule> collectUnique(Collection<BQModule> bqModules) { // TODO: looking up modules by java type limits the use of lambdas as modules. E.g. we loaded test // properties are dynamically created modules in a repeatedly called Lambda. This didn't work.. // So perhaps use provider name as a unique key? Map<Class<? extends Module>, RuntimeModule> map = new LinkedHashMap<>(); for (BQModule bqModule : bqModules) { RuntimeModule rm = new RuntimeModule(bqModule); RuntimeModule existing = map.putIfAbsent(rm.getModuleType(), rm); if (existing != null) { bootLogger.trace(() -> String.format( "Skipping module '%s' provided by '%s' (already provided by '%s')...", rm.getModuleName(), rm.getProviderName(), existing.getProviderName())); } } calcOverrideGraph(map); return map.values(); }
private Module fold(RuntimeModule rm) { RuntimeModule overriddenBy = rm.getOverriddenBy(); if (overriddenBy == null) { trace(rm.getBqModule(), null); return rm.getModule(); } trace(rm.getBqModule(), overriddenBy.getBqModule()); // WARN: using recursion because fold.. is there a realistic prospect of this blowing the stack? I haven't // seen overrides more than 2-4 levels deep. // fold must happen in this order (overriding starts from the tail). Otherwise the algorithm will not work. return Modules.override(rm.getModule()).with(fold(overriddenBy)); }
private void checkCycles(RuntimeModule root, List<RuntimeModule> trace) { trace.add(this); if (root == this) { // Add next level, to make error message more clear. trace.add(this.overriddenBy); throw new BootiqueException(1, "Circular override dependency between DI modules: " + trace.stream().map(rm -> rm.bqModule.getName()).collect(Collectors.joining(" -> "))); } if (overriddenBy != null) { overriddenBy.checkCycles(root, trace); } }
void checkCycles() { if (overriddenBy != null) { overriddenBy.checkCycles(this, new ArrayList<>()); } }
private void checkCycles(RuntimeModule root, List<RuntimeModule> trace) { trace.add(this); if (root == this) { // Add next level, to make error message more clear. trace.add(this.overriddenBy); throw new BootiqueException(1, "Circular override dependency between DI modules: " + trace.stream().map(rm -> rm.bqModule.getName()).collect(Collectors.joining(" -> "))); } if (overriddenBy != null) { overriddenBy.checkCycles(root, trace); } }