]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/Source/GenBuild/org/tianocore/build/global/OverrideProcess.java
1) Fix a bug for PCD autogen tools, see track#115 in PVCS: Module's PCD informtion...
[mirror_edk2.git] / Tools / Source / GenBuild / org / tianocore / build / global / OverrideProcess.java
CommitLineData
878ddf1f 1/** @file\r
2 OverrideProcess class.\r
3 \r
4 OverrideProcess class is used to override surface area information. \r
5\r
6Copyright (c) 2006, Intel Corporation\r
7All rights reserved. This program and the accompanying materials\r
8are licensed and made available under the terms and conditions of the BSD License\r
9which accompanies this distribution. The full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16package org.tianocore.build.global;\r
17\r
18import java.util.HashMap;\r
19import java.util.Map;\r
20\r
21import javax.xml.namespace.QName;\r
22\r
23import org.apache.tools.ant.BuildException;\r
24import org.apache.xmlbeans.XmlCursor;\r
25import org.apache.xmlbeans.XmlObject;\r
26import org.tianocore.BootModesDocument;\r
27import org.tianocore.BuildOptionsDocument;\r
28import org.tianocore.DataHubsDocument;\r
29import org.tianocore.EventsDocument;\r
30import org.tianocore.ExternsDocument;\r
31import org.tianocore.FormsetsDocument;\r
32import org.tianocore.GuidsDocument;\r
33import org.tianocore.HobsDocument;\r
34import org.tianocore.IncludesDocument;\r
35import org.tianocore.LibrariesDocument;\r
36import org.tianocore.LibraryClassDefinitionsDocument;\r
37import org.tianocore.MsaHeaderDocument;\r
38import org.tianocore.MsaLibHeaderDocument;\r
ad82307c 39import org.tianocore.PcdCodedDocument;\r
878ddf1f 40import org.tianocore.PPIsDocument;\r
41import org.tianocore.ProtocolsDocument;\r
42import org.tianocore.SourceFilesDocument;\r
43import org.tianocore.SystemTablesDocument;\r
44import org.tianocore.VariablesDocument;\r
45\r
46/**\r
47 This class is used to override surface area information. For example, MBD can\r
48 overried MSA, Platform can override all information of the module. \r
49 \r
50 <p>Override will take effect if two element satisfy one of following two condition: </p>\r
51 <ul>\r
52 <li>Element name and its attribute OverrideID equal each other. </li>\r
53 <li>Element is defined as exclusive which mean such element can be\r
54 only appeared in the surface area. </li>\r
55 </ul>\r
56 \r
57 <p>For example, here OutputDirectory element is exclusive: </p>\r
58 \r
59 <pre>\r
60 Low priority Xml Document fragment:\r
61 &lt;Libraries&gt;\r
62 &lt;Arch ArchType="IA32"&gt;\r
63 &lt;Library OverrideID="8888"&gt;EdkPeCoffLoaderLib&lt;/Library&gt;\r
64 &lt;Library OverrideID="8888"&gt;BasePeCoffLib&lt;/Library&gt;\r
65 &lt;/Arch&gt;\r
66 &lt;/Libraries&gt; \r
67 &lt;BuildOptions&gt;\r
68 &lt;OutputDirectory IntermediateDirectories="MODULE"/&gt;\r
69 &lt;Option&gt;CC_FLAGS = "/NOLOGO", "/C"&lt;/Option&gt;\r
70 &lt;BuildOptions&gt;\r
71 \r
72 High priority Xml Document fragment:\r
73 &lt;Libraries&gt;\r
74 &lt;Arch ArchType="IA32"&gt;\r
75 &lt;Library OverrideID="8888">Nt32PeCoffLoaderLib&lt;/Library&gt;\r
76 &lt;/Arch&gt;\r
77 &lt;/Libraries&gt;\r
78 &lt;BuildOptions&gt;\r
79 &lt;OutputDirectory IntermediateDirectories="UNIFIED"/&gt;\r
80 &lt;Option&gt;LIB_FLAGS = "/NOLOGO"&lt;/Option&gt;\r
81 &lt;BuildOptions&gt;\r
82 \r
83 The result is: \r
84 &lt;Libraries&gt;\r
85 &lt;Arch ArchType="IA32"&gt;\r
86 &lt;Library OverrideID="8888"&gt;Nt32PeCoffLoaderLib&lt;/Library&gt;\r
87 &lt;/Arch&gt;\r
88 &lt;/Libraries&gt;\r
89 &lt;BuildOptions&gt;\r
90 &lt;OutputDirectory IntermediateDirectories="UNIFIED"/&gt;\r
91 &lt;Option&gt;CC_FLAGS = "/NOLOGO", "/C"&lt;/Option&gt;\r
92 &lt;Option&gt;LIB_FLAGS = "/NOLOGO"&lt;/Option&gt;\r
93 &lt;BuildOptions&gt;\r
94 \r
95 </pre>\r
96 \r
97 <p>Note that using XmlBeans to walk through the whole XML document tree.</p> \r
98 \r
99 @since GenBuild 1.0\r
100 @see org.apache.xmlbeans.XmlBeans\r
101**/\r
102public class OverrideProcess {\r
103\r
104 ///\r
105 /// URI, the namespace of current XML schema\r
106 ///\r
107 public static String prefix = "http://www.TianoCore.org/2006/Edk2.0";\r
108\r
109 ///\r
110 /// list of top elements of surface area\r
111 ///\r
112 public static String[] topElements = { "LibraryClassDefinitions",\r
113 "SourceFiles", "Includes", "Libraries", "Protocols",\r
114 "Events", "Hobs", "PPIs", "Variables", "BootModes",\r
115 "SystemTables", "DataHubs", "Formsets", "Guids", "Externs",\r
ad82307c 116 "PcdCoded", "BuildOptions" };\r
878ddf1f 117\r
118 ///\r
119 /// list of exclusive elements\r
120 ///\r
121 public static String[] exclusiveElements = {"OutputDirectory"};\r
122 \r
123 /**\r
124 Recursively find out all elements specified with OverrideId attribute\r
125 and exclusive elements in current XML object. \r
126 \r
127 @param o curent parsing XML object\r
128 @param map Map to list elements specified OverrideID attribute\r
129 @param execlusiveMap Map to list exclusive elements appeared in current XMl object\r
130 @param level the depth in XML document tree\r
131 **/\r
132 private void listOverrideID(XmlObject o, Map<String,Object> map, Map<String,Object> execlusiveMap, int level) {\r
133 XmlCursor cursor = o.newCursor();\r
134 String name = cursor.getName().getLocalPart();\r
135 for (int i = 0 ; i < exclusiveElements.length; i++){\r
136 if (name.equalsIgnoreCase(exclusiveElements[i])){\r
137 execlusiveMap.put(exclusiveElements[i], cursor.getObject());\r
138 }\r
139 }\r
140 String overrideID = cursor.getAttributeText(new QName("OverrideID"));\r
141 if (overrideID != null) {\r
142 map.put(name + ":" + overrideID, cursor.getObject());\r
143 }\r
144 if (cursor.toFirstChild()) {\r
145 do {\r
146 listOverrideID(cursor.getObject(), map, execlusiveMap, level + 1);\r
147 } while (cursor.toNextSibling());\r
148 }\r
149 }\r
150\r
151 /**\r
152 This function is used to prepare for overriding with changing data. \r
153 \r
154 @param map original surface area information \r
155 @return after normalize surface area information\r
156 **/\r
157 public synchronized static Map<String, XmlObject> deal(Map<String, XmlObject> map) {\r
158 Map<String, XmlObject> newMap = new HashMap<String, XmlObject>();\r
159 if (map.get("MsaHeader") != null) {\r
160 newMap.put("MsaHeader", ((MsaHeaderDocument) map.get("MsaHeader"))\r
161 .getMsaHeader());\r
162 }\r
163 if (map.get("MsaLibHeader") != null) {\r
164 newMap.put("MsaLibHeader", ((MsaLibHeaderDocument) map\r
165 .get("MsaLibHeader")).getMsaLibHeader());\r
166 }\r
167 if (map.get("LibraryClassDefinitions") != null) {\r
168 newMap.put("LibraryClassDefinitions",\r
169 ((LibraryClassDefinitionsDocument) map\r
170 .get("LibraryClassDefinitions"))\r
171 .getLibraryClassDefinitions());\r
172 }\r
173 if (map.get("SourceFiles") != null) {\r
174 newMap.put("SourceFiles", ((SourceFilesDocument) map\r
175 .get("SourceFiles")).getSourceFiles());\r
176 }\r
177 if (map.get("Includes") != null) {\r
178 newMap.put("Includes", ((IncludesDocument) map.get("Includes"))\r
179 .getIncludes());\r
180 }\r
181 if (map.get("Libraries") != null) {\r
182 newMap.put("Libraries", ((LibrariesDocument) map.get("Libraries"))\r
183 .getLibraries());\r
184 }\r
185 if (map.get("Protocols") != null) {\r
186 newMap.put("Protocols", ((ProtocolsDocument) map.get("Protocols"))\r
187 .getProtocols());\r
188 }\r
189 if (map.get("Events") != null) {\r
190 newMap.put("Events", ((EventsDocument) map.get("Events"))\r
191 .getEvents());\r
192 }\r
193 if (map.get("Hobs") != null) {\r
194 newMap.put("Hobs", ((HobsDocument) map.get("Hobs")).getHobs());\r
195 }\r
196 if (map.get("PPIs") != null) {\r
197 newMap.put("PPIs", ((PPIsDocument) map.get("PPIs")).getPPIs());\r
198 }\r
199 if (map.get("Variables") != null) {\r
200 newMap.put("Variables", ((VariablesDocument) map.get("Variables"))\r
201 .getVariables());\r
202 }\r
203 if (map.get("BootModes") != null) {\r
204 newMap.put("BootModes", ((BootModesDocument) map.get("BootModes"))\r
205 .getBootModes());\r
206 }\r
207 if (map.get("SystemTables") != null) {\r
208 newMap.put("SystemTables", ((SystemTablesDocument) map\r
209 .get("SystemTables")).getSystemTables());\r
210 }\r
211 if (map.get("DataHubs") != null) {\r
212 newMap.put("DataHubs", ((DataHubsDocument) map.get("DataHubs"))\r
213 .getDataHubs());\r
214 }\r
215 if (map.get("Formsets") != null) {\r
216 newMap.put("Formsets", ((FormsetsDocument) map.get("Formsets"))\r
217 .getFormsets());\r
218 }\r
219 if (map.get("Guids") != null) {\r
220 newMap.put("Guids", ((GuidsDocument) map.get("Guids")).getGuids());\r
221 }\r
222 if (map.get("Externs") != null) {\r
223 newMap.put("Externs", ((ExternsDocument) map.get("Externs"))\r
224 .getExterns());\r
225 }\r
ad82307c 226 if (map.get("PcdCoded") != null) {\r
227 newMap.put("PcdCoded", ((PcdCodedDocument) map.get("PcdCoded")).getPcdCoded());\r
878ddf1f 228 }\r
229 if (map.get("BuildOptions") != null) {\r
230 newMap.put("BuildOptions", ((BuildOptionsDocument) map\r
231 .get("BuildOptions")).getBuildOptions());\r
232 }\r
233 return newMap;\r
234 }\r
235\r
236 /**\r
237 Recursively remove all subelement in Xml Object l (with low priority) \r
238 based on OverrideID or exclusive elements. \r
239 \r
240 @param l the XML object to process\r
241 @param map list of elements with OverrideID in high priority XML object\r
242 @param execusiveMap list of exclusive elements in high priority XML object\r
243 **/\r
244 private void cut(XmlCursor l, Map map, Map execusiveMap) {\r
245 String name = l.getName().getLocalPart();\r
246 if (execusiveMap.containsKey(name)){\r
247 l.removeXml();\r
248 return;\r
249 }\r
250 String overrideID = l.getAttributeText(new QName("OverrideID"));\r
251 if (overrideID != null) {\r
252 if (map.containsKey(name + ":" + overrideID)) {\r
253 l.removeXml();\r
254 return;\r
255 }\r
256 }\r
257 if (l.toFirstChild()) {\r
258 do {\r
259 cut(l, map, execusiveMap);\r
260 } while (l.toNextSibling());\r
261 }\r
262 }\r
263\r
264 private XmlObject cloneXmlObject(XmlObject object, boolean deep) throws BuildException {\r
265 XmlObject result = null;\r
266 try {\r
267 result = XmlObject.Factory.parse(object.getDomNode()\r
268 .cloneNode(deep));\r
269 } catch (Exception ex) {\r
270 throw new BuildException(ex.getMessage());\r
271 }\r
272 return result;\r
273 }\r
274\r
275 /**\r
276 Process every item list in h and l.\r
277 \r
278 @param h surface area info with high priority\r
279 @param l surface area info with low priority\r
280 @return surface area after override\r
281 **/\r
282 public Map<String, XmlObject> override(Map<String, XmlObject> h,\r
283 Map<String, XmlObject> l) {\r
284 Map<String, XmlObject> result = new HashMap<String, XmlObject>();\r
285 result.put("MsaHeader", override(l.get("MsaHeader"), null));\r
286 result.put("MsaLibHeader", override(l.get("MsaLibHeader"), null));\r
287 for (int i = 0; i < topElements.length; i++) {\r
288 result.put(topElements[i], override(h.get(topElements[i]), l\r
289 .get(topElements[i])));\r
290 }\r
291 return result;\r
292 }\r
293\r
294 /**\r
295 Recursively override two Xml Objects.\r
296 \r
297 @param h Xml Object info with high priority\r
298 @param l Xml Object info with low priority\r
299 @return Xml Object after area\r
300 **/\r
301 public XmlObject override(XmlObject h, XmlObject l) {\r
302 if (l == null && h == null) {\r
303 return null;\r
304 }\r
305 if (h == null) {\r
306 return cloneXmlObject(l, true);\r
307 }\r
308 if (l == null) {\r
309 return cloneXmlObject(h, true);\r
310 }\r
311 XmlCursor hc = h.newCursor();\r
312 if (h.getClass() != l.getClass()) {\r
313 System.out\r
314 .println("Error: Two XmlObject does not with compliant format.");\r
315 return null;\r
316 }\r
317 if (!hc.toFirstChild()) {\r
318 return cloneXmlObject(l, true);\r
319 }\r
320\r
321 XmlCursor result = cloneXmlObject(h, true).newCursor();\r
322 XmlCursor lcursor = cloneXmlObject(l, true).newCursor();\r
323 result.push();\r
324 result.toNextToken();\r
325 result.insertNamespace("", prefix);\r
326 result.toFirstChild();\r
327 //\r
328 // found out all element specified a OverrideID\r
329 //\r
330 Map<String,Object> hmap = new HashMap<String,Object>();\r
331 Map<String,Object> execlusiveMap = new HashMap<String,Object>();\r
332 listOverrideID(h, hmap, execlusiveMap, 0);\r
333 lcursor.toNextToken();\r
334 lcursor.push();\r
335 //\r
336 // for every direct subelement of l, cut all element satisfied with\r
337 // override rule\r
338 //\r
339 if (lcursor.toFirstChild()) {\r
340 do {\r
341 cut(lcursor, hmap, execlusiveMap);\r
342 } while (lcursor.toNextSibling());\r
343 }\r
344 lcursor.pop();\r
345 if (lcursor.toFirstChild()) {\r
346 do {\r
347 lcursor.copyXml(result);\r
348 result.insertChars("\n");\r
349 } while (lcursor.toNextSibling());\r
350 }\r
351 result.pop();\r
352 return result.getObject();\r
353 }\r
354}