ICU-3186 update the package name add LDMLUtilities

X-SVN-Rev: 16097
This commit is contained in:
Ram Viswanadha 2004-08-03 01:30:27 +00:00
parent 946f58dff5
commit 5be502279b
4 changed files with 2947 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,777 @@
/*
*******************************************************************************
* Copyright (C) 2003-2004, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
package com.ibm.icu.dev.tool.cldr;
/**
* @author ram
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
import java.io.*;
import java.util.*;
import java.io.PrintWriter;
import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
import java.util.Calendar;
//import java.util.Locale;
// DOM imports
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
// Needed JAXP classes
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
// SAX2 imports
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import com.ibm.icu.text.Normalizer;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.lang.UCharacter;
public class LDMLComparator {
/*
* This application will compare different locale data xml files
* conforming to localeElements.dtd and produces an xml file file
* in the format
*/
private static final short OPT_SUN_JDK = 0x001; /*2exp0*/
private static final short OPT_IBM_JDK = 0x002; /*2exp1*/
private static final short OPT_WINDOWS = 0x004; /*2exp2*/
private static final short OPT_HP_UX = 0x008; /*2exp3*/
private static final short OPT_SOLARIS = 0x010; /*2exp4*/
private static final short OPT_IBM_TOR = 0x020; /*2exp5*/
private static final short OPT_APPLE = 0x040; /*2exp6*/
private static final short OPT_ICU = 0x080; /*2exp7*/
private static final short OPT_OTHER = 0x100; /*2exp8*/
private static final short OPT_SOURCE = 0x200; /*2exp9*/
private static final short OPT_DEST = 0x400; /*2exp10*/
private static final short OPT_LINUX = 0x800; /*2exp11*/
private static final short OPT_AIX = 0x1000; /*2exp12*/
private static final short OPT_COMMON = 0x2000; /*2exp13*/
private static final short OPT_UNKNOWN = 0x4000; /*2exp15*/
private static final String COMMON = "common";
private static final String ICU = "icu";
private static final String IBM_TOR = "ibm_tor";
private static final String WINDOWS = "windows";
private static final String SUNJDK = "sunjdk";
private static final String IBMJDK = "ibmjdk";
private static final String HPUX = "hp";
private static final String APPLE = "apple";
private static final String SOLARIS = "solaris";
private static final String OPEN_OFFICE = "open_office";
private static final String AIX = "aix";
private static final String LINUX = "linux";
private static final String[] PLATFORM_PRINT_ORDER ={
COMMON,
ICU,
WINDOWS,
SUNJDK,
IBMJDK,
IBM_TOR,
APPLE,
SOLARIS,
OPEN_OFFICE,
AIX,
LINUX,
HPUX,
};
private static final String USER_OPTIONS[] = {
"-"+COMMON,
"-"+ICU,
"-"+IBM_TOR,
"-"+WINDOWS,
"-"+SUNJDK,
"-"+IBMJDK,
"-"+HPUX,
"-"+APPLE,
"-"+SOLARIS,
"-"+OPEN_OFFICE,
"-"+AIX,
"-"+LINUX,
"-s",
"-d",
};
public static void main(String[] args){
LDMLComparator comparator = new LDMLComparator();
comparator.processArgs(args);
}
Hashtable optionTable = new Hashtable();
private String sourceFolder = ".";
private String destFolder = ".";
private String localeStr;
private Calendar cal = Calendar.getInstance();
private Hashtable colorHash = new Hashtable();
private String goldFileName;
private String goldKey;
private int numPlatforms = 0;
private int serialNumber =0;
private TreeMap compareMap = new TreeMap();
private Hashtable doesNotExist = new Hashtable();
private Hashtable requested = new Hashtable();
private Hashtable deprecatedLanguageCodes = new Hashtable();
private Hashtable deprecatedCountryCodes = new Hashtable();
private String encoding = "UTF-8"; // default encoding
private class CompareElement{
String node;
String index;
String parentNode;
Hashtable platformData = new Hashtable();
}
LDMLComparator(){
//initialize the color hash
colorHash.put( COMMON, "#AD989D");
colorHash.put( ICU, "#CCFF00");
colorHash.put( IBM_TOR, "#FF7777");
colorHash.put( WINDOWS, "#98FB98");
colorHash.put( SUNJDK, "#FF6633");
colorHash.put( IBMJDK, "#CCFFFF");
colorHash.put( HPUX, "#FFE4B5");
colorHash.put( APPLE, "#FFBBBB");
colorHash.put( SOLARIS, "#CC9966");
colorHash.put( OPEN_OFFICE, "#FFFF33");
colorHash.put( AIX, "#EB97FE");
colorHash.put( LINUX, "#1191F1");
// TODO
//deprecatedLanguageCodes.put("sh", "what ever the new one is");
deprecatedLanguageCodes.put("iw", "he");
deprecatedLanguageCodes.put("in", "id");
deprecatedLanguageCodes.put("ji", "yi");
deprecatedLanguageCodes.put("jw", "jv"); // this does not even exist, JDK think jw is javanese!!
//country codes
deprecatedCountryCodes.put("TP", "TL");
deprecatedCountryCodes.put("ZR", "CD");
}
private void processArgs(String[] args){
short options = identifyOptions(args);
if ((args.length < 2) || ((options & OPT_UNKNOWN) != 0)) {
printUsage();
return;
}
boolean warning[] = new boolean[1];
warning[0] = false;
Enumeration enum = optionTable.keys();
try{
localeStr = goldFileName.substring(goldFileName.lastIndexOf(File.separatorChar)+1,goldFileName.indexOf('.'));
String fileName = destFolder+File.separator+localeStr+".html";
OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(fileName),encoding);
String curDir = System.getProperty("user.dir");
System.out.println("INFO: Creating file named: " + fileName +" in directory: " + curDir);
addToCompareMap(goldFileName, goldKey);
for(;enum.hasMoreElements();){
String key = (String)enum.nextElement();
String compFile = (String) optionTable.get(key);
addToCompareMap(compFile,key);
}
PrintWriter writer = new PrintWriter(os);
printHTML(writer, localeStr);
}catch(Exception e){
e.printStackTrace();
}
}
private void printUsage() {
System.err.println("Usage: XMLComparator [<option>:<gold>] filename1 [option] filename2 ... \n"+
" XMLComparator [-common:<gold>] filename [-icu] filename" +
" [-ibm_jdk] filename [-windows] filename" +
" [-hpux] filename [-solaris] filename" +
" [-ibm_tor] filename [-apple] filename" +
" [-sun_jdk] filename [-open_office] filename" +
" [-aix] filename [-linux] filename"
);
}
private short identifyOptions(String[] options) {
short result = 0;
for (int j = 0; j < options.length; j++) {
String option = options[j];
boolean isGold = false;
if (option.startsWith("-")) {
if(option.indexOf(":gold")>0){
option = option.substring(0,option.indexOf(":"));
isGold = true;
}
boolean optionRecognized = false;
for (short i = 0; i < USER_OPTIONS.length; i++) {
if (USER_OPTIONS[i].equals(option)) {
result |= (short)(1 << i);
optionRecognized = true;
if(USER_OPTIONS[i].equals("-s")){
sourceFolder = options[++j];
}else if(USER_OPTIONS[i].equals("-d")){
destFolder = options[++j];
}else{
if(!isGold){
optionTable.put(option.substring(1,option.length()),options[++j]);
}else{
goldFileName = options[++j];
goldKey = option.substring(1,option.length());
}
}
break;
}
}
if (!optionRecognized) {
result |= OPT_UNKNOWN;
}
}
}
return result;
}
private void printTableHeader(PrintWriter writer){
writer.print( " <tr>\n" +
" <th>N.</th>\n"+
" <th>ParentNode</th>\n"+
" <th>Name</th>\n"+
" <th>ID</th>\n");
for(int i=0; i< PLATFORM_PRINT_ORDER.length && PLATFORM_PRINT_ORDER[i]!=null; i++ ){
String name = PLATFORM_PRINT_ORDER[i];
String folder;
Object obj = requested.get(name);
if(obj!=null && doesNotExist.get(name)==null ){
folder = name+"/main/";
if(name.equals("icu")|| name.equals("common")|| name.indexOf("jdk")>=0){
int index = localeStr.indexOf("_");
String parent = localeStr.substring(0,index);
writer.print(" <th bgcolor=\""+
(String)colorHash.get(name)+ "\">" +
name.toUpperCase()+
" (<a href=\"../../"+folder+localeStr+".xml\">"+localeStr+"</a>,"+
" <a href=\"../../"+folder+parent+".xml\">"+parent+"</a>,"+
" <a href=\"../../"+folder+"root.xml\">root</a>)"+
"</th>\n");
}else{
writer.print(" <th bgcolor=\""+
(String)colorHash.get(name)+ "\">" +
name.toUpperCase()+
" (<a href=\"../../"+folder+localeStr+".xml\">"+localeStr+"</a>)"+
"</th>\n");
}
numPlatforms++;
}
}
writer.print(" </tr>\n");
}
private void printValue(CompareElement element, PrintWriter writer){
writer.print(" <tr>\n");
writer.print(" <td><a NAME=\""+serialNumber+"\" href=\"#"+serialNumber+"\">"+serialNumber+"</a></td>\n");
writer.print(" <td>"+mapToAbbr(element.parentNode)+"</td>\n");
writer.print(" <td>"+mapToAbbr(element.node)+"</td>\n");
writer.print(" <td>"+element.index+"</td>\n");
serialNumber++;
for(int i=0; i<PLATFORM_PRINT_ORDER.length; i++){
String value = (String)element.platformData.get(PLATFORM_PRINT_ORDER[i]);
String color = (String)colorHash.get(PLATFORM_PRINT_ORDER[i]);
boolean caseDiff = false;
boolean isEqual = false;
// the locale exists for the given platform but there is no data
// so just write non breaking space and continue
// else the object contains value to be written .. so write it
if(value == null ){
if(requested.get(PLATFORM_PRINT_ORDER[i])!=null && doesNotExist.get(PLATFORM_PRINT_ORDER[i])==null){
writer.print(" <td>&nbsp;</td>\n");
}
}else{
//pick the correct color
for(int j=0; j<i; j++){
String compareTo = (String)element.platformData.get(PLATFORM_PRINT_ORDER[j]);
if(compareTo==null){
continue;
}else if(value.equals("")){
color = "#FFFFFF";
break;
}else if(Normalizer.compare(compareTo,value,0)==0){
color = (String)colorHash.get(PLATFORM_PRINT_ORDER[j]);
isEqual = true;
break;
}else if(Normalizer.compare(compareTo,value,Normalizer.COMPARE_IGNORE_CASE)==0){
caseDiff=true;
color = (String)colorHash.get(PLATFORM_PRINT_ORDER[j]);
break;
}
}
if(isEqual){
value = "=";
}
if(caseDiff==true){
writer.print(" <td bgcolor="+color+">"+value+"&#x2020;</td>\n");
}else{
writer.print(" <td bgcolor="+color+">"+value+"</td>\n");
}
}
}
writer.print(" </tr>\n");
}
private String mapToAbbr(String source){
if(source.equals("icu:ruleBasedNumberFormat")){
return "icu:rbnf";
}
if(source.equals("icu:ruleBasedNumberFormats")){
return "icu:rbnfs";
}
if(source.equals("exemplarCharacters")){
return "exemplarC";
}
if(source.equals("localizedPatternChars")){
return "lpc";
}
return source;
}
private void printHTML(PrintWriter writer, String localeStr){
System.out.println("INFO: Creating the comparison chart ");
ULocale locale = new ULocale(localeStr);
String displayLang = locale.getDisplayLanguage();
String dispCountry = locale.getDisplayCountry();
String dispVariant = locale.getDisplayVariant();
String displayName = localeStr+" ("+locale.getDisplayName()+") ";
writer.print("<html>\n"+
" <head>\n"+
" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"+
" <title>"+localeStr+"</title>\n"+
" </head>\n"+
" <style>\n"+
" <!--\n" +
" table { border-spacing: 0; border-collapse: collapse; width: 100%; \n" +
" border: 1px solid black }\n" +
" td, th { width: 10%; border-spacing: 0; border-collapse: collapse; color: black; \n" +
" vertical-align: top; border: 1px solid black }\n" +
" -->\n" +
" </style>"+
" <body bgcolor=\"#FFFFFF\">\n"+
" <p><b>"+displayName+
"<a href=\"http://oss.software.ibm.com/cgi-bin/icu/lx/en/?_="+localeStr+"\">Demo</a>, "+
"<a href=\"../../comparison_charts.html\">Cover Page</a>, "+
"<a href=\"./index.html\">Index</a>, "+
"<a href=\"../collation/"+localeStr+".html\">Collation</a> "+
"</b></p>\n"+
" <table>\n");
printTableHeader(writer);
// walk down the compare map and print the data
Iterator iter = compareMap.keySet().iterator();
while(iter.hasNext()){
Object obj = iter.next();
CompareElement element;
if(obj != null){
Object value = compareMap.get(obj);
if(value instanceof CompareElement){
element = (CompareElement)value;
}else{
throw new RuntimeException("The object stored in the compare map is not an instance of CompareElement");
}
printValue(element,writer);
}else{
throw new RuntimeException("No objects stored in the compare map!");
}
}
writer.print( " </table>\n");
writer.print( " <p>Created on: " + cal.getTime() +"</p>\n"+
" </body>\n"+
"</html>\n");
writer.flush();
writer.flush();
}
private Document getFullyResolvedLocale(String localeName,String fileName){
// here we assume that "_" is the delimiter
int index = fileName.lastIndexOf(File.separatorChar);
String sourceDir = fileName.substring(0, index+1);
String locale = fileName.substring(index+1, fileName.lastIndexOf("."));
Document doc = LDMLUtilities.getFullyResolvedLDML(sourceDir, locale, true);
/*
* debugging code
*/
try{
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(destFolder+File.separator+localeName+"_debug.xml"),encoding);
LDMLUtilities.printDOMTree(doc,new PrintWriter(writer));
}catch( Exception e){
//throw the exception away .. this is for debugging
}
return doc;
}
private boolean addToCompareMap(String fileName, String key)
{
// parse the test doc only if gold doc was parsed OK
Document testDoc = getFullyResolvedLocale(key,fileName);
requested.put(key,"");
if (null == testDoc)
{
doesNotExist.put(key, "");
return false;
}
return extractMergeData(testDoc,key);
}
// ---------------------------------------------------------------------------
//
// Merge element nodes. dest and source are Element nodes of the same type.
// Move any children Elements that exist in the source but not in the
// destination into the destination
//
// ---------------------------------------------------------------------------
private void mergeElements(Node dest, Node source) {
Node childOfSource;
Node childOfDest;
Document destDoc = dest.getOwnerDocument();
Node spaces = destDoc.createTextNode("\n ");
childOfSource = source.getFirstChild();
childOfDest = dest.getFirstChild();
for (childOfSource = source.getFirstChild(); childOfSource != null; childOfSource = childOfSource.getNextSibling()) {
//String dNodeVal = dest.getFirstChild().getNodeValue();
//String sNodeVal = childOfSource.getNodeValue();
if (childOfSource.getNodeType() != Node.ELEMENT_NODE) {
continue;
}
boolean didMerge = false;
for (childOfDest = dest.getFirstChild(); childOfDest != null; childOfDest = childOfDest.getNextSibling()) {
String childOfDestNN = childOfDest.getNodeName();
String childOfSourceNN = childOfSource.getNodeName();
if (childOfDest.getNodeType() == Node.ELEMENT_NODE &&
childOfDestNN.equals(childOfSourceNN)) {
// The destination document already has an element of this type at this level.
// Recurse to pick up any extra children that the source node may have.
mergeElements(childOfDest, childOfSource);
didMerge = true;
break;
}
}
if(didMerge == false) {
// destination document had no corresponding node to the current childOfSource. Add it.
Node importedNode = destDoc.importNode(childOfSource, true);
dest.appendChild(spaces);
dest.appendChild(importedNode);
}
}
}
private boolean comparePatterns(String pat1,String pat2){
//TODO: just return for now .. this is useful only
//when comparing data from toronto
/*
double args1 = 10000000000.00;
double args2 = -10000000000.00;
DecimalFormat fmt = new DecimalFormat();
fmt.applyPattern(pat1);
String s1 = fmt.format(args1);
String s3 = fmt.format(args2);
fmt.applyPattern(pat2);
String s2 = fmt.format(args1);
String s4 = fmt.format(args2);
if(s1.equals(s2) && s3.equals(s4)){
return true;
}
return false;
*/
return true;
}
private String trim(String source){
char[] src = source.toCharArray();
char[] dest = new char[src.length];
int start=0;
while(start<(src.length) && (UCharacter.isWhitespace(src[start]))){start++;}
int stop=src.length-1;
while(stop>0 && (UCharacter.isWhitespace(src[stop])||(src[stop]==0xA0))){stop--;}
if(stop!=-1 && start!=src.length){
System.arraycopy(src,start,dest,0,(stop-start)+1);
return new String(dest,0,(stop-start)+1);
}else{
return new String();
}
}
private void addElement(String childNode, String parentNode, String id, String index,
String platformValue, String platformName){
Object obj = compareMap.get(id);
CompareElement element;
if(obj==null){
element = new CompareElement();
//initialize the values
element.index = index;
element.parentNode = parentNode;
element.node = childNode;
// add the element to the compare map
compareMap.put(id, element);
}else{
if(obj instanceof CompareElement){
element = (CompareElement) obj;
}else{
throw new RuntimeException("The object stored in the compareMap is not a CompareElement object!");
}
}
if((!element.index.equals(index)) ||
(!element.node.equals(childNode)) ||
(!element.parentNode.equals(parentNode))){
throw new RuntimeException("The retrieved object is not the same as the one trying to be saved");
}
element.platformData.put(platformName, platformValue);
}
private boolean childrenAreElements(Node node){
NodeList list = node.getChildNodes();
for(int i=0;i<list.getLength();i++){
if(list.item(i).getNodeType()==Node.ELEMENT_NODE){
return true;
}
}
return false;
}
private String getTag(String childNodeName, String index){
//for months make index a,b,c,d etc
if(childNodeName.indexOf("month")>-1){
int i = Integer.parseInt(index);
StringBuffer temp = new StringBuffer();
temp.append((char)('a'+i));
return temp.toString();
}else if(childNodeName.indexOf("day")>-1){
if (index.equals("sun")){
return "a";
}else if(index.equals("mon")){
return "b";
}else if( index.equals("tue")){
return "c";
}else if (index.equals("wed")){
return "d";
}else if (index.equals("thu")){
return "e";
}else if (index.equals("fri")){
return "f";
}else if (index.equals("sat")){
return "g";
}
}else{
return index;
}
return "";
}
private boolean extractMergeData(Node node,String key){
Node childOfSource;
for(childOfSource = node.getFirstChild(); childOfSource != null; childOfSource = childOfSource.getNextSibling()) {
if (childOfSource.getNodeType() != Node.ELEMENT_NODE) {
continue;
}
String childOfSourceName = childOfSource.getNodeName();
//Ignore collation and special tags
if(childOfSourceName.equals("collations")|| childOfSource.equals("special")){
continue;
}
if(childrenAreElements(childOfSource)==false){
NamedNodeMap attr = childOfSource.getAttributes();
Node typeNode = attr.getNamedItem("type");
String index="";
if(typeNode!=null){
String temp =typeNode.getNodeValue();
if(!temp.equals("standard")){
index = temp;
}
}
String nodeValue = "";
Node valueNode = childOfSource.getFirstChild();
if(valueNode != null){
String temp = trim(valueNode.getNodeValue());
if(!temp.equals("standard")){
nodeValue = temp;
}
}
Node parentNode = childOfSource.getParentNode();
String parentNodeName = trim(parentNode.getNodeName());
String childNodeName = trim(childOfSource.getNodeName());
Node grandParentNode = childOfSource.getParentNode().getParentNode();
String grandParentNodeName = grandParentNode.getNodeName();
NamedNodeMap parentAttrib = parentNode.getAttributes();
String type ="";
if(parentAttrib != null){
Node mytypeNode = parentAttrib.getNamedItem("type");
if(mytypeNode!=null){
String mytype = mytypeNode.getNodeValue();
if(!mytype.equals("standard")){
type = mytype;
}
}
}
if(grandParentNodeName.equals("monthContext")|| grandParentNodeName.equals("dayContext")){
NamedNodeMap gpa = grandParentNode.getAttributes();
Node gptNode = gpa.getNamedItem("type");
if(gptNode!=null){
String gptType = gptNode.getNodeValue();
if(!gptType.equals("standard")){
parentNodeName = parentNodeName+ "\u200b_"+gptType;
}
}
NamedNodeMap pa = parentNode.getAttributes();
Node ptNode = pa.getNamedItem("type");
if(ptNode!=null){
String ptType = ptNode.getNodeValue();
if(!ptType.equals("standard")){
childNodeName = childNodeName+ "\u200b_"+ptType;
}
}
Node calendar = grandParentNode.getParentNode().getParentNode();
NamedNodeMap ggpa = calendar.getAttributes();
Node ggptNode = ggpa.getNamedItem("type");
if(ggptNode!=null){
String ggptType = ggptNode.getNodeValue();
if(!ggptType.equals("standard")){
grandParentNodeName = grandParentNodeName+ "\u200b_"+ggptType;
}
}
}
if(childNodeName.equals("pattern") ||grandParentNodeName.equals("zone") ){
NamedNodeMap at = grandParentNode.getAttributes();
Node mytypeNode = at.getNamedItem("type");
if(mytypeNode!=null){
String mytype = mytypeNode.getNodeValue();
if(!mytype.equals("standard")){
if(type.equals("")){
type = mytype;
}else{
type = type+"\u200b_"+mytype;
}
}
}
}
if(grandParentNodeName.equals("special") || parentNodeName.equals("special") || childNodeName.equals("special")
|| grandParentNodeName.indexOf(":")>0){
continue;
}
if(!nodeValue.equals("") &&
!childOfSource.getNodeName().equals("version")){
if(grandParentNodeName.equals("zone")){
parentNodeName = grandParentNodeName+"\u200b_"+parentNodeName;
}
// for country codes and language codes
// replace the deprecated codes with the latest ones
if(childNodeName.equals("language")){
String temp = (String)deprecatedLanguageCodes.get(index);
if(temp!=null){
index = temp;
}
}else if( childNodeName.equals("territory")){
String temp = (String)deprecatedCountryCodes.get(index);
if(temp!=null){
index = temp;
}
}
String id = parentNodeName+"_"+childNodeName+"_"+type+"_"+getTag(childNodeName, index)+"_"+grandParentNodeName;
if(!index.equals("")){
if(!index.equals(nodeValue) && !index.equals("Fallback")){
addElement(childNodeName, parentNodeName, id, index, nodeValue, key);
}
}else{
if(!type.equals(nodeValue) && !type.equals("Fallback")){
addElement(childNodeName, parentNodeName, id, type, nodeValue, key);
}
}
}
if(attr.getLength()>0 && typeNode==null){
// add an element for each attribute different for each attribute
for(int i=0; i<attr.getLength(); i++){
Node item = attr.item(i);
String attrName =item.getNodeName();
if(attrName.equals("type")){
continue;
}
if(grandParentNodeName.equals("zone")){
parentNodeName = grandParentNodeName+"\u200b_"+parentNodeName;
}
String id = parentNodeName+"_"+childNodeName+"_"+type+"_"+attrName+"_"+grandParentNodeName;
if(!index.equals("")){
addElement(childNodeName, parentNodeName, id, index, item.getNodeValue(), key);
}else{
addElement(childNodeName, parentNodeName, id, type, item.getNodeValue(), key);
}
}
}
}else{
//the element has more children .. recurse to pick them all
extractMergeData(childOfSource,key);
}
}
return true;
}
}

