(no commit message)
[utils] / system / general / src / main / java / org / wamblee / system / graph / component / ComponentGraph.java
1 /*
2  * Copyright 2008 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 java.util.ArrayList;
19 import java.util.List;
20
21 import org.wamblee.general.Pair;
22 import org.wamblee.system.core.Component;
23 import org.wamblee.system.core.ProvidedInterface;
24 import org.wamblee.system.core.RequiredInterface;
25 import org.wamblee.system.graph.CompositeEdgeFilter;
26 import org.wamblee.system.graph.DefaultEdge;
27 import org.wamblee.system.graph.Edge;
28 import org.wamblee.system.graph.Graph;
29 import org.wamblee.system.graph.Node;
30
31 /**
32  * Represents a component graph and provides the bridge from the 
33  * component model to a graph model. The graph model is easier
34  * to work with to implement specific actions and validations than 
35  * the component model. 
36  */
37 public class ComponentGraph extends Graph {
38     
39     private CompositeEdgeFilter _edgeFilter; 
40
41     /**
42      * Constructs an empty component graph. 
43      */
44     public ComponentGraph() {
45         _edgeFilter = new CompositeEdgeFilter(); 
46     }
47     
48     /**
49      * Adds an externally required interface of a container.  
50      * This should be called before any components of the container are
51      * added. 
52      * @param aComponent Component requiring the interface. 
53      * @param aInterface Required interface. 
54      */
55     public void addRequiredInterface(Component aComponent, RequiredInterface aInterface) { 
56         addNode(new ExternalRequiredInterfaceNode(aComponent, aInterface));
57     }
58     
59     /**
60      * Adds an externally provided interface of a container.
61      * This should be called after all components of the container have been added.
62      * @param aComponent Component providing the interface.   
63      * @param aInterface Provided interface. 
64      */
65     public void addProvidedInterface(Component aComponent, ProvidedInterface aInterface) { 
66         addNode(new ExternalProvidedInterfaceNode(aComponent, aInterface));
67     }
68     
69     /**
70      * Validates the component graph. 
71      */
72     public void validate() { 
73         extend(new RequiredProvidedEdgeFactory());
74         applyFilter(_edgeFilter);
75         accept(new CheckRequiredProvidedMultiplicityVisitor(this));
76         accept(new CheckExternallyRequiredVisitor(this)); 
77         accept(new CheckExternallyProvidedVisitor(this));
78         accept(new CheckStartupDependenciesVisitor(this));
79     }
80     
81     /**
82      * Links provided and required interfaces together in the component
83      * model based on the graph model. 
84      */
85     public void link() { 
86         accept(new LinkVisitor());
87     }
88     
89     /**
90      * Finds a list of mappings of external provided interface to internal provided interface. 
91      * 
92      * @return List of pairs of external to internal interface. 
93      */
94     public List<Pair<ProvidedInterface, ProvidedInterface>> findExternalProvidedInterfaceMapping() { 
95         List<Pair<ProvidedInterface, ProvidedInterface>> result = 
96             new ArrayList<Pair<ProvidedInterface,ProvidedInterface>>(); 
97         for (Edge edge: getEdges()) { 
98             if ( edge.getFrom() instanceof ExternalProvidedInterfaceNode  && 
99                     edge.getTo() instanceof ProvidedInterfaceNode ) { 
100                 result.add(new Pair<ProvidedInterface,ProvidedInterface>(
101                         ((ExternalProvidedInterfaceNode)edge.getFrom()).getProvided(), 
102                         ((ProvidedInterfaceNode)edge.getTo()).getProvided()
103                         )); 
104             }
105         }
106         return result; 
107     }
108     
109     /**
110      * Adds a component by adding required interfaces, components, and
111      * provided interfaces. 
112      * @param aComponent Component to add. 
113      */
114     public void addComponent(Component<?> aComponent) { 
115         // Add required interfaces. 
116         Node compNode = new ComponentNode(aComponent);
117         List<Node> requiredNodes = new ArrayList<Node>();
118         for (RequiredInterface required: aComponent.getRequiredInterfaces()) { 
119             Node reqNode = new RequiredInterfaceNode(aComponent, required); 
120             addNode(reqNode);
121             requiredNodes.add(reqNode);
122         }
123         // Add the component
124         addNode(compNode);
125      
126         // Edges from component to required interface. 
127         for (Node reqNode: requiredNodes) { 
128             addEdge(new DefaultEdge(compNode, reqNode));
129         }
130         
131         // Add provided interfaces
132         List<Node> providedNodes = new ArrayList<Node>();
133         for (ProvidedInterface provided: aComponent.getProvidedInterfaces()) { 
134             Node provNode = new ProvidedInterfaceNode(aComponent, provided); 
135             addNode(provNode);
136             providedNodes.add(provNode);
137         }
138         
139         // Edges from provided interface to component
140         for (Node provNode: providedNodes) { 
141             addEdge(new DefaultEdge(provNode, compNode));
142         }
143     }
144
145     public void addEdgeFilter(CompositeEdgeFilter aEdgeFilter) {
146         _edgeFilter.add(aEdgeFilter);    
147     }
148 }