]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/Source/Prototype/Module.java
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@422 6f19259b...
[mirror_edk2.git] / Tools / Source / Prototype / Module.java
1 import java.util.*;
2
3 public class Module
4 {
5 Module()
6 {
7 }
8 Module(String n)
9 {
10 name=n;
11 }
12 String name;
13
14 public String name() { return name; }
15
16 public Set<LibClass> consumesLibClasses;
17
18 // The set of packages that this module depends upon.
19 Set<Package> packageDepends;
20 public Set<Package> packageDeps() { return packageDepends; }
21
22 public boolean autoBuild()
23 {
24 // This should be implemented in the derived class.
25 return true;
26 }
27
28 // Make sure that each class in this set of libclasses is declared in one
29 // of the packages that this module depends on.
30 public boolean validateLibClasses(Set<LibClass> classes)
31 {
32 for(LibClass lc : classes)
33 {
34 // Assume we will not find it.
35 boolean found = false;
36
37 for(Package p : packageDepends)
38 {
39 if(p.libClassDecls.contains(lc))
40 {
41 found=true;
42 break;
43 }
44 }
45 if(found == false)
46 {
47 // Error: This LibClass is not found in any of our Packages.
48 return false;
49 }
50 }
51 // Well, we never came up empty handed, so it looks good.
52 return true;
53 }
54
55 public Set<LibClass> libClassesProduced(Collection<LibInst> instances)
56 {
57 // given a set of lib instances, what is the set of lib classes produced?
58
59 Set<LibClass> classes = new HashSet<LibClass>();
60
61 for(LibInst li : instances)
62 {
63 classes.addAll(li.producesLibClasses);
64 }
65 return classes;
66 }
67
68 // Search the given set of lib instance to see if, among them, they
69 // produce the same LibClass more than once.
70 public Set<LibClass> duplicateLibClasses(Set<LibInst> libs)
71 {
72 // Return true iff each class produced is produced only once.
73
74 List<LibClass> classes = new LinkedList<LibClass>();
75 Set<LibClass> dups = new HashSet<LibClass>();
76
77 for(LibInst li : libs)
78 {
79 classes.addAll(li.producesLibClasses);
80 }
81
82 for(LibClass c : classes)
83 {
84 for(LibClass inner : classes)
85 {
86 if(c.equals(inner))
87 {
88 dups.add(c);
89 }
90 }
91 }
92 return dups;
93 }
94
95 public Set<LibInst> getProducers(LibClass lc, Set<LibInst> libs)
96 {
97 // Return the subset of the given libs that produce this LibClass.
98
99 Set<LibInst> producers = new HashSet<LibInst>();
100
101 for(LibInst li : libs)
102 {
103 if(li.producesLibClasses.contains(lc))
104 {
105 producers.add(li);
106 }
107 }
108 return producers;
109 }
110
111 //
112 // The central dependency relationship between library instances is as follows.
113 // A LibInst "A" depends upon LibInst "B" if, and only if, there exists a LibClass
114 // "C" such that A consumes C and B produces C. This is the partial order over which
115 // we construct a Directed Acyclic Graph (DAG). The DAG can be used to detect
116 // cycles in the depends relation (which are illegal) and it can be used to implement a
117 // topological sort which is a total ordering over LibInstances. This total order on
118 // lib instances is what is needed in order to call the constructors and destructors
119 // in the proper sequence.
120 //
121 public DAG<LibInst> makeDAG(Set<LibInst> libs)
122 {
123 DAG<LibInst> dag = new DAG<LibInst>();
124
125 if(duplicateLibClasses(libs).size()>0)
126 {
127 System.out.format("Error: The library instances implement at least one "
128 + "library class more than once.\n");
129 }
130
131 for(LibInst consumer : libs)
132 {
133 // Find all the producers for each LC that li consumes.
134 for(LibClass lc : consumer.consumesLibClasses )
135 {
136 Set<LibInst> producers = getProducers(lc, libs);
137 if(producers.isEmpty())
138 {
139 System.out.format("Error: Unmet dependency libclass:%s .", lc.name() );
140 return null;
141 }
142
143 // There is exactly one lib inst that produces this class.
144 LibInst producer = producers.iterator().next();
145
146 // Now we are ready to add the dependency to the dag. It will flag
147 // circular dependencies for us.
148 dag.add(consumer, producer);
149 }
150 }
151 return dag;
152 }
153
154 // As you evaluate each node in the graph (starting with the module node), you
155 // must call the constructors for all the child nodes before you call the
156 // constructor for the current node.
157 public List<LibInst> getConstructorOrder(Set<LibInst> libs)
158 {
159 List<LibInst> rev = new LinkedList<LibInst>();
160
161 for(LibInst li : getDestructorOrder(libs))
162 rev.add(0, li);
163
164 return rev;
165 }
166
167 // The destructor order is exactly the reverese of the constructor order.
168 // As you evaluate each node in the graph (starting with the module node), you
169 // must call the destructor for the all the parent nodes before calling the
170 // destructors for the current node, and then call the destructors for all the
171 // child nodes.
172 public List<LibInst> getDestructorOrder(Set<LibInst> libs)
173 {
174 DAG<LibInst> dag = makeDAG(libs);
175
176 return dag.sort();
177 }
178 }