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