
no.mnemonic.commons.container.ComponentNode Maven / Gradle / Ivy
package no.mnemonic.commons.container;
import no.mnemonic.commons.component.ComponentConfigurationException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
class ComponentNode {
private final String objectName;
private final Object object;
private boolean started;
private Set initializationDependencies = new HashSet<>();
private Set destructionDependencies = new HashSet<>();
ComponentNode(String objectName, Object object) {
this.object = object;
this.objectName = objectName;
}
@Override
public String toString() {
return String.format("%s / %s", objectName, object.getClass().getName());
}
Object getObject() {
return object;
}
String getObjectName() {
return objectName;
}
boolean isStarted() {
return started;
}
void setStarted(boolean set) {
this.started = set;
}
/**
* @return set of nodes which should be destroyed before this node
*/
Set getDestructionDependencies() {
return this.destructionDependencies;
}
/**
* @return set of nodes which should be initialized before this node
*/
Set getInitializationDependencies() {
return this.initializationDependencies;
}
/**
* Add init dependency to n, i.e. n should initialize before this node
*
* @param n node to dependency
*/
void addInitializationDependency(ComponentNode n) {
List depTree = n.resolveInitializationDependencyPath(this);
if (depTree != null) {
throwCircularDependencyException(depTree);
}
this.initializationDependencies.add(n);
}
/**
* Add destroy dependency to n, i.e. n should be destroyed before this node
*
* @param n node to dependency
*/
void addDestructionDependency(ComponentNode n) {
List depTree = n.resolveDestructionDependencyPath(this);
if (depTree != null) {
throwCircularDependencyException(depTree);
}
this.destructionDependencies.add(n);
}
//private methods
/**
* Check if node n is set to initialize before this node
*
* @param n node to check
* @return initialization dependency path back to node n
*/
private List resolveInitializationDependencyPath(ComponentNode n) {
List dependencyPath = new ArrayList<>();
dependencyPath.add(this);
// if n is set to initialize after this, then return true
if (this.getInitializationDependencies().contains(n)) {
dependencyPath.add(n);
return dependencyPath;
}
// if any node which is set to initialize before this node
// (i.e. this node is initialized after that node)
// also is set to initialize before n, then
// return true
for (ComponentNode previous : this.getInitializationDependencies()) {
List prevDependencyPath = previous.resolveInitializationDependencyPath(n);
if (prevDependencyPath != null) {
dependencyPath.addAll(prevDependencyPath);
return dependencyPath;
}
}
// if not, there is no indication that we are set to start before n
return null;
}
/**
* Check if node n is set to destroy before this node
*
* @param n node to check
* @return destruction dependency path back to node n
*/
private List resolveDestructionDependencyPath(ComponentNode n) {
List dependencyPath = new ArrayList<>();
dependencyPath.add(this);
// if n is listed to destroy before this, then return true
if (this.getDestructionDependencies().contains(n)) {
dependencyPath.add(n);
return dependencyPath;
}
// if any node which is set to destroy before this node (we have a destroy dependency on)
// has a destroy dependency on n, then we also have a destroy dependency on n.
for (ComponentNode previous : this.getDestructionDependencies()) {
List prevDependencyPath = previous.resolveDestructionDependencyPath(n);
if (prevDependencyPath != null) {
dependencyPath.addAll(prevDependencyPath);
return dependencyPath;
}
}
// if not, there is no indication that n is set to destroy before us
return null;
}
private void throwCircularDependencyException(List depTree) {
StringBuilder buf = new StringBuilder("Circular dependency: ");
buf.append(this.getObjectName());
for (ComponentNode nn : depTree) {
buf.append(" -> ").append(nn.getObjectName());
}
throw new ComponentConfigurationException(buf.toString());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy