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