View File

@ -0,0 +1,537 @@
/*
* Created on Jul 28, 2004
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Generation - Code and Comments
*/
package com.ibm.icu.dev.tool.cldr;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
// DOM imports
import org.apache.xpath.XPathAPI;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
// Needed JAXP classes
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.TransformerException;
// SAX2 imports
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
/**
* @author ram
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Generation - Code and Comments
*/
public class LDMLUtilities {
/**
* Creates a fully resolved locale starting with root and
* @param sourceDir
* @param locale
* @return
*/
public static Document getFullyResolvedLDML(String sourceDir, String locale, boolean ignoreRoot){
Document full =null;
try{
full = parse(sourceDir+File.separator+ "root.xml");
}catch(RuntimeException ex){
if(!ignoreRoot){
throw ex;
}
}
String[] constituents = locale.split("_");
String loc=null;
for(int i=0; i<constituents.length; i++){
if(loc==null){
loc = constituents[i];
}else{
loc = loc +"_"+ constituents[i];
}
Document doc = parse(sourceDir+File.separator+loc+".xml");
StringBuffer xpath = new StringBuffer();
mergeLDMLDocuments(full, doc, xpath);
}
return full;
}
private static String TYPE = "type";
private static String IDENTITY = "identity";
/**
* Resolved Data File
* <p>To produce fully resolved locale data file from CLDR for a locale ID L, you start with root, and
* replace/add items from the child locales until you get down to L. More formally, this can be
* expressed as the following procedure.</p>
* <ol>
* <li>Let Result be an empty LDML file.</li>
*
* <li>For each Li in the locale chain for L<ol>
* <li>For each element pair P in the LDML file for Li:<ol>
* <li>If Result has an element pair Q with an equivalent element chain, remove Q.</li>
* <li>Add P to Result.</li>
* </ol>
* </li>
* </ol>
*
* </li>
* </ol>
* <p>Note: when adding an element pair to a result, it has to go in the right order for it to be valid
* according to the DTD.</p>
*
* @param source
* @param overide
* @return the merged document
*/
public static Node mergeLDMLDocuments(Document source, Node overide, StringBuffer xpath){
if(source==null){
return overide;
}
if(xpath.length()==0){
xpath.append("/");
}
// we know that every child xml file either adds or
// overrides the elements in parent
// so we traverse the child, at every node check if
// if the node is present in the source,
// if (present)
// recurse to replace any nodes that need to be overridded
// else
// import the node into source
Node child = overide.getFirstChild();
while( child!=null){
// we are only concerned with element nodes
if(child.getNodeType()!=Node.ELEMENT_NODE){
child = child.getNextSibling();
continue;
}
String childName = child.getNodeName();
int savedLength=xpath.length();
xpath.append("/");
xpath.append(childName);
appendXPathAttribute(child,xpath);
Node nodeInSource = getNode(source, xpath.toString());
if(nodeInSource==null){
// the child xml has a new node
// that should be added to parent
String parentXpath = xpath.substring(0, savedLength);
Node parentNodeInSource = getNode(source, parentXpath);
if(parentNodeInSource==null){
throw new RuntimeException("Internal Error");
}
if(xpath.indexOf(IDENTITY)>-1){
String delXPath= xpath.substring(0,savedLength)+"/"+childName;
Node delNode = getNode(source, delXPath);
if(delNode!=null){
parentNodeInSource.removeChild(delNode);
}
}
Node childToImport = source.importNode(child,true);
parentNodeInSource.appendChild(childToImport);
}else{
if(areChildrenElementNodes(child)){
//recurse to pickup any children!
mergeLDMLDocuments(source, child, xpath);
}else{
// we have reached a leaf node now get the
// replace to the source doc
Node parentNodeInSource = nodeInSource.getParentNode();
Node childToImport = source.importNode(child,true);
parentNodeInSource.replaceChild(childToImport, nodeInSource);
}
}
xpath.delete(savedLength,xpath.length());
child= child.getNextSibling();
}
return source;
}
private static final String ALT = "alt";
public static void appendXPathAttribute(Node node, StringBuffer xpath){
boolean terminate = false;
String val = getAttributeValue(node, TYPE);
if(val!=null){
xpath.append("[@type='");
xpath.append(val);
xpath.append("'");
terminate = true;
}
val = getAttributeValue(node, ALT);
if(val!=null){
xpath.append("and @alt='");
xpath.append(val);
xpath.append("'");
terminate = true;
}
if(terminate){
xpath.append("]");
}
}
public static boolean areChildrenElementNodes(Node node){
NodeList list = node.getChildNodes();
for(int i=0;i<list.getLength();i++){
if(list.item(i).getNodeType()==Node.ELEMENT_NODE){
return true;
}
}
return false;
}
public static NodeList getNodeList( Document doc, String xpath){
try{
return XPathAPI.selectNodeList(doc, xpath);
}catch(TransformerException ex){
throw new RuntimeException(ex.getMessage());
}
}
/**
*
* @param doc
* @param xpath
* @return
*/
public static Node getNode(Document doc, String xpath){
try{
NodeList nl = XPathAPI.selectNodeList(doc, xpath);
int len = nl.getLength();
//TODO watch for attribute "alt"
if(len>1){
throw new IllegalArgumentException("The XPATH returned more than 1 node!. Check XPATH: "+xpath);
}
if(len==0){
return null;
}
return nl.item(0);
}catch(TransformerException ex){
throw new RuntimeException(ex.getMessage());
}
}
public static Node getNode(Node node, String xpath){
try{
NodeList nl = XPathAPI.selectNodeList(node, xpath);
int len = nl.getLength();
//TODO watch for attribute "alt"
if(len>1){
throw new IllegalArgumentException("The XPATH returned more than 1 node!. Check XPAHT: "+xpath);
}
if(len==0){
return null;
}
return nl.item(0);
}catch(TransformerException ex){
throw new RuntimeException(ex.getMessage());
}
}
public static Node getNode(Node context, String resToFetch, Document fullyResolved, String xpath){
String ctx = "./"+ resToFetch;
Node node = getNode(context, ctx);
if(node == null && fullyResolved!=null){
// try from fully resolved
String path = xpath+"/"+resToFetch;
node = getNode(fullyResolved, path);
}
return node;
}
/** Decide if the node is text, and so must be handled specially */
static boolean isTextNode(Node n) {
if (n == null)
return false;
short nodeType = n.getNodeType();
return nodeType == Node.CDATA_SECTION_NODE || nodeType == Node.TEXT_NODE;
}
public static String getAttributeValue(Node sNode, String attribName){
String value=null;
Node node = sNode;
NamedNodeMap attributes = node.getAttributes();
Node attr = attributes.getNamedItem(attribName);
if(attr!=null){
value = attr.getNodeValue();
}
return value;
}
public static String getNodeValue(Node node){
for(Node child=node.getFirstChild(); child!=null; child=child.getNextSibling() ){
if(child.getNodeType()==Node.TEXT_NODE){
return child.getNodeValue();
}
}
return null;
}
/**
* Simple worker method to parse filename to a Document.
*
* Attempts XML parse, then HTML parse (when parser available),
* then just parses as text and sticks into a text node.
*
* @param filename to parse as a local path
*
* @return Document object with contents of the file;
* otherwise throws an unchecked RuntimeException if there
* is any fatal problem
*/
public static Document parse(String filename)
{
// Force filerefs to be URI's if needed: note this is independent of any other files
String docURI = filenameToURL(filename);
return parse(new InputSource(docURI),filename);
}
public static Document parse(InputSource docSrc, String filename){
DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
// Always set namespaces on
dfactory.setNamespaceAware(true);
dfactory.setValidating(true);
// Set other attributes here as needed
//applyAttributes(dfactory, attributes);
// Local class: cheap non-printing ErrorHandler
// This is used to suppress validation warnings
ErrorHandler nullHandler = new ErrorHandler() {
public void warning(SAXParseException e) throws SAXException {System.err.println("Warning: " + e.getMessage());}
public void error(SAXParseException e) throws SAXException {System.err.println("Error: " + e.getMessage());}
public void fatalError(SAXParseException e) throws SAXException
{
throw e;
}
};
Document doc = null;
try
{
// First, attempt to parse as XML (preferred)...
DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
docBuilder.setErrorHandler(nullHandler);
doc = docBuilder.parse(docSrc);
}
catch (Throwable se)
{
// ... if we couldn't parse as XML, attempt parse as HTML...
System.out.println("ERROR :" + se.getMessage());
try
{
// @todo need to find an HTML to DOM parser we can use!!!
// doc = someHTMLParser.parse(new InputSource(filename));
throw new RuntimeException("XMLComparator no HTML parser!");
}
catch (Exception e)
{
if(filename!=null)
{
// ... if we can't parse as HTML, then just parse the text
try
{
// Parse as text, line by line
// Since we already know it should be text, this should
// work better than parsing by bytes.
FileReader fr = new FileReader(filename);
BufferedReader br = new BufferedReader(fr);
StringBuffer buffer = new StringBuffer();
for (;;)
{
String tmp = br.readLine();
if (tmp == null)
{
break;
}
buffer.append(tmp);
buffer.append("\n"); // Put in the newlines as well
}
DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
doc = docBuilder.newDocument();
Element outElem = doc.createElement("out");
Text textNode = doc.createTextNode(buffer.toString());
// Note: will this always be a valid node? If we're parsing
// in as text, will there ever be cases where the diff that's
// done later on will fail becuase some really garbage-like
// text has been put into a node?
outElem.appendChild(textNode);
doc.appendChild(outElem);
}
catch (Throwable throwable)
{
//throwable.printStackTrace();
}
}
}
}
return doc;
} // end of parse()
/*
* Utility method to translate a String filename to URL.
*
* Note: This method is not necessarily proven to get the
* correct URL for every possible kind of filename; it should
* be improved. It handles the most common cases that we've
* encountered when running Conformance tests on Xalan.
* Also note, this method does not handle other non-file:
* flavors of URLs at all.
*
* If the name is null, return null.
* If the name starts with a common URI scheme (namely the ones
* found in the examples of RFC2396), then simply return the
* name as-is (the assumption is that it's already a URL)
* Otherwise we attempt (cheaply) to convert to a file:/// URL.
*/
public static String filenameToURL(String filename){
// null begets null - something like the commutative property
if (null == filename){
return null;
}
// Don't translate a string that already looks like a URL
if (filename.startsWith("file:")
|| filename.startsWith("http:")
|| filename.startsWith("ftp:")
|| filename.startsWith("gopher:")
|| filename.startsWith("mailto:")
|| filename.startsWith("news:")
|| filename.startsWith("telnet:")
){
return filename;
}
File f = new File(filename);
String tmp = null;
try{
// This normally gives a better path
tmp = f.getCanonicalPath();
}catch (IOException ioe){
// But this can be used as a backup, for cases
// where the file does not exist, etc.
tmp = f.getAbsolutePath();
}
// URLs must explicitly use only forward slashes
if (File.separatorChar == '\\') {
tmp = tmp.replace('\\', '/');
}
// Note the presumption that it's a file reference
// Ensure we have the correct number of slashes at the
// start: we always want 3 /// if it's absolute
// (which we should have forced above)
if (tmp.startsWith("/")){
return "file://" + tmp;
}
else{
return "file:///" + tmp;
}
}
/** Prints the specified node, recursively. */
public static void printDOMTree(Node node, PrintWriter out)
{
int type = node.getNodeType();
switch (type)
{
// print the document element
case Node.DOCUMENT_NODE:
{
printDOMTree(((Document)node).getDocumentElement(), out);
break;
}
// print element with attributes
case Node.ELEMENT_NODE:
{
out.print("<");
out.print(node.getNodeName());
NamedNodeMap attrs = node.getAttributes();
for (int i = 0; i < attrs.getLength(); i++)
{
Node attr = attrs.item(i);
out.print(" " + attr.getNodeName() +
"=\"" + attr.getNodeValue() +
"\"");
}
out.print(">");
NodeList children = node.getChildNodes();
if (children != null)
{
int len = children.getLength();
for (int i = 0; i < len; i++)
printDOMTree(children.item(i), out);
}
break;
}
// handle entity reference nodes
case Node.ENTITY_REFERENCE_NODE:
{
out.print("&");
out.print(node.getNodeName());
out.print(";");
break;
}
// print cdata sections
case Node.CDATA_SECTION_NODE:
{
out.print("<![CDATA[");
out.print(node.getNodeValue());
out.print("]]>");
break;
}
// print text
case Node.TEXT_NODE:
{
out.print(node.getNodeValue());
break;
}
// print processing instruction
case Node.PROCESSING_INSTRUCTION_NODE:
{
out.print("<?");
out.print(node.getNodeName());
String data = node.getNodeValue();
{
out.print(" ");
out.print(data);
}
out.print("?>");
break;
}
}
if (type == Node.ELEMENT_NODE)
{
out.print("</");
out.print(node.getNodeName());
out.print('>');
}
} // printDOMTree(Node, PrintWriter)
}

