1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.inputmethod.keyboard.tools;
18
19import org.xml.sax.Attributes;
20import org.xml.sax.SAXException;
21import org.xml.sax.SAXParseException;
22import org.xml.sax.ext.DefaultHandler2;
23
24import java.io.IOException;
25import java.io.InputStream;
26import java.util.ArrayList;
27import java.util.Collections;
28import java.util.HashMap;
29import java.util.List;
30import java.util.Map;
31
32import javax.xml.parsers.ParserConfigurationException;
33import javax.xml.parsers.SAXParser;
34import javax.xml.parsers.SAXParserFactory;
35
36public class StringResourceMap {
37    // String resource list.
38    private final List<StringResource> mResources;
39    // Name to string resource map.
40    private final Map<String, StringResource> mResourcesMap;
41
42    public StringResourceMap(final InputStream is) {
43        final StringResourceHandler handler = new StringResourceHandler();
44        final SAXParserFactory factory = SAXParserFactory.newInstance();
45        factory.setNamespaceAware(true);
46        try {
47            final SAXParser parser = factory.newSAXParser();
48            // In order to get comment tag.
49            parser.setProperty("http://xml.org/sax/properties/lexical-handler", handler);
50            parser.parse(is, handler);
51        } catch (ParserConfigurationException e) {
52        } catch (SAXParseException e) {
53            throw new RuntimeException(e.getMessage() + " at line " + e.getLineNumber()
54                    + ", column " + e.getColumnNumber());
55        } catch (SAXException e) {
56            throw new RuntimeException(e.getMessage());
57        } catch (IOException e) {
58        }
59
60        mResources = Collections.unmodifiableList(handler.mResources);
61        final HashMap<String,StringResource> map = new HashMap<String,StringResource>();
62        for (final StringResource res : mResources) {
63            map.put(res.mName, res);
64        }
65        mResourcesMap = map;
66    }
67
68    public List<StringResource> getResources() {
69        return mResources;
70    }
71
72    public boolean contains(final String name) {
73        return mResourcesMap.containsKey(name);
74    }
75
76    public StringResource get(final String name) {
77        return mResourcesMap.get(name);
78    }
79
80    static class StringResourceHandler extends DefaultHandler2 {
81        private static final String TAG_RESOURCES = "resources";
82        private static final String TAG_STRING = "string";
83        private static final String ATTR_NAME = "name";
84
85        final ArrayList<StringResource> mResources = new ArrayList<StringResource>();
86
87        private String mName;
88        private final StringBuilder mValue = new StringBuilder();
89        private final StringBuilder mComment = new StringBuilder();
90
91        private void init() {
92            mName = null;
93            mComment.setLength(0);
94        }
95
96        @Override
97        public void comment(char[] ch, int start, int length) {
98            mComment.append(ch, start, length);
99            if (ch[start + length - 1] != '\n') {
100                mComment.append('\n');
101            }
102        }
103
104        @Override
105        public void startElement(String uri, String localName, String qName, Attributes attr) {
106            if (TAG_RESOURCES.equals(localName)) {
107                init();
108            } else if (TAG_STRING.equals(localName)) {
109                mName = attr.getValue(ATTR_NAME);
110                mValue.setLength(0);
111            }
112        }
113
114        @Override
115        public void characters(char[] ch, int start, int length) {
116            mValue.append(ch, start, length);
117        }
118
119        @Override
120        public void endElement(String uri, String localName, String qName) throws SAXException {
121            if (TAG_STRING.equals(localName)) {
122                if (mName == null)
123                    throw new SAXException(TAG_STRING + " doesn't have name");
124                final String comment = mComment.length() > 0 ? mComment.toString() : null;
125                String value = mValue.toString();
126                if (value.startsWith("\"") && value.endsWith("\"")) {
127                    // Trim surroundings double quote.
128                    value = value.substring(1, value.length() - 1);
129                }
130                mResources.add(new StringResource(mName, value, comment));
131                init();
132            }
133        }
134    }
135}
136