package org.wamblee.system.container;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
*/
package org.wamblee.system.graph;
+/**
+ * Represents an application-independent edge of a graph.
+ * Applications might choose to implement the Edge interface
+ * directly.
+ *
+ * @author Erik Brakkee
+ */
public class DefaultEdge implements Edge {
private Node _from;
*/
package org.wamblee.system.graph;
+/**
+ * Default application-independent node. Specific applications of the graph might
+ * implement the Node interface directly.
+ * @author Erik Brakkee
+ *
+ */
public class DefaultNode implements Node {
private String _name;
+ /**
+ * Constructs the node.
+ * @param aName Node name.
+ */
public DefaultNode(String aName) {
_name = aName;
}
+ /**
+ * Returns the node name.
+ */
@Override
public String getName() {
return _name;
*/
package org.wamblee.system.graph;
+/**
+ * Represents an edge of a graph.
+ *
+ * @author Erik Brakkee
+ */
public interface Edge {
+ /**
+ * @return The from part of the edge.
+ */
Node getFrom();
+
+ /**
+ * @return The to part of the edge.
+ */
Node getTo();
}
import java.util.List;
+/**
+ * Edge factory used to extend a graph with new edges.
+ * @author Erik Brakkee
+ *
+ * @param <NodeType> Type of node.
+ */
public interface EdgeFactory<NodeType extends Node> {
+ /**
+ * Computes a number of new edges to be added to the graph.
+ * @param aFrom From node.
+ * @param aTo To node.
+ * @return List of edges from the from to the to node.
+ */
List<Edge> create(NodeType aFrom, NodeType aTo);
}
import java.util.ArrayList;
import java.util.List;
+/**
+ * Represents a graph consisting of nodes and edges.
+ *
+ * @author Erik Brakkee
+ */
public class Graph {
private List<Node> _nodes;
private List<Edge> _edges;
+ /**
+ * Constructs the graph.
+ */
public Graph() {
_nodes = new ArrayList<Node>();
_edges = new ArrayList<Edge>();
}
+ /**
+ * Adds a node.
+ *
+ * @param aNode
+ * Node to add.
+ * @throws IllegalArgumentException
+ * In case the node already exists. Node equality is checked
+ * using <code>equals</code>.
+ */
public void addNode(Node aNode) {
if (_nodes.contains(aNode)) {
throw new IllegalArgumentException("Node '" + aNode.getName()
}
_nodes.add(aNode);
}
-
- public Node findNode(String aName) {
- for (Node node: _nodes) {
- if ( node.getName().equals(aName)) {
- return node;
+
+ /**
+ * Finds a node with the given name.
+ *
+ * @param aName
+ * Node name.
+ * @return Node or null if not found.
+ */
+ public Node findNode(String aName) {
+ for (Node node : _nodes) {
+ if (node.getName().equals(aName)) {
+ return node;
}
}
- return null;
+ return null;
}
+ /**
+ * Removes a node.
+ *
+ * @param aNode
+ * Node to remove.
+ * @return True iff the node was removed.
+ * @throws IllegalArgumentException
+ * In case there are edges of which the node is a part.
+ */
public boolean removeNode(Node aNode) {
if (!findOutgoing(aNode).isEmpty() || !findIncoming(aNode).isEmpty()) {
throw new IllegalArgumentException("Cannot remove node '"
return _nodes.remove(aNode);
}
+ /**
+ * Adds a list of nodes.
+ *
+ * @param aNodes
+ * Nodes to add.
+ *
+ * @see #addNode(Node)
+ */
public void addNodes(List<Node> aNodes) {
for (Node node : aNodes) {
addNode(node);
}
}
+ /**
+ * Adds an edge.
+ *
+ * @param aEdge
+ * Edge to add.
+ * @throws IllegalArgumentException
+ * In case one of the nodes of the edges is not part of the
+ * graph or if the same edge (as determined by
+ * {@link #equals(Object)} is already a part of the graph.
+ */
public void addEdge(Edge aEdge) {
if (_edges.contains(aEdge)) {
throw new IllegalArgumentException("Edge '" + aEdge
_edges.add(aEdge);
}
+ /**
+ * Removes an edge.
+ * @param aEdge Edge to remove.
+ * @return True if the edge was removed.
+ */
public boolean removeEdge(Edge aEdge) {
return _edges.remove(aEdge);
}
+ /**
+ * Adds a number of edges.
+ * @param aEdges Edges to add.
+ */
public void addEdges(List<Edge> aEdges) {
for (Edge edge : aEdges) {
addEdge(edge);
}
}
+ /**
+ * Gets the nodes.
+ * @return Copy of the list of nodes of the graph.
+ */
public List<Node> getNodes() {
return new ArrayList<Node>(_nodes);
}
+ /**
+ * Gets the edges.
+ * @return Copy of the list of edges of the graph.
+ */
public List<Edge> getEdges() {
return new ArrayList<Edge>(_edges);
}
+ /**
+ * Extends the graph with edges using an edge factory. All combinations of
+ * nodes are passed to the factory which creates additional edges.
+ * @param aFactory Edge factory.
+ */
public void extend(EdgeFactory aFactory) {
for (Node from : _nodes) {
for (Node to : _nodes) {
}
}
+ /**
+ * Finds all outgoing edges of a node. More specifically, finds
+ * all edges <code>e</code> for which <code>e.getFrom().getName() = aNode.getName()</code>.
+ * @param aNode Node for which to find outgoing edges.
+ * @return List of outgoing edges.
+ */
public List<Edge> findOutgoing(Node aNode) {
List<Edge> result = new ArrayList<Edge>();
for (Edge edge : _edges) {
return result;
}
+ /**
+ * Finds all incoming edges of a node.
+ * More specifically, finds
+ * all edges <code>e</code> for which <code>e.getTo().getName() = aNode.getName()</code>.
+ * @param aNode Node for which to find incoming edges.
+ * @return List of incoming edges.
+ */
public List<Edge> findIncoming(Node aNode) {
List<Edge> result = new ArrayList<Edge>();
for (Edge edge : _edges) {
return result;
}
+ /**
+ * Implements a visitor design pattern.
+ * This loops over all nodes and all edges and invokes the appropriate visit
+ * methods on the visitor.
+ * @param aVisitor Visitor.
+ */
public void accept(Visitor aVisitor) {
List<Node> nodes = getNodes(); // copy to make sure the visitor can
- // modify the
+ // modify the
// list of nodes as part of the loop.
List<Edge> edges = getEdges(); // copy ..... (see above).
*/
package org.wamblee.system.graph;
+/**
+ * Represents a node in a graph.
+ * @author Erik Brakkee
+ */
public interface Node {
+ /**
+ * Gets the node name uniquely identifying the node in the graph.
+ * @return Node name.
+ */
String getName();
}
*/
package org.wamblee.system.graph;
+/**
+ * Visitor of a graph.
+ * @author Erik Brakkee.
+ *
+ */
public interface Visitor {
+ /**
+ * Visits a node. Called by {@link Graph#accept(Visitor)}.
+ * @param aNode Node to visit.
+ */
void visitNode(Node aNode);
+ /**
+ * Visits a node. Called by {@link Graph#accept(Visitor)}.
+ * @param aEdge Edge to visit.
+ */
void visitEdge(Edge aEdge);
}
import org.wamblee.system.graph.Node;
import org.wamblee.system.graph.Visitor;
+/**
+ * Applies restrictions on a graph by removing all edges that violate the restriction.
+ *
+ * @author Erik Brakkee.
+ *
+ */
public class ApplyRestrictionsVisitor implements Visitor {
private Graph _graph;
private InterfaceRestriction _restriction;
-
+
+ /**
+ * Constructs the visitor.
+ * @param aGraph Graph.
+ * @param aRestriction Restriction.
+ */
public ApplyRestrictionsVisitor(Graph aGraph, InterfaceRestriction aRestriction) {
_graph = aGraph;
_restriction = aRestriction;
import org.wamblee.system.graph.Visitor;
/**
- * Visitor that checks externally provided
- * <ul>
- * <li>
- * </ul>
+ * Visitor that checks whether all externally provided interfaces are actually provided
+ * by any of the internal components.
*
* @author Erik Brakkee
*
public class CheckExternallyProvidedVisitor implements Visitor {
private Graph _graph;
-
+
+ /**
+ * Constructs the visitor.
+ * @param aGraph Component graph.
+ */
public CheckExternallyProvidedVisitor(Graph aGraph) {
_graph = aGraph;
}
import org.wamblee.system.graph.Visitor;
/**
- * Visitor that checks externally required services:
- * <ul>
- * <li>
- * </ul>
- *
+ * Visitor that checks whether all required external interfaces of the container
+ * are provided.
* @author Erik Brakkee
*
*/
import org.wamblee.system.graph.Node;
import org.wamblee.system.graph.Visitor;
+/**
+ * Checks whether the given component graph can be started in component
+ * order without any missing dependencies.
+ * @author Erik Brakkee
+ *
+ */
public class CheckStartupDependenciesVisitor implements Visitor {
private Graph _graph;
private List<Node> _available;
-
+
+ /**
+ * Constructs the visitor.
+ * @param aGraph Graph.
+ */
public CheckStartupDependenciesVisitor(Graph aGraph) {
_graph = aGraph;
_available = new ArrayList<Node>();
// TODO info superfluous required interfaces
// TODO check optional external required but mandatory internal.
+/**
+ * Represents a component graph and provides the bridge from the
+ * component model to a graph model. The graph model is easier
+ * to work with to implement specific actions and validations than
+ * the component model.
+ */
public class ComponentGraph extends Graph {
private CompositeInterfaceRestriction _restriction;
+ /**
+ * Constructs an empty component graph.
+ */
public ComponentGraph() {
_restriction = new CompositeInterfaceRestriction();
}
+ /**
+ * Adds a restriction that must be satisfied by the component model.
+ * @param aRestriction Restriction.
+ */
public void addRestriction(InterfaceRestriction aRestriction) {
_restriction.add(aRestriction);
}
+ /**
+ * Adds an externally required interface of a container.
+ * This should be called before any components of the container are
+ * added.
+ * @param aInterface Required interface.
+ */
public void addRequiredInterface(RequiredInterface aInterface) {
addNode(new ExternalRequiredInterfaceNode(aInterface));
}
+ /**
+ * Adds an externally provided interface of a container.
+ * This should be called after all components of the container have been added.
+ * @param aInterface Provided interface.
+ */
public void addProvidedInterface(ProvidedInterface aInterface) {
addNode(new ExternalProvidedInterfaceNode(aInterface));
}
+ /**
+ * Validates the component graph.
+ */
public void validate() {
extend(new RequiredProvidedEdgeFactory());
accept(new ApplyRestrictionsVisitor(this, _restriction));
accept(new CheckStartupDependenciesVisitor(this));
}
+ /**
+ * Links provided and required interfaces together in the component
+ * model based on the graph model.
+ */
public void link() {
accept(new LinkVisitor());
}
return result;
}
+ /**
+ * Adds a component by adding required interfaces, components, and
+ * provided interfaces.
+ * @param aComponent Component to add.
+ */
public void addComponent(Component aComponent) {
// Add required interfaces.
Node compNode = new ComponentNode(aComponent);
import org.wamblee.system.core.Component;
import org.wamblee.system.graph.Node;
+/**
+ * Represents a component node.
+ * @author Erik Brakkee.
+ *
+ */
public class ComponentNode implements Node {
private Component<?> _component;
import org.wamblee.system.core.ProvidedInterface;
import org.wamblee.system.graph.Node;
+/**
+ * Represents an external provided interface of a container.
+ * @author Erik Brakkee
+ *
+ */
public class ExternalProvidedInterfaceNode implements Node {
private ProvidedInterface _provided;
import org.wamblee.system.core.RequiredInterface;
import org.wamblee.system.graph.Node;
+/**
+ * Represents an externally required interface of a container.
+ * @author Erik Brakkee
+ *
+ */
public class ExternalRequiredInterfaceNode implements Node {
private RequiredInterface _required;
* Visitor that creates links between required and provided interfaces as
* described by the edges in the graph.
*
+ * Specically it links together (1) required and provided interfaces of internal component
+ * of a container and (2) the providers of externally required interfaces and internal required
+ * interfaces.
+ *
* @author Erik Brakkee
*
*/
import org.wamblee.system.core.ProvidedInterface;
import org.wamblee.system.graph.Node;
+/**
+ * Provided interface node.
+ * @author Erik Brakkee
+ */
public class ProvidedInterfaceNode implements Node {
private Component _component;
import org.wamblee.system.core.RequiredInterface;
import org.wamblee.system.graph.Node;
+/**
+ * Required interface node.
+ * @author Erik Brakkee
+ *
+ */
public class RequiredInterfaceNode implements Node {
private Component _component;
import org.wamblee.system.graph.Node;
/**
- * Factory that creates links between required and provided interfaces.
+ * Factory that creates edges between required and provided interfaces.
+ * Speciflcally it creates:
+ * <ul>
+ * <li> Edges between provided and required interfaces of a container. </li>
+ * <li> Edges between required and externally required interfaces </li>
+ * <li> Edges between externally provided and provided interfaces.
+ * </ul>
*
* @author Erik Brakkee
*