b41c41c81445d277165fed2eb7f44414b224d944
[utils] /
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 boolean _isLinked; 
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.  
52      * This should be called before any components of the container are
53      * added. 
54      * @param aComponent Component requiring the interface. 
55      * @param aInterface Required interface. 
56      */
57     public void addRequiredInterface(Component aComponent, RequiredInterface aInterface) { 
58         addNode(new ExternalRequiredInterfaceNode(aComponent, aInterface));
59     }
60     
61     /**
62      * Adds an externally provided interface of a container.
63      * This should be called after all components of the container have been added.
64      * @param aComponent Component providing the interface.   
65      * @param aInterface Provided interface. 
66      */
67     public void addProvidedInterface(Component aComponent, ProvidedInterface aInterface) { 
68         addNode(new ExternalProvidedInterfaceNode(aComponent, aInterface));
69     }
70     
71     /**
72      * Validates the component graph. 
73      */
74     public void validate() { 
75         extend(new RequiredProvidedEdgeFactory());
76         applyFilter(_edgeFilter);
77         accept(new CheckRequiredProvidedMultiplicityVisitor(this));
78         accept(new CheckExternallyRequiredVisitor(this)); 
79         accept(new CheckExternallyProvidedVisitor(this));
80         accept(new CheckStartupDependenciesVisitor(this));
81     }
82     
83     /**
84      * Links provided and required interfaces together in the component
85      * model based on the graph model. 
86      */
87     public void link() {
88         if ( _isLinked ) { 
89             return; 
90         }
91         accept(new LinkVisitor());
92         _isLinked = true; 
93     }
94     
95     /**
96      * Finds a list of mappings of external provided interface to internal provided interface. 
97      * 
98      * @return List of pairs of external to internal interface. 
99      */
100     public List<Pair<ProvidedInterface, ProvidedInterface>> findExternalProvidedInterfaceMapping() { 
101         List<Pair<ProvidedInterface, ProvidedInterface>> result = 
102             new ArrayList<Pair<ProvidedInterface,ProvidedInterface>>(); 
103         for (Edge edge: getEdges()) { 
104             if ( edge.getFrom() instanceof ExternalProvidedInterfaceNode  && 
105                     edge.getTo() instanceof ProvidedInterfaceNode ) { 
106                 result.add(new Pair<ProvidedInterface,ProvidedInterface>(
107                         ((ExternalProvidedInterfaceNode)edge.getFrom()).getProvided(), 
108                         ((ProvidedInterfaceNode)edge.getTo()).getProvided()
109                         )); 
110             }
111         }
112         return result; 
113     }
114     
115     /**
116      * Adds a component by adding required interfaces, components, and
117      * provided interfaces. 
118      * @param aComponent Component to add. 
119      */
120     public void addComponent(Component<?> aComponent) { 
121         // Add required interfaces. 
122         Node compNode = new ComponentNode(aComponent);
123         List<Node> requiredNodes = new ArrayList<Node>();
124         for (RequiredInterface required: aComponent.getRequiredInterfaces()) { 
125             Node reqNode = new RequiredInterfaceNode(aComponent, required); 
126             addNode(reqNode);
127             requiredNodes.add(reqNode);
128         }
129         // Add the component
130         addNode(compNode);
131      
132         // Edges from component to required interface. 
133         for (Node reqNode: requiredNodes) { 
134             addEdge(new DefaultEdge(compNode, reqNode));
135         }
136         
137         // Add provided interfaces
138         List<Node> providedNodes = new ArrayList<Node>();
139         for (ProvidedInterface provided: aComponent.getProvidedInterfaces()) { 
140             Node provNode = new ProvidedInterfaceNode(aComponent, provided); 
141             addNode(provNode);
142             providedNodes.add(provNode);
143         }
144         
145         // Edges from provided interface to component
146         for (Node provNode: providedNodes) { 
147             addEdge(new DefaultEdge(provNode, compNode));
148         }
149     }
150
151     public void addEdgeFilter(CompositeEdgeFilter aEdgeFilter) {
152         _edgeFilter.add(aEdgeFilter);    
153     }
154 }