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