(no commit message)
[utils] / system / general / src / main / java / org / wamblee / system / graph / component / ComponentGraph.java
1 /*
2  * Copyright 2005-2010 the original author or authors.
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  * 
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  * 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.wamblee.system.graph.component;
17
18 import org.wamblee.general.Pair;
19
20 import org.wamblee.system.core.Component;
21 import org.wamblee.system.core.ProvidedInterface;
22 import org.wamblee.system.core.RequiredInterface;
23 import org.wamblee.system.graph.CompositeEdgeFilter;
24 import org.wamblee.system.graph.DefaultEdge;
25 import org.wamblee.system.graph.Edge;
26 import org.wamblee.system.graph.Graph;
27 import org.wamblee.system.graph.Node;
28
29 import java.util.ArrayList;
30 import java.util.List;
31
32 /**
33  * Represents a component graph and provides the bridge from the component model
34  * to a graph model. The graph model is easier to work with to implement
35  * specific actions and validations than the component model.
36  */
37 public class ComponentGraph extends Graph {
38     private boolean isLinked;
39
40     private CompositeEdgeFilter edgeFilter;
41
42     /**
43      * Constructs an empty component graph.
44      */
45     public ComponentGraph() {
46         isLinked = false;
47         edgeFilter = new CompositeEdgeFilter();
48     }
49
50     /**
51      * Adds an externally required interface of a container. This should be
52      * called before any components of the container are added.
53      * 
54      * @param aComponent
55      *            Component requiring the interface.
56      * @param aInterface
57      *            Required interface.
58      */
59     public void addRequiredInterface(Component aComponent,
60         RequiredInterface aInterface) {
61         addNode(new ExternalRequiredInterfaceNode(aComponent, aInterface));
62     }
63
64     /**
65      * Adds an externally provided interface of a container. This should be
66      * called after all components of the container have been added.
67      * 
68      * @param aComponent
69      *            Component providing the interface.
70      * @param aInterface
71      *            Provided interface.
72      */
73     public void addProvidedInterface(Component aComponent,
74         ProvidedInterface aInterface) {
75         addNode(new ExternalProvidedInterfaceNode(aComponent, aInterface));
76     }
77
78     /**
79      * Validates the component graph.
80      */
81     public void validate() {
82         extend(new RequiredProvidedEdgeFactory());
83         applyFilter(edgeFilter);
84         accept(new CheckRequiredProvidedMultiplicityVisitor(this));
85         accept(new CheckExternallyRequiredVisitor(this));
86         accept(new CheckExternallyProvidedVisitor(this));
87         accept(new CheckStartupDependenciesVisitor(this));
88     }
89
90     /**
91      * Links provided and required interfaces together in the component model
92      * based on the graph model.
93      */
94     public void link() {
95         if (isLinked) {
96             return;
97         }
98
99         accept(new LinkVisitor());
100         isLinked = true;
101     }
102
103     /**
104      * Finds a list of mappings of external provided interface to internal
105      * provided interface.
106      * 
107      * @return List of pairs of external to internal interface.
108      */
109     public List<Pair<ProvidedInterface, ProvidedInterface>> findExternalProvidedInterfaceMapping() {
110         List<Pair<ProvidedInterface, ProvidedInterface>> result = new ArrayList<Pair<ProvidedInterface, ProvidedInterface>>();
111
112         for (Edge edge : getEdges()) {
113             if (edge.getFrom() instanceof ExternalProvidedInterfaceNode &&
114                 edge.getTo() instanceof ProvidedInterfaceNode) {
115                 result.add(new Pair<ProvidedInterface, ProvidedInterface>(
116                     ((ExternalProvidedInterfaceNode) edge.getFrom())
117                         .getProvided(), ((ProvidedInterfaceNode) edge.getTo())
118                         .getProvided()));
119             }
120         }
121
122         return result;
123     }
124
125     /**
126      * Adds a component by adding required interfaces, components, and provided
127      * interfaces.
128      * 
129      * @param aComponent
130      *            Component to add.
131      */
132     public void addComponent(Component<?> aComponent) {
133         // Add required interfaces.
134         Node compNode = new ComponentNode(aComponent);
135         List<Node> requiredNodes = new ArrayList<Node>();
136
137         for (RequiredInterface required : aComponent.getRequiredInterfaces()) {
138             Node reqNode = new RequiredInterfaceNode(aComponent, required);
139             addNode(reqNode);
140             requiredNodes.add(reqNode);
141         }
142
143         // Add the component
144         addNode(compNode);
145
146         // Edges from component to required interface.
147         for (Node reqNode : requiredNodes) {
148             addEdge(new DefaultEdge(compNode, reqNode));
149         }
150
151         // Add provided interfaces
152         List<Node> providedNodes = new ArrayList<Node>();
153
154         for (ProvidedInterface provided : aComponent.getProvidedInterfaces()) {
155             Node provNode = new ProvidedInterfaceNode(aComponent, provided);
156             addNode(provNode);
157             providedNodes.add(provNode);
158         }
159
160         // Edges from provided interface to component
161         for (Node provNode : providedNodes) {
162             addEdge(new DefaultEdge(provNode, compNode));
163         }
164     }
165
166     public void addEdgeFilter(CompositeEdgeFilter aEdgeFilter) {
167         edgeFilter.add(aEdgeFilter);
168     }
169 }