1 package org.opendaylight.controller.config.spi;
3 import org.opendaylight.controller.config.api.DependencyResolver;
4 import org.opendaylight.controller.config.api.ModuleIdentifier;
5 import org.slf4j.Logger;
6 import org.slf4j.LoggerFactory;
9 * Base implementation of Module. This implementation contains base logic for Module reconfiguration with associated fields.
10 * @param <M> Type of module implementation. Enables easier implementation for the {@link #isSame} method
12 public abstract class AbstractModule<M extends AbstractModule<M>> implements org.opendaylight.controller.config.spi.Module {
14 private static final Logger LOG = LoggerFactory.getLogger(AbstractModule.class);
16 private final M oldModule;
17 private final AutoCloseable oldInstance;
18 protected final ModuleIdentifier identifier;
19 private AutoCloseable instance;
20 protected final DependencyResolver dependencyResolver;
23 * Called when module is configured.
25 * @param identifier id of current instance.
26 * @param dependencyResolver resolver used in dependency injection and validation.
28 public AbstractModule(ModuleIdentifier identifier, DependencyResolver dependencyResolver) {
29 this(identifier, dependencyResolver, null, null);
33 * Called when module is reconfigured.
35 * @param identifier id of current instance.
36 * @param dependencyResolver resolver used in dependency injection and validation.
37 * @param oldModule old instance of module that is being reconfigred(replaced) by current instance. The old instance can be examined for reuse.
38 * @param oldInstance old instance wrapped by the old module. This is the resource that is actually being reused if possible or closed otherwise.
40 public AbstractModule(ModuleIdentifier identifier, DependencyResolver dependencyResolver, M oldModule, AutoCloseable oldInstance) {
41 this.identifier = identifier;
42 this.dependencyResolver = dependencyResolver;
43 this.oldModule = oldModule;
44 this.oldInstance = oldInstance;
48 public ModuleIdentifier getIdentifier() {
54 * General algorithm for spawning/closing and reusing wrapped instances.
56 * @return current instance of wrapped resource either by reusing the old one (if present) or constructing a brand new.
59 public final AutoCloseable getInstance() {
61 if(oldInstance!=null && canReuseInstance(oldModule)) {
62 resolveDependencies();
63 instance = reuseInstance(oldInstance);
65 if(oldInstance!=null) {
68 } catch(Exception e) {
69 LOG.error("An error occurred while closing old instance {} for module {}", oldInstance, getIdentifier(), e);
72 resolveDependencies();
73 instance = createInstance();
74 if (instance == null) {
75 throw new IllegalStateException("Error in createInstance - null is not allowed as return value. Module: " + getIdentifier());
83 * @return Brand new instance of wrapped class in case no previous instance is present or reconfiguration is impossible.
85 protected abstract AutoCloseable createInstance();
88 public final boolean canReuse(Module oldModule) {
89 // Just cast into a specific instance
90 // TODO unify this method with canReuseInstance (required Module interface to be generic which requires quite a lot of changes)
91 return getClass().isInstance(oldModule) ? canReuseInstance((M) oldModule) : false;
96 * Users are welcome to override this method to provide custom logic for advanced reusability detection.
98 * @param oldModule old instance of a Module
99 * @return true if the old instance is reusable false if a new one should be spawned
101 protected abstract boolean canReuseInstance(final M oldModule);
104 * By default the oldInstance is returned since this method is by default called only if the oldModule had the same configuration and dependencies configured.
105 * Users are welcome to override this method to provide custom logic for advanced reusability.
107 * @param oldInstance old instance of a class wrapped by the module
108 * @return reused instance
110 protected AutoCloseable reuseInstance(AutoCloseable oldInstance) {
111 // implement if instance reuse should be supported. Override canReuseInstance to change the criteria.
116 * Inject all the dependencies using dependency resolver instance.
118 protected abstract void resolveDependencies();