• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  ******************************************************************************
3  * Copyright (C) 2004, International Business Machines Corporation and        *
4  * others. All Rights Reserved.                                               *
5  ******************************************************************************
6  */
7 package org.unicode.cldr.tool;
8 
9 import java.io.File;
10 import java.io.FileInputStream;
11 import java.io.IOException;
12 import java.io.PrintWriter;
13 import java.util.Collection;
14 import java.util.Comparator;
15 import java.util.HashMap;
16 import java.util.Iterator;
17 import java.util.Map;
18 import java.util.Set;
19 import java.util.TreeMap;
20 import java.util.TreeSet;
21 import java.util.regex.Matcher;
22 
23 import org.unicode.cldr.util.CLDRFile;
24 import org.unicode.cldr.util.CLDRPaths;
25 import org.unicode.cldr.util.CldrUtility;
26 import org.unicode.cldr.util.DtdData;
27 import org.unicode.cldr.util.Factory;
28 import org.unicode.cldr.util.PathUtilities;
29 import org.unicode.cldr.util.PatternCache;
30 import org.unicode.cldr.util.StandardCodes;
31 import org.unicode.cldr.util.TransliteratorUtilities;
32 import org.xml.sax.Attributes;
33 import org.xml.sax.ContentHandler;
34 import org.xml.sax.InputSource;
35 import org.xml.sax.Locator;
36 import org.xml.sax.SAXException;
37 import org.xml.sax.XMLReader;
38 import org.xml.sax.ext.DeclHandler;
39 
40 public class GenerateAttributeList {
41     Map<String, Map<String, Set<String>[]>> element_attribute_valueSet = new TreeMap<>();
42     Set<String> allElements = new TreeSet<>();
43     Map<String, String> defaults = new HashMap<>();
44 
GenerateAttributeList(Factory cldrFactory)45     public GenerateAttributeList(Factory cldrFactory) throws IOException {
46         addFromStandardCodes();
47         addFromDTD(CLDRPaths.COMMON_DIRECTORY + "main/en.xml");
48         addFromDTD(CLDRPaths.COMMON_DIRECTORY + "supplemental/characters.xml");
49         addFromDirectory(CLDRPaths.COMMON_DIRECTORY + "collation/");
50         addFromDirectory(CLDRPaths.COMMON_DIRECTORY + "main/");
51         addFromDirectory(CLDRPaths.COMMON_DIRECTORY + "rbnf/");
52         addFromDirectory(CLDRPaths.COMMON_DIRECTORY + "segments/");
53         addFromDirectory(CLDRPaths.COMMON_DIRECTORY + "supplemental/");
54         addFromDirectory(CLDRPaths.COMMON_DIRECTORY + "transforms/");
55     }
56 
57     /**
58      *
59      */
addFromStandardCodes()60     private void addFromStandardCodes() {
61         StandardCodes sc = StandardCodes.make();
62         addFromStandardCodes(sc, "language");
63         addFromStandardCodes(sc, "territory");
64         addFromStandardCodes(sc, "script");
65         addFromStandardCodes(sc, "variant");
66         addFromStandardCodes(sc, "currency");
67         addFromStandardCodes(sc, "tzid");
68     }
69 
70     /**
71      *
72      */
addFromStandardCodes(StandardCodes sc, String cat)73     private void addFromStandardCodes(StandardCodes sc, String cat) {
74         Collection<String> c = sc.getGoodAvailableCodes(cat);
75         String target = cat.equals("tzid") ? "zone" : cat;
76         for (Iterator<String> it = c.iterator(); it.hasNext();) {
77             String item = it.next();
78             add(target, "type", item, true);
79         }
80     }
81 
82     /**
83      * @throws IOException
84      *
85      */
addFromDTD(String filename)86     private void addFromDTD(String filename) throws IOException {
87         // StringBufferInputStream fis = new StringBufferInputStream(
88         // "<!DOCTYPE ldml SYSTEM \"http://www.unicode.org/cldr/dtd/1.2/ldml.dtd\"><ldml></ldml>");
89         FileInputStream fis = new FileInputStream(filename);
90         try {
91             XMLReader xmlReader = CLDRFile.createXMLReader(true);
92             MyDeclHandler me = new MyDeclHandler();
93             xmlReader.setProperty("http://xml.org/sax/properties/declaration-handler", me);
94             InputSource is = new InputSource(fis);
95             is.setSystemId(filename);
96             // xmlReader.setContentHandler(me);
97             // xmlReader.setErrorHandler(me);
98             xmlReader.parse(is);
99         } catch (Exception e) {
100             e.printStackTrace();
101         } finally {
102             fis.close();
103         }
104     }
105 
addFromDirectory(String directory)106     private void addFromDirectory(String directory) throws IOException {
107         File dir = new File(directory);
108         directory = PathUtilities.getNormalizedPathString(dir);
109         String[] files = dir.list();
110         for (int i = 0; i < files.length; ++i) {
111             if (files[i].startsWith(".#")) continue;
112             if (!files[i].endsWith(".xml")) continue;
113             String file = directory + File.separatorChar + files[i];
114             if (new File(file).isDirectory()) continue;
115             addFromFiles(file);
116         }
117     }
118 
addFromFiles(String file)119     private void addFromFiles(String file) throws IOException {
120         // StringBufferInputStream fis = new StringBufferInputStream(
121         // "<!DOCTYPE ldml SYSTEM \"http://www.unicode.org/cldr/dtd/1.2/ldml.dtd\"><ldml></ldml>");
122         System.out.println(file);
123         FileInputStream fis = new FileInputStream(file);
124         try {
125             XMLReader xmlReader = CLDRFile.createXMLReader(true);
126             xmlReader.setContentHandler(new MyContentHandler());
127             InputSource is = new InputSource(fis);
128             is.setSystemId(file);
129 
130             // xmlReader.setErrorHandler(me);
131             // xmlReader.setProperty("http://xml.org/sax/properties/declaration-handler", me);
132             xmlReader.parse(is);
133         } catch (Exception e) {
134             System.err.println("Failure in " + file);
135             e.printStackTrace();
136         } finally {
137             fis.close();
138         }
139     }
140 
add(String element, String attribute, String attributeValue, boolean dtd)141     void add(String element, String attribute, String attributeValue, boolean dtd) {
142         // fiddle the fields
143         if (element.equals("generation") && attribute.equals("date"))
144             attributeValue = "[date]";
145         else if (element.equals("version") && attribute.equals("number"))
146             attributeValue = "[revision]";
147         else if (attribute.equals("draft")
148             || attribute.equals("validSubLocales")
149             || attribute.equals("standard")
150             || attribute.equals("references"))
151             element = "[common]";
152         else if (attribute.equals("alt")) {
153             int pos = attributeValue.indexOf("proposed");
154             if (pos == 0) return;
155             if (pos > 0) attributeValue = attributeValue.substring(0, pos - 1);
156             element = "[common]";
157         }
158         // now add
159         Map<String, Set<String>[]> attribute_valueSet = element_attribute_valueSet.get(element);
160         if (attribute_valueSet == null) element_attribute_valueSet.put(element, attribute_valueSet = new TreeMap<>());
161         Set<String>[] valueSets = attribute_valueSet.get(attribute);
162         if (valueSets == null) {
163             Comparator<String> c = DtdData.getAttributeValueComparator(element, attribute);
164             valueSets = new Set[2];
165             valueSets[0] = new TreeSet<>(c);
166             valueSets[1] = new TreeSet<>();
167             attribute_valueSet.put(attribute, valueSets);
168         }
169         try {
170             valueSets[dtd ? 1 : 0].add(attributeValue);
171         } catch (Exception e) {
172             throw new IllegalArgumentException("Error with " + element
173                 + ", " + attribute + ", " + attributeValue + ", " + dtd, e);
174         }
175     }
176 
show(PrintWriter pw)177     void show(PrintWriter pw) {
178         pw.println("<html><head>");
179         pw.println("<style>td,th { border-style: solid; border-width: 1; vertical-align: top }</style>");
180         pw.println("</head><body>");
181         pw.println("<p>Date: $" +
182             "Date$</p>");
183         pw.println("<p>Version: " + ToolConstants.CHART_DISPLAY_VERSION + "</p>");
184         pw.println("<table>");
185         pw.println("<tr><th>Element</th><th>Attribute</th><th>Actual Attribute Values</th><th>Other DTD Attribute Values</th></tr>");
186 
187         // show those with no attributes
188         /*
189          * Set hasNoAttributes = new TreeSet(allElements);
190          * hasNoAttributes.removeAll(element_attribute_valueSet.keySet());
191          * pw.print("<tr><td>");
192          * pw.print(toString(hasNoAttributes));
193          * pw.println("</td><td>{none}</td><td>{none}</td></tr>");
194          */
195 
196         for (Iterator<String> it = element_attribute_valueSet.keySet().iterator(); it.hasNext();) {
197             String element = it.next();
198             Map<String, Set<String>[]> attribute_valueSet = element_attribute_valueSet.get(element);
199             int size = attribute_valueSet.size();
200             if (size == 0) continue;
201             boolean first = true;
202             for (Iterator<String> it2 = attribute_valueSet.keySet().iterator(); it2.hasNext();) {
203                 String attribute = it2.next();
204                 Set<String>[] valueSets = attribute_valueSet.get(attribute);
205                 pw.print("<tr>");
206                 if (first) {
207                     first = false;
208                     pw.print("<td" + (size == 1 ? "" : " rowSpan='" + attribute_valueSet.size() + "'") + ">" + element
209                         + "</td>");
210                 }
211                 pw.print("<td>" + attribute + "</td><td>");
212                 String defaultKey = element + "|" + attribute;
213                 pw.print(toString(valueSets[0], defaultKey));
214                 pw.println("</td><td>");
215                 Set<String> toRemove = new TreeSet<>(valueSets[0]);
216                 Set<String> remainder = new TreeSet<>(valueSets[1]);
217                 remainder.removeAll(toRemove);
218                 pw.print(toString(remainder, defaultKey));
219                 pw.println("</td></tr>");
220             }
221         }
222         pw.println("</table>");
223         pw.println(CldrUtility.ANALYTICS);
224         pw.println("</body></html>");
225     }
226 
227     /**
228      *
229      */
toString(Collection<String> source, String defaultKey)230     private String toString(Collection<String> source, String defaultKey) {
231         StringBuffer result = new StringBuffer();
232         boolean first = true;
233         for (Iterator<String> it = source.iterator(); it.hasNext();) {
234             String value = it.next();
235             if (first)
236                 first = false;
237             else
238                 result.append(", ");
239             final boolean isDefault = value.equals(defaults.get(defaultKey));
240             if (isDefault) {
241                 result.append("<b>");
242             }
243             result.append(TransliteratorUtilities.toHTML.transform(value));
244             if (isDefault) {
245                 result.append("</b>");
246             }
247         }
248         return result.toString();
249     }
250 
251     class MyDeclHandler implements DeclHandler {
252 
253         Matcher idmatcher = PatternCache.get("[a-zA-Z][-_a-zA-Z0-9]*").matcher("");
254 
255         @Override
attributeDecl(String eName, String aName, String type, String mode, String value)256         public void attributeDecl(String eName, String aName, String type, String mode, String value)
257             throws SAXException {
258             // System.out.println("Attribute\t" + eName + "\t" + aName + "\t" + type + "\t" + mode + "\t" + value);
259             if (value != null) {
260                 add(eName, aName, value, true);
261                 defaults.put(eName + "|" + aName, value);
262             }
263             idmatcher.reset(type);
264             while (idmatcher.find()) {
265                 add(eName, aName, idmatcher.group(), true);
266             }
267         }
268 
269         /*
270          * (non-Javadoc)
271          *
272          * @see org.xml.sax.ext.DeclHandler#elementDecl(java.lang.String, java.lang.String)
273          */
274         @Override
elementDecl(String name, String model)275         public void elementDecl(String name, String model) throws SAXException {
276             // TODO Auto-generated method stub
277 
278         }
279 
280         /*
281          * (non-Javadoc)
282          *
283          * @see org.xml.sax.ext.DeclHandler#internalEntityDecl(java.lang.String, java.lang.String)
284          */
285         @Override
internalEntityDecl(String name, String value)286         public void internalEntityDecl(String name, String value) throws SAXException {
287             // TODO Auto-generated method stub
288 
289         }
290 
291         /*
292          * (non-Javadoc)
293          *
294          * @see org.xml.sax.ext.DeclHandler#externalEntityDecl(java.lang.String, java.lang.String, java.lang.String)
295          */
296         @Override
externalEntityDecl(String name, String publicId, String systemId)297         public void externalEntityDecl(String name, String publicId, String systemId) throws SAXException {
298             // TODO Auto-generated method stub
299 
300         }
301     }
302 
303     class MyContentHandler implements ContentHandler {
304 
305         /*
306          * (non-Javadoc)
307          *
308          * @see org.xml.sax.ContentHandler#endDocument()
309          */
310         @Override
endDocument()311         public void endDocument() throws SAXException {
312             // TODO Auto-generated method stub
313 
314         }
315 
316         /*
317          * (non-Javadoc)
318          *
319          * @see org.xml.sax.ContentHandler#startDocument()
320          */
321         @Override
startDocument()322         public void startDocument() throws SAXException {
323             // TODO Auto-generated method stub
324 
325         }
326 
327         /*
328          * (non-Javadoc)
329          *
330          * @see org.xml.sax.ContentHandler#characters(char[], int, int)
331          */
332         @Override
characters(char[] ch, int start, int length)333         public void characters(char[] ch, int start, int length) throws SAXException {
334             // TODO Auto-generated method stub
335 
336         }
337 
338         /*
339          * (non-Javadoc)
340          *
341          * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int)
342          */
343         @Override
ignorableWhitespace(char[] ch, int start, int length)344         public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
345             // TODO Auto-generated method stub
346 
347         }
348 
349         /*
350          * (non-Javadoc)
351          *
352          * @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String)
353          */
354         @Override
endPrefixMapping(String prefix)355         public void endPrefixMapping(String prefix) throws SAXException {
356             // TODO Auto-generated method stub
357 
358         }
359 
360         /*
361          * (non-Javadoc)
362          *
363          * @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String)
364          */
365         @Override
skippedEntity(String name)366         public void skippedEntity(String name) throws SAXException {
367             // TODO Auto-generated method stub
368 
369         }
370 
371         /*
372          * (non-Javadoc)
373          *
374          * @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator)
375          */
376         @Override
setDocumentLocator(Locator locator)377         public void setDocumentLocator(Locator locator) {
378             // TODO Auto-generated method stub
379 
380         }
381 
382         /*
383          * (non-Javadoc)
384          *
385          * @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, java.lang.String)
386          */
387         @Override
processingInstruction(String target, String data)388         public void processingInstruction(String target, String data) throws SAXException {
389             // TODO Auto-generated method stub
390 
391         }
392 
393         /*
394          * (non-Javadoc)
395          *
396          * @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String)
397          */
398         @Override
startPrefixMapping(String prefix, String uri)399         public void startPrefixMapping(String prefix, String uri) throws SAXException {
400             // TODO Auto-generated method stub
401 
402         }
403 
404         /*
405          * (non-Javadoc)
406          *
407          * @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
408          */
409         @Override
endElement(String namespaceURI, String localName, String qName)410         public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
411             // TODO Auto-generated method stub
412 
413         }
414 
415         /*
416          * (non-Javadoc)
417          *
418          * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String,
419          * org.xml.sax.Attributes)
420          */
421         @Override
startElement(String namespaceURI, String localName, String qName, Attributes attributes)422         public void startElement(String namespaceURI, String localName, String qName, Attributes attributes)
423             throws SAXException {
424             if (attributes == null) return;
425             for (int i = 0; i < attributes.getLength(); ++i) {
426                 String attribute = attributes.getQName(i);
427                 String value = attributes.getValue(i);
428                 add(qName, attribute, value, false);
429             }
430         }
431     }
432 
getElement_attribute_valueSet()433     public Map<String, Map<String, Set<String>[]>> getElement_attribute_valueSet() {
434         return element_attribute_valueSet;
435     }
436 }
437