]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/Source/FrameworkWizard/src/org/tianocore/frameworkwizard/platform/ui/global/GlobalData.java
Added all header files in the packages's include directory into spd files.
[mirror_edk2.git] / Tools / Source / FrameworkWizard / src / org / tianocore / frameworkwizard / platform / ui / global / GlobalData.java
CommitLineData
a13899c5 1/** @file\r
2 GlobalData class. \r
3 \r
4 GlobalData provide initializing, instoring, querying and update global data.\r
5 It is a bridge to intercommunicate between multiple component, such as AutoGen,\r
6 PCD and so on. \r
7 \r
8Copyright (c) 2006, Intel Corporation\r
9All rights reserved. This program and the accompanying materials\r
10are licensed and made available under the terms and conditions of the BSD License\r
11which accompanies this distribution. The full text of the license may be found at\r
12http://opensource.org/licenses/bsd-license.php\r
13\r
14THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
15WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
16**/\r
17package org.tianocore.frameworkwizard.platform.ui.global;\r
18\r
19import org.apache.xmlbeans.XmlObject;\r
20import org.tianocore.DbPathAndFilename;\r
21import org.tianocore.FrameworkDatabaseDocument;\r
22import org.tianocore.ModuleSurfaceAreaDocument;\r
23import org.tianocore.ModuleSurfaceAreaDocument.ModuleSurfaceArea;\r
24import org.tianocore.frameworkwizard.platform.ui.id.FpdModuleIdentification;\r
25import org.tianocore.frameworkwizard.platform.ui.id.ModuleIdentification;\r
26import org.tianocore.frameworkwizard.platform.ui.id.PackageIdentification;\r
27import org.tianocore.frameworkwizard.platform.ui.id.PlatformIdentification;\r
28\r
29import java.io.File;\r
30import java.util.Comparator;\r
31import java.util.HashMap;\r
32import java.util.HashSet;\r
33import java.util.Iterator;\r
a13899c5 34import java.util.List;\r
35import java.util.Map;\r
36import java.util.Set;\r
a13899c5 37import java.util.logging.Logger;\r
a13899c5 38\r
39/**\r
40 GlobalData provide initializing, instoring, querying and update global data.\r
41 It is a bridge to intercommunicate between multiple component, such as AutoGen,\r
42 PCD and so on. \r
43 \r
44 <p>Note that all global information are initialized incrementally. All data will \r
45 parse and record only of necessary during build time. </p>\r
46 \r
47 @since GenBuild 1.0\r
48**/\r
49public class GlobalData {\r
50\r
51\r
52 public static Logger log = Logger.getAnonymousLogger();\r
53 public static KeyComparator comparator = new KeyComparator();\r
54 ///\r
55 /// Record current WORKSPACE Directory\r
56 ///\r
57 private static String workspaceDir = "";\r
58 \r
59 ///\r
60 /// Be used to ensure Global data will be initialized only once.\r
61 ///\r
62 private static boolean globalFlag = false;\r
63 \r
64 ///\r
65 /// Framework Database information: package list and platform list\r
66 ///\r
67 private static Set<PackageIdentification> packageList = new HashSet<PackageIdentification>(); \r
68\r
69 private static Set<PlatformIdentification> platformList = new HashSet<PlatformIdentification>();\r
70\r
71 ///\r
72 /// Every detail SPD informations: Module list, Library class definition,\r
73 /// Package header file, GUID/PPI/Protocol definitions\r
74 ///\r
75 private static final Map<PackageIdentification, Spd> spdTable = new HashMap<PackageIdentification, Spd>();\r
76\r
77 ///\r
78 /// Build informations are divided into three parts:\r
79 /// 1. From MSA 2. From FPD 3. From FPD' ModuleSA\r
80 ///\r
81 private static Map<ModuleIdentification, Map<String, XmlObject>> nativeMsa = new HashMap<ModuleIdentification, Map<String, XmlObject>>();\r
82\r
83 private static Map<FpdModuleIdentification, Map<String, XmlObject>> fpdModuleSA= new HashMap<FpdModuleIdentification, Map<String, XmlObject>>();\r
84\r
85 private static XmlObject fpdBuildOptions;\r
86\r
87 private static XmlObject fpdDynamicPcds;\r
88 \r
89 ///\r
90 /// Parsed modules list\r
91 ///\r
92 private static Map<FpdModuleIdentification, Map<String, XmlObject>> parsedModules = new HashMap<FpdModuleIdentification, Map<String, XmlObject>>();\r
93 \r
94 ///\r
95 /// built modules list with ARCH, TARGET, TOOLCHAIN\r
96 ///\r
97 private static Set<FpdModuleIdentification> builtModules = new HashSet<FpdModuleIdentification>();\r
98 \r
99 ///\r
100 /// PCD memory database stored all PCD information which collected from FPD,MSA and SPD.\r
101 ///\r
102// private static final MemoryDatabaseManager pcdDbManager = new MemoryDatabaseManager();\r
103\r
104 ///\r
105 /// build target + tool chain family/tag name + arch + command types + command options\r
106 ///\r
107 private static Map<String, Object> toolChainOptions;\r
108 private static Map<String, Object> toolChainFamilyOptions;\r
109 private static Map<String, String> toolChainDefinitions;\r
a13899c5 110 ///\r
111 ///\r
112 ///\r
113 private static Set<String> targets;\r
114 ///\r
115 ///\r
116 ///\r
117 private static Set<String> toolChainFamilies;\r
118 ///\r
119 ///\r
120 ///\r
121 private static Set<String> toolChains;\r
122 ///\r
123 /// keep track which toolchain family a toolchain tag belongs to\r
124 ///\r
125 private static Map<String, Set<String>> toolChainFamilyMap;\r
126 private static Map<String, Set<String>> toolChainCommandMap;\r
127 \r
128 ///\r
129 /// list of Arch: EBC, ARM, IA32, X64, IPF, PPC\r
130 ///\r
131 private static Set<String> archs;\r
132\r
133 ///\r
134 /// list of Command Type: CC, LIB, LINK, ASL, ASM, ASMLINK, PP\r
135 ///\r
136 private static Set<String> commandTypes;\r
137 \r
138 /**\r
139 Parse framework database (DB) and all SPD files listed in DB to initialize\r
140 the environment for next build. This method will only be executed only once\r
141 in the whole build process. \r
142 \r
143 @param workspaceDatabaseFile the file name of framework database\r
144 @param workspaceDir current workspace directory path\r
145 @throws Exception\r
146 Framework Dababase or SPD or MSA file is not valid\r
147 **/\r
148 public synchronized static void initInfo(String workspaceDatabaseFile, String workspaceDir) throws Exception {\r
149 //\r
150 // ensure this method will be revoked only once\r
151 //\r
152 if (globalFlag) {\r
153 return;\r
154 }\r
155 globalFlag = true;\r
156 \r
157 //\r
158 // Backup workspace directory. It will be used by other method\r
159 //\r
160 GlobalData.workspaceDir = workspaceDir.replaceAll("(\\\\)", "/");\r
161 File dbFile = new File(workspaceDir + File.separatorChar + workspaceDatabaseFile);\r
162 try {\r
163 FrameworkDatabaseDocument db = (FrameworkDatabaseDocument) XmlObject.Factory.parse(dbFile);\r
164 //\r
165 // validate FrameworkDatabaseFile\r
166 //\r
167// if (! db.validate()) {\r
168// throw new Exception("Framework Database file [" + dbFile.getPath() + "] is invalid.");\r
169// }\r
170 //\r
171 // Get package list\r
172 //\r
173 List<DbPathAndFilename> packages = db.getFrameworkDatabase().getPackageList().getFilenameList();\r
174 \r
175 Iterator iter = packages.iterator();\r
176 while (iter.hasNext()) {\r
177 DbPathAndFilename dbPath = (DbPathAndFilename)iter.next();\r
178 String fileName = dbPath.getStringValue();\r
179 Spd spd = new Spd(new File(workspaceDir + File.separatorChar + fileName));\r
180 packageList.add(spd.getPackageId());\r
181 spdTable.put(spd.getPackageId(), spd);\r
182 }\r
183\r
184 \r
185 } catch (Exception e) {\r
186 e.printStackTrace();\r
187 throw new Exception("Parse workspace Database [" + dbFile.getPath() + "] Error.\n" + e.getMessage());\r
188 }\r
189 }\r
190 \r
191 /**\r
192 Get the current WORKSPACE Directory. \r
193 \r
194 @return current workspace directory\r
195 **/\r
196 public synchronized static String getWorkspacePath() {\r
197 return workspaceDir;\r
198 }\r
199\r
200\r
201 /**\r
202 Get the MSA file name with absolute path\r
203 */\r
204 public synchronized static File getMsaFile(ModuleIdentification moduleId) throws Exception {\r
205 File msaFile = null;\r
206 //\r
207 // TBD. Do only when package is null. \r
208 //\r
209 Iterator iter = packageList.iterator();\r
210 while (iter.hasNext()) {\r
211 PackageIdentification packageId = (PackageIdentification)iter.next();\r
212 Spd spd = spdTable.get(packageId);\r
213 msaFile = spd.getModuleFile(moduleId);\r
214 if (msaFile != null ) {\r
215 break ;\r
216 }\r
217 }\r
218 if (msaFile == null){\r
219 throw new Exception("Can't find Module [" + moduleId.getName() + "] in all packages. ");\r
220 }\r
221 else {\r
222 return msaFile;\r
223 }\r
224 }\r
225\r
226 public synchronized static PackageIdentification getPackageForModule(ModuleIdentification moduleId) {\r
227 //\r
228 // If package already defined in module\r
229 //\r
230 if (moduleId.getPackage() != null) {\r
231 return moduleId.getPackage();\r
232 }\r
233 \r
234 PackageIdentification packageId = null;\r
235 Iterator iter = packageList.iterator();\r
236 while (iter.hasNext()) {\r
237 packageId = (PackageIdentification)iter.next();\r
238 \r
239 Spd spd = spdTable.get(packageId);\r
240 if (spd.getModuleFile(moduleId) != null ) {\r
241 moduleId.setPackage(packageId);\r
242 break ;\r
243 }\r
244 }\r
245 if (packageId == null){\r
246 return null;\r
247 }\r
248 else {\r
249 return packageId;\r
250 }\r
251 }\r
252 \r
253 /**\r
254 Difference between build and parse: ToolChain and Target\r
255 **/\r
256 public synchronized static boolean isModuleBuilt(FpdModuleIdentification moduleId) {\r
257 return builtModules.contains(moduleId);\r
258 }\r
259 \r
260 public synchronized static void registerBuiltModule(FpdModuleIdentification fpdModuleId) {\r
261 builtModules.add(fpdModuleId);\r
262 }\r
263\r
264 \r
265 public synchronized static void registerFpdModuleSA(FpdModuleIdentification fpdModuleId, Map<String, XmlObject> doc) throws Exception{\r
266 Map<String, XmlObject> result = new HashMap<String, XmlObject>();\r
267 Set keySet = doc.keySet();\r
268 Iterator iter = keySet.iterator();\r
269 while (iter.hasNext()){\r
270 String key = (String)iter.next();\r
271 XmlObject item = cloneXmlObject(doc.get(key), true);\r
272 result.put(key, item);\r
273 }\r
274 fpdModuleSA.put(fpdModuleId, result);\r
275 }\r
276 \r
277 /**\r
278 Query overrided module surface area information. If current is Package\r
279 or Platform build, also include the information from FPD file. \r
280 \r
281 <p>Note that surface area parsing is incremental. That means the method will \r
282 only parse the MSA and MBD files if necessary. </p>\r
283 \r
284 @param moduleName the base name of the module\r
285 @return the overrided module surface area information\r
286 @throws Exception\r
287 MSA or MBD is not valid\r
288 **/\r
289 public synchronized static Map<String, XmlObject> getDoc(FpdModuleIdentification fpdModuleId) throws Exception {\r
290 if (parsedModules.containsKey(fpdModuleId)) {\r
291 return parsedModules.get(fpdModuleId);\r
292 }\r
293 Map<String, XmlObject> doc = new HashMap<String, XmlObject>();\r
294 ModuleIdentification moduleId = fpdModuleId.getModule();\r
295 //\r
296 // First part: get the MSA files info\r
297 //\r
298 doc = getNativeMsa(moduleId);\r
299 \r
300 //\r
301 // Second part: put build options\r
302 //\r
303 doc.put("BuildOptions", fpdBuildOptions);\r
304 \r
305 //\r
306 // Third part: get Module info from FPD, such as Library instances, PCDs\r
307 //\r
308 if (fpdModuleSA.containsKey(fpdModuleId)){\r
309 //\r
310 // merge module info in FPD to final Doc\r
311 // For Library Module, do nothing here\r
312 //\r
313 doc.putAll(fpdModuleSA.get(fpdModuleId));\r
314 }\r
315 parsedModules.put(fpdModuleId, doc);\r
316 return doc;\r
317 }\r
318\r
319 public synchronized static Map<String, XmlObject> getDoc(ModuleIdentification moduleId, String arch) throws Exception {\r
320 FpdModuleIdentification fpdModuleId = new FpdModuleIdentification(moduleId, arch);\r
321 return getDoc(fpdModuleId);\r
322 }\r
323 /**\r
324 Query the native MSA information with module base name. \r
325 \r
326 <p>Note that MSA parsing is incremental. That means the method will \r
327 only to parse the MSA files when never parsed before. </p>\r
328 \r
329 @param moduleName the base name of the module\r
330 @return the native MSA information\r
331 @throws Exception\r
332 MSA file is not valid\r
333 **/\r
334 public synchronized static Map<String, XmlObject> getNativeMsa(ModuleIdentification moduleId) throws Exception {\r
335 if (nativeMsa.containsKey(moduleId)) {\r
336 return nativeMsa.get(moduleId);\r
337 }\r
338 File msaFile = getMsaFile(moduleId);\r
339 Map<String, XmlObject> msaMap = getNativeMsa(msaFile);\r
340 nativeMsa.put(moduleId, msaMap);\r
341 return msaMap;\r
342 }\r
343 \r
344 public synchronized static Map<String, XmlObject> getNativeMsa(File msaFile) throws Exception {\r
345 if (! msaFile.exists()) {\r
346 throw new Exception("Surface Area file [" + msaFile.getPath() + "] can't found.");\r
347 }\r
348 try {\r
349 ModuleSurfaceAreaDocument doc = (ModuleSurfaceAreaDocument)XmlObject.Factory.parse(msaFile);\r
350 //\r
351 // Validate File if they accord with XML Schema\r
352 //\r
353// if ( ! doc.validate()){\r
354// throw new Exception("Module Surface Area file [" + msaFile.getPath() + "] is invalid.");\r
355// }\r
356 //\r
357 // parse MSA file\r
358 //\r
359 ModuleSurfaceArea msa= doc.getModuleSurfaceArea();\r
360 Map<String, XmlObject> msaMap = new HashMap<String, XmlObject>();\r
361 msaMap.put("ModuleSurfaceArea", msa);\r
362 msaMap.put("MsaHeader", cloneXmlObject(msa.getMsaHeader(), true));\r
363 msaMap.put("LibraryClassDefinitions", cloneXmlObject(msa.getLibraryClassDefinitions(), true));\r
364 msaMap.put("SourceFiles", cloneXmlObject(msa.getSourceFiles(), true));\r
365 msaMap.put("PackageDependencies", cloneXmlObject(msa.getPackageDependencies(), true));\r
366 msaMap.put("Protocols", cloneXmlObject(msa.getProtocols(), true));\r
367 msaMap.put("PPIs", cloneXmlObject(msa.getPPIs(), true));\r
368 msaMap.put("Guids", cloneXmlObject(msa.getGuids(), true));\r
369 msaMap.put("Externs", cloneXmlObject(msa.getExterns(), true));\r
370 return msaMap;\r
371 }\r
372 catch (Exception ex){\r
373 throw new Exception(ex.getMessage());\r
374 }\r
375 }\r
376 \r
377 public static Map<String, XmlObject> getFpdBuildOptions() {\r
378 Map<String, XmlObject> map = new HashMap<String, XmlObject>();\r
379 map.put("BuildOptions", fpdBuildOptions);\r
380 return map;\r
381 }\r
382 \r
383 public static void setFpdBuildOptions(XmlObject fpdBuildOptions) throws Exception{\r
384 GlobalData.fpdBuildOptions = cloneXmlObject(fpdBuildOptions, true);\r
385 }\r
386\r
387 public static XmlObject getFpdDynamicPcds() {\r
388 return fpdDynamicPcds;\r
389 }\r
390\r
391 public static void setFpdDynamicPcds(XmlObject fpdDynamicPcds) {\r
392 GlobalData.fpdDynamicPcds = fpdDynamicPcds;\r
393 }\r
394\r
395 //////////////////////////////////////////////\r
396 //////////////////////////////////////////////\r
397 \r
398 public static Set<ModuleIdentification> getModules(PackageIdentification packageId){\r
399 Spd spd = spdTable.get(packageId);\r
400 if (spd == null ) {\r
401 Set<ModuleIdentification> dummy = new HashSet<ModuleIdentification>();\r
402 return dummy;\r
403 }\r
404 else {\r
405 return spd.getModules();\r
406 }\r
407 }\r
408\r
a13899c5 409 public synchronized static PlatformIdentification getPlatform(String name) throws Exception {\r
410 Iterator iter = platformList.iterator();\r
411 while(iter.hasNext()){\r
412 PlatformIdentification platformId = (PlatformIdentification)iter.next();\r
413 if (platformId.getName().equalsIgnoreCase(name)) {\r
414 GlobalData.log.info("Platform: " + platformId + platformId.getFpdFile());\r
415 return platformId;\r
416 }\r
417 }\r
418 throw new Exception("Can't find platform [" + name + "] in current workspace. ");\r
419 }\r
420 \r
421 public synchronized static File getPackageFile(PackageIdentification packageId) throws Exception {\r
422 Iterator iter = packageList.iterator();\r
423 while(iter.hasNext()){\r
424 PackageIdentification packageItem = (PackageIdentification)iter.next();\r
425 if (packageItem.equals(packageId)) {\r
426 packageId.setName(packageItem.getName());\r
427 return packageItem.getSpdFile();\r
428 }\r
429 }\r
430 throw new Exception("Can't find " + packageId + " in current workspace. ");\r
431 }\r
432 \r
433 public synchronized static File getModuleFile(ModuleIdentification moduleId) throws Exception {\r
434 PackageIdentification packageId = getPackageForModule(moduleId);\r
435 moduleId.setPackage(packageId);\r
436 Spd spd = spdTable.get(packageId);\r
437 return spd.getModuleFile(moduleId);\r
438 }\r
439 //\r
440 // expanded by FrameworkWizard\r
441 //\r
442 public synchronized static XmlObject getModuleXmlObject(ModuleIdentification moduleId) throws Exception {\r
443 PackageIdentification packageId = getPackageForModule(moduleId);\r
444 moduleId.setPackage(packageId);\r
445 Spd spd = spdTable.get(packageId);\r
446 return spd.msaDocMap.get(moduleId);\r
447 }\r
448 \r
449 public synchronized static XmlObject getPackageXmlObject(PackageIdentification packageId) {\r
450 Spd spd = spdTable.get(packageId);\r
451 if (spd != null){\r
452 return spd.spdDocMap.get("PackageSurfaceArea");\r
453 }\r
454 return null;\r
455 }\r
456 \r
457 public synchronized static Set<PackageIdentification> getPackageList(){\r
458 return packageList;\r
459 }\r
460 ///// remove!!\r
461 private static XmlObject cloneXmlObject(XmlObject object, boolean deep) throws Exception {\r
462 if ( object == null) {\r
463 return null;\r
464 }\r
465 XmlObject result = null;\r
466 try {\r
467 result = XmlObject.Factory.parse(object.getDomNode()\r
468 .cloneNode(deep));\r
469 } catch (Exception ex) {\r
470 throw new Exception(ex.getMessage());\r
471 }\r
472 return result;\r
473 }\r
474\r
475 ////// Tool Chain Related, try to refine and put some logic process to ToolChainFactory\r
476 public static void setBuildToolChainFamilyOptions(Map<String, Object> map) {\r
477 toolChainFamilyOptions = map;\r
478 }\r
479\r
480 public static Map<String, Object> getToolChainFamilyOptions() {\r
481 return toolChainFamilyOptions;\r
482 }\r
483\r
484 public static void setBuildToolChainOptions(Map<String, Object> map) {\r
485 toolChainOptions = map;\r
486 }\r
487\r
488 public static Map<String, Object> getToolChainOptions() {\r
489 return toolChainOptions;\r
490 }\r
491\r
492 public static void setTargets(Set<String> targetSet) {\r
493 GlobalData.log.info("TargetSet: " + targetSet);\r
494 targets = targetSet;\r
495 }\r
496\r
497 public static String[] getTargets() {\r
498 return (String[])targets.toArray(new String[targets.size()]);\r
499 }\r
500\r
501 public static void setToolChains(Set<String> toolChainSet) {\r
502 toolChains = toolChainSet;\r
503 }\r
504\r
505 public static String[] getToolChains() {\r
506 String[] toolChainList = new String[toolChains.size()];\r
507 return (String[])toolChains.toArray(toolChainList);\r
508 }\r
509\r
510 public static void setToolChainFamilies(Set<String> toolChainFamilySet) {\r
511 toolChainFamilies = toolChainFamilySet;\r
512 }\r
513\r
514 public static void setToolChainFamiliyMap(Map<String, Set<String>> map) {\r
515 /*\r
516 Set<String> keys = map.keySet();\r
517 Iterator it = keys.iterator();\r
518 while (it.hasNext()) {\r
519 String toolchain = (String)it.next();\r
520 Set<String> familyMap = (Set<String>)map.get(toolchain);\r
521 Iterator fit = familyMap.iterator();\r
522 System.out.print(toolchain + ": ");\r
523 while (fit.hasNext()) {\r
524 System.out.print((String)fit.next() + " ");\r
525 }\r
526 System.out.println("");\r
527 }\r
528 */\r
529 toolChainFamilyMap = map;\r
530 }\r
531\r
532 public static String[] getToolChainFamilies() {\r
533 String[] toolChainFamilyList = new String[toolChainFamilies.size()];\r
534 return (String[])toolChainFamilies.toArray(toolChainFamilyList);\r
535 }\r
536\r
537 public static String[] getToolChainFamilies(String toolChain) {\r
538 Set<String> familySet = (Set<String>)toolChainFamilyMap.get(toolChain);\r
539 String[] toolChainFamilyList = new String[familySet.size()];\r
540 return (String[])familySet.toArray(toolChainFamilyList);\r
541 }\r
542\r
543 public static Set<String> getToolChainFamilySet(String toolChain) {\r
544 return (Set<String>)toolChainFamilyMap.get(toolChain);\r
545 }\r
546\r
547 public static void setArchs(Set<String> archSet) {\r
548 archs = archSet;\r
549 }\r
550\r
551 public static String[] getArchs() {\r
552 String[] archList = new String[archs.size()];\r
553 return (String[])archs.toArray(archList);\r
554 }\r
555 /*\r
556\r
557 */\r
558 public static void SetCommandTypes(Set<String> commandTypeSet) {\r
559 commandTypes = commandTypeSet;\r
560 }\r
561 /*\r
562\r
563 */\r
564 public static void SetCommandTypes(Map<String, Set<String>> commandTypeMap) {\r
565 toolChainCommandMap = commandTypeMap;\r
566 }\r
567 /*\r
568\r
569 */\r
570 public static String[] getCommandTypes() {\r
571 String[] commandList = new String[commandTypes.size()];\r
572 return (String[])commandTypes.toArray(commandList);\r
573 }\r
574 /*\r
575\r
576 */\r
577 public static String[] getCommandTypes(String toolChain) {\r
578 Set<String> commands = (Set<String>)toolChainCommandMap.get(toolChain);\r
579 if (commands == null) {\r
580 return new String[0];\r
581 }\r
582\r
583 String[] commandList = new String[commands.size()];\r
584 return (String[])commands.toArray(commandList);\r
585 }\r
a13899c5 586 /*\r
587\r
588 */\r
589 public static String getCommandSetting(String commandDescString) {\r
590 return (String)toolChainDefinitions.get(commandDescString);\r
591 }\r
a13899c5 592 /*\r
593\r
594 */\r
595 public static void setToolChainDefinitions(Map<String, String> def) {\r
596 toolChainDefinitions = def;\r
597 }\r
598\r
599 public static Map<String, String> getToolChainDefinitions() {\r
600 return toolChainDefinitions;\r
601 }\r
602\r
a13899c5 603}\r
604\r
605final class KeyComparator implements Comparator<String> {\r
606 public int compare(String x, String y) {\r
607 return x.compareToIgnoreCase(y);\r
608 }\r
609 \r
610}\r
611\r