(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.container.CompositeInterfaceRestriction;
23 import org.wamblee.system.container.InterfaceRestriction;
24 import org.wamblee.system.core.Component;
25 import org.wamblee.system.core.ProvidedInterface;
26 import org.wamblee.system.core.RequiredInterface;
27 import org.wamblee.system.graph.DefaultEdge;
28 import org.wamblee.system.graph.Edge;
29 import org.wamblee.system.graph.Graph;
30 import org.wamblee.system.graph.Node;
31
32 /**
33  * Represents a component graph and provides the bridge from the 
34  * component model to a graph model. The graph model is easier
35  * to work with to implement specific actions and validations than 
36  * the component model. 
37  */
38 public class ComponentGraph extends Graph {
39     
40     private CompositeInterfaceRestriction _restriction; 
41
42     /**
43      * Constructs an empty component graph. 
44      */
45     public ComponentGraph() {
46         _restriction = new CompositeInterfaceRestriction(); 
47     }
48     
49     /**
50      * Adds a restriction that must be satisfied by the component model. 
51      * @param aRestriction Restriction. 
52      */
53     public void addRestriction(InterfaceRestriction aRestriction) { 
54         _restriction.add(aRestriction);
55     }
56     
57     /**
58      * Adds an externally required interface of a container.  
59      * This should be called before any components of the container are
60      * added. 
61      * @param aComponent Component requiring the interface. 
62      * @param aInterface Required interface. 
63      */
64     public void addRequiredInterface(Component aComponent, RequiredInterface aInterface) { 
65         addNode(new ExternalRequiredInterfaceNode(aComponent, aInterface));
66     }
67     
68     /**
69      * Adds an externally provided interface of a container.
70      * This should be called after all components of the container have been added.
71      * @param aComponent Component providing the interface.   
72      * @param aInterface Provided interface. 
73      */
74     public void addProvidedInterface(Component aComponent, 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         accept(new ApplyRestrictionsVisitor(this, _restriction));
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
92      * model based on the graph model. 
93      */
94     public void link() { 
95         accept(new LinkVisitor());
96     }
97     
98     /**
99      * Finds a list of mappings of external provided interface to internal provided interface. 
100      * 
101      * @return List of pairs of external to internal interface. 
102      */
103     public List<Pair<ProvidedInterface, ProvidedInterface>> findExternalProvidedInterfaceMapping() { 
104         List<Pair<ProvidedInterface, ProvidedInterface>> result = 
105             new ArrayList<Pair<ProvidedInterface,ProvidedInterface>>(); 
106         for (Edge edge: getEdges()) { 
107             if ( edge.getFrom() instanceof ExternalProvidedInterfaceNode  && 
108                     edge.getTo() instanceof ProvidedInterfaceNode ) { 
109                 result.add(new Pair<ProvidedInterface,ProvidedInterface>(
110                         ((ExternalProvidedInterfaceNode)edge.getFrom()).getProvided(), 
111                         ((ProvidedInterfaceNode)edge.getTo()).getProvided()
112                         )); 
113             }
114         }
115         return result; 
116     }
117     
118     /**
119      * Adds a component by adding required interfaces, components, and
120      * provided interfaces. 
121      * @param aComponent Component to add. 
122      */
123     public void addComponent(Component aComponent) { 
124         // Add required interfaces. 
125         Node compNode = new ComponentNode(aComponent);
126         List<Node> requiredNodes = new ArrayList<Node>();
127         for (RequiredInterface required: aComponent.getRequiredInterfaces()) { 
128             Node reqNode = new RequiredInterfaceNode(aComponent, required); 
129             addNode(reqNode);
130             requiredNodes.add(reqNode);
131         }
132         // Add the component
133         addNode(compNode);
134      
135         // Edges from component to required interface. 
136         for (Node reqNode: requiredNodes) { 
137             addEdge(new DefaultEdge(compNode, reqNode));
138         }
139         
140         // Add provided interfaces
141         List<Node> providedNodes = new ArrayList<Node>();
142         for (ProvidedInterface provided: aComponent.getProvidedInterfaces()) { 
143             Node provNode = new ProvidedInterfaceNode(aComponent, provided); 
144             addNode(provNode);
145             providedNodes.add(provNode);
146         }
147         
148         // Edges from provided interface to component
149         for (Node provNode: providedNodes) { 
150             addEdge(new DefaultEdge(provNode, compNode));
151         }
152     }
153 }