2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.controller.config.spi;
11 import org.opendaylight.controller.config.api.DependencyResolver;
12 import org.opendaylight.controller.config.api.ModuleIdentifier;
13 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory;
17 * Base implementation of Module. This implementation contains base logic for Module reconfiguration with associated fields.
18 * @param <M> Type of module implementation. Enables easier implementation for the {@link #isSame} method
20 public abstract class AbstractModule<M extends AbstractModule<M>> implements org.opendaylight.controller.config.spi.Module {
22 private static final Logger LOG = LoggerFactory.getLogger(AbstractModule.class);
24 private final M oldModule;
25 private final AutoCloseable oldInstance;
26 protected final ModuleIdentifier identifier;
27 private AutoCloseable instance;
28 protected final DependencyResolver dependencyResolver;
31 * Called when module is configured.
33 * @param identifier id of current instance.
34 * @param dependencyResolver resolver used in dependency injection and validation.
36 public AbstractModule(ModuleIdentifier identifier, DependencyResolver dependencyResolver) {
37 this(identifier, dependencyResolver, null, null);
41 * Called when module is reconfigured.
43 * @param identifier id of current instance.
44 * @param dependencyResolver resolver used in dependency injection and validation.
45 * @param oldModule old instance of module that is being reconfigred(replaced) by current instance. The old instance can be examined for reuse.
46 * @param oldInstance old instance wrapped by the old module. This is the resource that is actually being reused if possible or closed otherwise.
48 public AbstractModule(ModuleIdentifier identifier, DependencyResolver dependencyResolver, M oldModule, AutoCloseable oldInstance) {
49 this.identifier = identifier;
50 this.dependencyResolver = dependencyResolver;
51 this.oldModule = oldModule;
52 this.oldInstance = oldInstance;
56 public ModuleIdentifier getIdentifier() {
62 * General algorithm for spawning/closing and reusing wrapped instances.
64 * @return current instance of wrapped resource either by reusing the old one (if present) or constructing a brand new.
67 public final AutoCloseable getInstance() {
69 if(oldInstance!=null && canReuseInstance(oldModule)) {
70 resolveDependencies();
71 instance = reuseInstance(oldInstance);
73 if(oldInstance!=null) {
76 } catch(Exception e) {
77 LOG.error("An error occurred while closing old instance {} for module {}", oldInstance, getIdentifier(), e);
80 resolveDependencies();
81 instance = createInstance();
82 if (instance == null) {
83 throw new IllegalStateException("Error in createInstance - null is not allowed as return value. Module: " + getIdentifier());
91 * @return Brand new instance of wrapped class in case no previous instance is present or reconfiguration is impossible.
93 protected abstract AutoCloseable createInstance();
96 public final boolean canReuse(Module oldModule) {
97 // Just cast into a specific instance
98 // TODO unify this method with canReuseInstance (required Module interface to be generic which requires quite a lot of changes)
99 return getClass().isInstance(oldModule) ? canReuseInstance((M) oldModule) : false;
104 * Users are welcome to override this method to provide custom logic for advanced reusability detection.
106 * @param oldModule old instance of a Module
107 * @return true if the old instance is reusable false if a new one should be spawned
109 protected abstract boolean canReuseInstance(final M oldModule);
112 * By default the oldInstance is returned since this method is by default called only if the oldModule had the same configuration and dependencies configured.
113 * Users are welcome to override this method to provide custom logic for advanced reusability.
115 * @param oldInstance old instance of a class wrapped by the module
116 * @return reused instance
118 protected AutoCloseable reuseInstance(AutoCloseable oldInstance) {
119 // implement if instance reuse should be supported. Override canReuseInstance to change the criteria.
124 * Inject all the dependencies using dependency resolver instance.
126 protected abstract void resolveDependencies();