AbstractLDMLHandler.java revision 8845:4be14673b9bf
1/*
2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package build.tools.cldrconverter;
27
28import build.tools.cldrconverter.CLDRConverter.DraftType;
29import java.util.HashMap;
30import java.util.Map;
31import java.util.Set;
32import org.xml.sax.Attributes;
33import org.xml.sax.SAXException;
34import org.xml.sax.SAXParseException;
35import org.xml.sax.helpers.DefaultHandler;
36
37/**
38 * This is an abstract class for general LDML parsing purpose.
39 * LDMLParseHandler, SupplementLDMLParseHandler, and NumberingLDMLParseHandler
40 * are the subclasses of this class.
41 */
42
43abstract class AbstractLDMLHandler<V> extends DefaultHandler {
44    static final Map<String, String> DAY_OF_WEEK_MAP = new HashMap<>();
45    static {
46        DAY_OF_WEEK_MAP.put("sun", "1");
47        DAY_OF_WEEK_MAP.put("mon", "2");
48        DAY_OF_WEEK_MAP.put("tue", "3");
49        DAY_OF_WEEK_MAP.put("wed", "4");
50        DAY_OF_WEEK_MAP.put("thu", "5");
51        DAY_OF_WEEK_MAP.put("fri", "6");
52        DAY_OF_WEEK_MAP.put("sat", "7");
53    }
54    // Collected data in JRE locale data format.
55    private Map<String, V> data = new HashMap<>();
56
57    // The root Container
58    Container currentContainer = new Container("$ROOT", null);
59
60    AbstractLDMLHandler() {
61    }
62
63    Map<String, V> getData() {
64        return data;
65    }
66
67    V put(String key, V value) {
68        return data.put(key, value);
69    }
70
71    V get(String key) {
72        return data.get(key);
73    }
74
75    Set<String> keySet() {
76        return data.keySet();
77    }
78
79    /*
80     * It returns true if the data should be ignored based on the user
81     * defined acceptance level, which is listed with draft attribute in
82     * the cldr locale xml files.
83     * When the alt attribute is present, the data is always ignored since
84     * we always use the primary data
85     */
86    boolean isIgnored(Attributes attributes) {
87        if (attributes.getValue("alt") != null) {
88            return true;
89        }
90        String draftValue = attributes.getValue("draft");
91        if (draftValue != null) {
92            return DraftType.getDefault().ordinal() > DraftType.forKeyword(draftValue).ordinal();
93        }
94        return false;
95    }
96
97    void pushContainer(String qName, Attributes attributes) {
98        if (isIgnored(attributes) || currentContainer instanceof IgnoredContainer) {
99            currentContainer = new IgnoredContainer(qName, currentContainer);
100        } else {
101            currentContainer = new Container(qName, currentContainer);
102        }
103    }
104
105    void pushIgnoredContainer(String qName) {
106        currentContainer = new IgnoredContainer(qName, currentContainer);
107    }
108
109    void pushKeyContainer(String qName, Attributes attributes, String key) {
110        if (!pushIfIgnored(qName, attributes)) {
111            currentContainer = new KeyContainer(qName, currentContainer, key);
112        }
113    }
114
115    /**
116     * start an element that defines a string entry, with the value provided by the element's text.
117     */
118    void pushStringEntry(String qName, Attributes attributes, String key) {
119        if (!pushIfIgnored(qName, attributes)) {
120            currentContainer = new StringEntry(qName, currentContainer, key);
121        }
122    }
123
124    /**
125     * start an element that defines a string entry, with the value provided by an attribute value.
126     */
127    void pushStringEntry(String qName, Attributes attributes, String key, String value) {
128        if (!pushIfIgnored(qName, attributes)) {
129            currentContainer = new StringEntry(qName, currentContainer, key, value);
130        }
131    }
132
133    void pushStringArrayEntry(String qName, Attributes attributes, String key, int length) {
134        if (!pushIfIgnored(qName, attributes)) {
135            currentContainer = new StringArrayEntry(qName, currentContainer, key, length);
136        }
137    }
138
139    void pushStringArrayElement(String qName, Attributes attributes, int index) {
140        if (!pushIfIgnored(qName, attributes)) {
141            currentContainer = new StringArrayElement(qName, currentContainer, index);
142        }
143    }
144
145    private boolean pushIfIgnored(String qName, Attributes attributes) {
146        if (isIgnored(attributes) || currentContainer instanceof IgnoredContainer) {
147            pushIgnoredContainer(qName);
148            return true;
149        }
150        return false;
151    }
152
153    /**
154     * Obtains the key from the innermost containing container that provides one.
155     */
156    String getContainerKey() {
157        Container current = currentContainer;
158        while (current != null) {
159            if (current instanceof KeyContainer) {
160                return ((KeyContainer) current).getKey();
161            }
162            current = current.getParent();
163        }
164        return null;
165    }
166
167    @Override
168    public void characters(char[] ch, int start, int length) throws SAXException {
169        currentContainer.addCharacters(ch, start, length);
170    }
171
172    @SuppressWarnings(value = "CallToThreadDumpStack")
173    @Override
174    public void warning(SAXParseException e) throws SAXException {
175        e.printStackTrace();
176    }
177
178    @SuppressWarnings(value = "CallToThreadDumpStack")
179    @Override
180    public void error(SAXParseException e) throws SAXException {
181        e.printStackTrace();
182    }
183
184    @SuppressWarnings(value = "CallToThreadDumpStack")
185    @Override
186    public void fatalError(SAXParseException e) throws SAXException {
187        e.printStackTrace();
188        super.fatalError(e);
189    }
190}
191