Added some new field to the far template.
[mirror_edk2.git] / Tools / Java / Source / GenBuild / org / tianocore / build / autogen / AutogenLibOrder.java
CommitLineData
878ddf1f 1/**@file\r
2 AutogenLibOrder class.\r
3\r
4 This class is to reorder library instance sequence according to library \r
5 dependence.\r
6 \r
7 Copyright (c) 2006, Intel Corporation\r
8 All rights reserved. This program and the accompanying materials\r
9 are licensed and made available under the terms and conditions of the BSD License\r
10 which accompanies this distribution. The full text of the license may be found at\r
11 http://opensource.org/licenses/bsd-license.php\r
12 \r
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15\r
16 **/\r
17package org.tianocore.build.autogen;\r
18\r
19import java.util.ArrayList;\r
20import java.util.HashMap;\r
21import java.util.List;\r
22import java.util.Map;\r
a29c47e0 23\r
878ddf1f 24import org.apache.xmlbeans.XmlObject;\r
61528a1b 25import org.tianocore.build.exception.AutoGenException;\r
878ddf1f 26import org.tianocore.build.global.GlobalData;\r
27import org.tianocore.build.global.SurfaceAreaQuery;\r
a29c47e0 28import org.tianocore.build.id.ModuleIdentification;\r
61528a1b 29import org.tianocore.common.exception.EdkException;\r
192a42b4 30import org.tianocore.common.logger.EdkLog;\r
878ddf1f 31/**\r
32 This class This class is to reorder library instance sequence according to\r
33 library dependence.\r
34**/\r
35public class AutogenLibOrder {\r
36 ///\r
37 /// The map of library class and its library instance.\r
38 ///\r
a29c47e0 39 private Map<String, ModuleIdentification> libClassMap = new HashMap<String, ModuleIdentification>();\r
878ddf1f 40\r
41 ///\r
a29c47e0 42 /// The map of library instance and its implemet libraryClass.\r
878ddf1f 43 ///\r
a29c47e0 44 private Map<ModuleIdentification, String[]> libInstanceMap = new HashMap<ModuleIdentification, String[]>();\r
878ddf1f 45\r
46 ///\r
47 /// List of library instance. It is String[3] list, String[0] is libraryName,\r
48 /// String[1] is libraryConstructor name, String[2] is libDestructor name.\r
49 ///\r
a29c47e0 50 private List<LibraryInstanceNode> libInstanceList = new ArrayList<LibraryInstanceNode>();\r
878ddf1f 51 \r
52 /**\r
53 Constructor function\r
54 \r
55 This function mainly initialize some member variable.\r
56 \r
57 @param libraryList List of the library instance.\r
58 @throws Exception\r
59 **/\r
61528a1b 60 AutogenLibOrder(ModuleIdentification[] libraryList, String arch) throws EdkException {\r
a29c47e0 61 LibraryInstanceNode libInstanceNode;\r
62 String[] libClassDeclList = null;\r
63 String[] libClassConsmList = null;\r
878ddf1f 64 \r
a29c47e0 65 for (int i = 0; i < libraryList.length; i++) {\r
878ddf1f 66 //\r
67 // Add libraryInstance in to libInstanceList.\r
a29c47e0 68 // \r
69 Map<String, XmlObject> libDoc = GlobalData.getDoc(libraryList[i], arch);\r
83fba802 70 SurfaceAreaQuery saq = new SurfaceAreaQuery(libDoc);\r
71 libInstanceNode = new LibraryInstanceNode (libraryList[i],saq.getLibConstructorName(), saq.getLibDestructorName());\r
a29c47e0 72 libInstanceList.add(libInstanceNode);\r
878ddf1f 73 \r
74 //\r
75 // Add library instance and consumed library class list to\r
76 // libInstanceMap.\r
77 //\r
83fba802 78 libClassConsmList = saq.getLibraryClasses(CommonDefinition.ALWAYSCONSUMED, arch);\r
878ddf1f 79 if (libClassConsmList != null) {\r
80 String[] classStr = new String[libClassConsmList.length];\r
81 for (int k = 0; k < libClassConsmList.length; k++) {\r
a29c47e0 82 classStr[k] = libClassConsmList[k];\r
878ddf1f 83 }\r
a29c47e0 84 if (this.libInstanceMap.containsKey(libraryList[i])) {\r
61528a1b 85 throw new AutoGenException(\r
a29c47e0 86 libraryList[i].getName()\r
61528a1b 87 + "-- this library instance already exists, please check the library instance list!");\r
878ddf1f 88 } else {\r
a29c47e0 89 this.libInstanceMap.put(libraryList[i], classStr);\r
878ddf1f 90 }\r
91 }\r
92\r
93 //\r
94 // Add library class and library instance map.\r
95 //\r
83fba802 96 libClassDeclList = saq.getLibraryClasses(CommonDefinition.ALWAYSPRODUCED, arch);\r
878ddf1f 97 if (libClassDeclList != null) {\r
98 for (int j = 0; j < libClassDeclList.length; j++) {\r
a29c47e0 99 if (this.libClassMap.containsKey(libClassDeclList[j])) {\r
192a42b4 100 EdkLog.log(EdkLog.EDK_ERROR,libClassDeclList[j]\r
878ddf1f 101 + " class is already implement by "\r
a29c47e0 102 + this.libClassMap.get(libClassDeclList[j]));\r
61528a1b 103 throw new AutoGenException("Library Class: " + libClassDeclList\r
391dbbb1 104 + " already has a library instance!");\r
878ddf1f 105 } else {\r
a29c47e0 106 this.libClassMap.put(libClassDeclList[j], libraryList[i]);\r
878ddf1f 107 }\r
108 }\r
109 }\r
878ddf1f 110 }\r
111\r
112 //\r
113 // Check is the library instance list meet the require;\r
114 //\r
cb4d97bd 115 //for (int s = 0; s < this.libInstanceList.size(); s++) {\r
116 // String[] libClass = this.libInstanceMap.get(this.libInstanceList\r
117 // .get(s));\r
118 // if (libClass != null) {\r
119 // for (int t = 0; t < libClass.length; t++) {\r
120 // if (this.libClassMap.get(libClass[t]) == null) {\r
878ddf1f 121 //\r
122 // Note: There exist a kind of module which depend on \r
123 // library class with no instance or whose instance will\r
124 // never be linked into the module. \r
125 // For this satuation, the module has the description of \r
126 // library class in MSA file but no description of \r
127 // corresponding library instance in MBD file. There \r
128 // will be a warnig message given here after a standard \r
129 // log way has been decided.\r
130 //\r
cb4d97bd 131 // }\r
132 // }\r
133 // }\r
134 //}\r
878ddf1f 135 }\r
136\r
137 /**\r
138 orderLibInstance\r
139 \r
140 This function reorder the library instance according the library class \r
141 dependency.\r
142 \r
143 @return List which content the ordered library instance.\r
144 **/\r
a29c47e0 145 List<ModuleIdentification> orderLibInstance() {\r
146 List<ModuleIdentification> orderList = new ArrayList<ModuleIdentification>();\r
878ddf1f 147 //\r
148 // Stack of node which track the library instance name ant its visiting\r
149 // flag.\r
150 //\r
151 List<Node> stackList = new ArrayList<Node>();\r
152 int stackSize = 0;\r
a29c47e0 153 ModuleIdentification libInstanceId = null;\r
878ddf1f 154 if (libInstanceList.size() < 0) {\r
155 return null;\r
156 }\r
157\r
158 //\r
159 // Reorder the library instance.\r
160 //\r
161 for (int i = 0; i < libInstanceList.size(); i++) {\r
162 //\r
163 // If library instance is already in the order list skip it.\r
164 //\r
a29c47e0 165 if (isInLibInstance(orderList, libInstanceList.get(i).libId)) {\r
878ddf1f 166 continue;\r
167 }\r
168 \r
a29c47e0 169 Node node = new Node(libInstanceList.get(i).libId, false);\r
878ddf1f 170 //\r
171 // Use stack to reorder library instance.\r
172 // Push node to stack.\r
173 //\r
174 stackList.add(node);\r
175 while (stackList.size() > 0) {\r
176 stackSize = stackList.size() - 1;\r
177 //\r
178 // Pop the first node in stack. If the node flag has been visited\r
179 // add this node to orderlist and remove it from stack.\r
180 //\r
181 if (stackList.get(stackSize).isVisit) {\r
182 if (!isInLibInstance(orderList,\r
a29c47e0 183 stackList.get(stackSize).nodeId)) {\r
184 orderList.add(stackList.get(stackSize).nodeId);\r
878ddf1f 185 stackList.remove(stackSize);\r
186 }\r
187 \r
188 } else {\r
189 //\r
190 // Get the node value and set visit flag as true.\r
191 //\r
192 stackList.get(stackList.size() - 1).isVisit = true;\r
193 String[] libClassList = this.libInstanceMap.get(stackList\r
a29c47e0 194 .get(stackSize).nodeId);\r
878ddf1f 195 //\r
196 // Push the node dependence library instance to the stack.\r
197 //\r
198 if (libClassList != null) {\r
199 for (int j = 0; j < libClassList.length; j++) {\r
a29c47e0 200 libInstanceId = this.libClassMap.get(libClassList[j]);\r
201 if (libInstanceId != null\r
202 && !isInLibInstance(orderList, libInstanceId)) {\r
878ddf1f 203 //\r
204 // If and only if the currently library instance\r
205 // is not in stack and it have constructor or \r
206 // destructor function, push this library \r
207 // instacne in stack.\r
208 //\r
209 if (!isInStackList(stackList, this.libClassMap\r
a29c47e0 210 .get(libClassList[j])) && isHaveConsDestructor(libInstanceId)) {\r
878ddf1f 211 stackList.add(new Node(this.libClassMap\r
212 .get(libClassList[j]), false));\r
213 }\r
214 }\r
215 }\r
216 }\r
217 }\r
218 }\r
219 }\r
220 return orderList;\r
221 }\r
222\r
223 /**\r
224 isInLibInstance\r
225 \r
226 This function check does the library instance already in the list.\r
227 \r
228 @param list List of the library instance.\r
229 @param instanceName Name of library instance.\r
230 @return "true" the library instance in list |\r
231 "false" the library instance is not in list.\r
232 **/\r
a29c47e0 233 private boolean isInLibInstance(List<ModuleIdentification> list, ModuleIdentification instanceId) {\r
878ddf1f 234 for (int i = 0; i < list.size(); i++) {\r
a29c47e0 235 \r
236 if (instanceId.equals(list.get(i))) {\r
878ddf1f 237 return true;\r
238 }\r
239 }\r
240 return false;\r
241 }\r
242\r
243 /**\r
244 isInStackList \r
245 \r
246 This function check if the node already in the stack.\r
247 \r
248 @param list Stack.\r
249 @param nodeName Name of node.\r
250 @return "true" if node have in stack |\r
251 "false" if node don't in stack.\r
252 **/ \r
a29c47e0 253 private boolean isInStackList(List<Node> list, ModuleIdentification instanceId) {\r
878ddf1f 254 for (int i = 0; i < list.size(); i++) {\r
a29c47e0 255 if (instanceId.equals(list.get(i).nodeId)) {\r
878ddf1f 256 return true;\r
257 }\r
258 }\r
259 return false;\r
260 }\r
261 \r
262 /**\r
263 isHaveConsDestructor\r
264 \r
265 This function check if the library have constructor or destructor \r
266 function.\r
267 \r
268 @param libName Name of library\r
269 @return "true" if library have constructor or desconstructor |\r
270 "false" if library don't have constructor \r
271 and desconstructor.\r
272 **/\r
a29c47e0 273 private boolean isHaveConsDestructor (ModuleIdentification libNode){\r
878ddf1f 274 for (int i = 0; i < libInstanceList.size(); i++){\r
a29c47e0 275 if (libInstanceList.get(i).libId.equals(libNode)){\r
276 if (libInstanceList.get(i).constructorName != null || libInstanceList.get(i).deconstructorName != null){\r
878ddf1f 277 return true;\r
278 }\r
279 }\r
280 }\r
281 return false;\r
282 }\r
283}\r
284\r
285/**\r
286 Node \r
287 \r
288 This class is used as stack node.\r
289 \r
290 **/\r
291class Node {\r
a29c47e0 292 ModuleIdentification nodeId;\r
878ddf1f 293\r
294 boolean isVisit;\r
295\r
a29c47e0 296 Node(ModuleIdentification nodeId, boolean isVisit) {\r
297 this.nodeId = nodeId;\r
878ddf1f 298 this.isVisit = false;\r
299 }\r
a29c47e0 300} \r
301/**\r
302 LibraryInstance Node \r
303 \r
304 This class is used to store LibrayInstance and it's deconstructor and constructor\r
305**/\r
306 \r
307class LibraryInstanceNode {\r
308 ModuleIdentification libId;\r
309 String deconstructorName;\r
310 String constructorName;\r
311 \r
312 LibraryInstanceNode (ModuleIdentification libId, String deconstructor, String constructor){\r
313 this.libId = libId;\r
314 this.deconstructorName = deconstructor;\r
315 this.constructorName = constructor;\r
316 }\r
317}\r