View File

@ -0,0 +1,212 @@
/*
******************************************************************************
* Copyright (C) 2003-2004, International Business Machines Corporation and *
* others. All Rights Reserved. *
******************************************************************************
*/
package com.ibm.icu.dev.tool.cldr;
/**
* @author Ram
*
* To change this generated comment edit the template variable "typecomment":
* Window>Preferences>Java>Templates.
* To enable and disable the creation of type comments go to
* Window>Preferences>Java>Code Generation.
*/
/**
* @author ram
*
* This tool validates xml against DTD ... IE 6 does not do a good job
*/
import java.io.*;
import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
// Needed JAXP classes
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
// SAX2 imports
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
//DOM imports
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
public class XMLValidator {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("No files specified. Validation failed");
return;
}
for (int i = 0; i < args.length; i++) {
/* Document doc = */parse(args[i]);
System.out.println("Processing file " + args[i]);
}
}
/**
* Utility method to translate a String filename to URL.
*
* Note: This method is not necessarily proven to get the correct URL for
* every possible kind of filename; it should be improved. It handles the
* most common cases that we've encountered when running Conformance tests
* on Xalan. Also note, this method does not handle other non-file: flavors
* of URLs at all.
*
* If the name is null, return null. If the name starts with a common URI
* scheme (namely the ones found in the examples of RFC2396), then simply
* return the name as-is (the assumption is that it's already a URL)
* Otherwise we attempt (cheaply) to convert to a file:/// URL.
*
* @param filename
* a local path/filename of a file
* @return a file:/// URL, the same string if it appears to already be a
* URL, or null if error
*/
public static String filenameToURL(String filename) {
// null begets null - something like the commutative property
if (null == filename)
return null;
// Don't translate a string that already looks like a URL
if (filename.startsWith("file:") || filename.startsWith("http:")
|| filename.startsWith("ftp:")
|| filename.startsWith("gopher:")
|| filename.startsWith("mailto:")
|| filename.startsWith("news:")
|| filename.startsWith("telnet:"))
return filename;
File f = new File(filename);
String tmp = null;
try {
// This normally gives a better path
tmp = f.getCanonicalPath();
} catch (IOException ioe) {
// But this can be used as a backup, for cases
// where the file does not exist, etc.
tmp = f.getAbsolutePath();
}
// URLs must explicitly use only forward slashes
if (File.separatorChar == '\\') {
tmp = tmp.replace('\\', '/');
}
// Note the presumption that it's a file reference
// Ensure we have the correct number of slashes at the
// start: we always want 3 /// if it's absolute
// (which we should have forced above)
if (tmp.startsWith("/"))
return "file://" + tmp;
else
return "file:///" + tmp;
}
static Document parse(String filename) {
// Force filerefs to be URI's if needed: note this is independent of any
// other files
String docURI = filenameToURL(filename);
return parse(new InputSource(docURI), filename);
}
static Document parse(InputSource docSrc, String filename) {
DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
// Always set namespaces on
dfactory.setNamespaceAware(true);
dfactory.setValidating(true);
// Set other attributes here as needed
//applyAttributes(dfactory, attributes);
// Local class: cheap non-printing ErrorHandler
// This is used to suppress validation warnings
ErrorHandler nullHandler = new ErrorHandler() {
public void warning(SAXParseException e) throws SAXException {
System.err.println("Warning: " + e.getMessage());
}
public void error(SAXParseException e) throws SAXException {
System.err.println("Element " + e.getPublicId()
+ " is not valid because " + e.getMessage());
System.err.println("Error: " + "at line " + e.getLineNumber()
+ ", column " + e.getColumnNumber());
}
public void fatalError(SAXParseException e) throws SAXException {
throw e;
}
};
Document doc = null;
try {
// First, attempt to parse as XML (preferred)...
DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
docBuilder.setErrorHandler(nullHandler);
//if(docBuilder.isValidating()){
//System.out.println("The parser is a validating parser");
//}
doc = docBuilder.parse(docSrc);
} catch (Throwable se) {
// ... if we couldn't parse as XML, attempt parse as HTML...
System.out.println("ERROR :" + se.toString());
if (se instanceof SAXParseException) {
SAXParseException pe = (SAXParseException) se;
System.out.println("At line: " + pe.getLineNumber()
+ " column: " + pe.getColumnNumber());
}
try {
// @todo need to find an HTML to DOM parser we can use!!!
// doc = someHTMLParser.parse(new InputSource(filename));
throw new RuntimeException("XMLComparator no HTML parser!");
} catch (Exception e) {
if (filename != null) {
// ... if we can't parse as HTML, then just parse the text
try {
// Parse as text, line by line
// Since we already know it should be text, this should
// work better than parsing by bytes.
FileReader fr = new FileReader(filename);
BufferedReader br = new BufferedReader(fr);
StringBuffer buffer = new StringBuffer();
for (;;) {
String tmp = br.readLine();
if (tmp == null) {
break;
}
buffer.append(tmp);
buffer.append("\n"); // Put in the newlines as well
}
DocumentBuilder docBuilder = dfactory
.newDocumentBuilder();
doc = docBuilder.newDocument();
Element outElem = doc.createElement("out");
Text textNode = doc.createTextNode(buffer.toString());
// Note: will this always be a valid node? If we're
// parsing
// in as text, will there ever be cases where the diff that's
// done later on will fail becuase some really garbage-like
// text has been put into a node?
outElem.appendChild(textNode);
doc.appendChild(outElem);
} catch (Throwable throwable) {
//throwable.printStackTrace();
}
}
}
}
return doc;
}
}