Home | History | Annotate | Download | only in tools
      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 
     17 package com.android.inputmethod.keyboard.tools;
     18 
     19 import org.xml.sax.Attributes;
     20 import org.xml.sax.SAXException;
     21 import org.xml.sax.SAXParseException;
     22 import org.xml.sax.ext.DefaultHandler2;
     23 
     24 import java.io.IOException;
     25 import java.io.InputStream;
     26 import java.util.ArrayList;
     27 import java.util.Collections;
     28 import java.util.HashMap;
     29 import java.util.List;
     30 import java.util.Locale;
     31 import java.util.Map;
     32 
     33 import javax.xml.parsers.ParserConfigurationException;
     34 import javax.xml.parsers.SAXParser;
     35 import javax.xml.parsers.SAXParserFactory;
     36 
     37 public class StringResourceMap {
     38     // Locale of this string resource map.
     39     public final Locale mLocale;
     40     // String resource list.
     41     private final List<StringResource> mResources;
     42     // Name to string resource map.
     43     private final Map<String, StringResource> mResourcesMap;
     44 
     45     // The length of String[] that is created from this {@link StringResourceMap}. The length is
     46     // calculated in {@link MoreKeysResources#dumpTexts(OutputStream)} and recorded by
     47     // {@link #setOutputArraySize(int)}. The recorded length is used as a part of comment by
     48     // {@link MoreKeysResources#dumpLocaleMap(OutputStream)} via {@link #getOutputArraySize()}.
     49     private int mOutputArraySize;
     50 
     51     public StringResourceMap(final String jarEntryName) {
     52         mLocale = JarUtils.getLocaleFromEntryName(jarEntryName);
     53         final StringResourceHandler handler = new StringResourceHandler();
     54         final SAXParserFactory factory = SAXParserFactory.newInstance();
     55         factory.setNamespaceAware(true);
     56         final InputStream stream = JarUtils.openResource(jarEntryName);
     57         try {
     58             final SAXParser parser = factory.newSAXParser();
     59             // In order to get comment tag.
     60             parser.setProperty("http://xml.org/sax/properties/lexical-handler", handler);
     61             parser.parse(stream, handler);
     62         } catch (ParserConfigurationException e) {
     63             throw new RuntimeException(e.getMessage(), e);
     64         } catch (SAXParseException e) {
     65             throw new RuntimeException(e.getMessage() + " at line " + e.getLineNumber()
     66                     + ", column " + e.getColumnNumber(), e);
     67         } catch (SAXException e) {
     68             throw new RuntimeException(e.getMessage(), e);
     69         } catch (IOException e) {
     70             throw new RuntimeException(e.getMessage(), e);
     71         } finally {
     72             JarUtils.close(stream);
     73         }
     74 
     75         mResources = Collections.unmodifiableList(handler.mResources);
     76         final HashMap<String, StringResource> map = new HashMap<>();
     77         for (final StringResource res : mResources) {
     78             map.put(res.mName, res);
     79         }
     80         mResourcesMap = map;
     81     }
     82 
     83     public List<StringResource> getResources() {
     84         return mResources;
     85     }
     86 
     87     public boolean contains(final String name) {
     88         return mResourcesMap.containsKey(name);
     89     }
     90 
     91     public StringResource get(final String name) {
     92         return mResourcesMap.get(name);
     93     }
     94 
     95     public void setOutputArraySize(final int arraySize) {
     96         mOutputArraySize = arraySize;
     97     }
     98 
     99     public int getOutputArraySize() {
    100         return mOutputArraySize;
    101     }
    102 
    103     static class StringResourceHandler extends DefaultHandler2 {
    104         private static final String TAG_RESOURCES = "resources";
    105         private static final String TAG_STRING = "string";
    106         private static final String ATTR_NAME = "name";
    107 
    108         final ArrayList<StringResource> mResources = new ArrayList<>();
    109 
    110         private String mName;
    111         private final StringBuilder mValue = new StringBuilder();
    112         private final StringBuilder mComment = new StringBuilder();
    113 
    114         private void init() {
    115             mName = null;
    116             mComment.setLength(0);
    117         }
    118 
    119         @Override
    120         public void comment(char[] ch, int start, int length) {
    121             mComment.append(ch, start, length);
    122             if (ch[start + length - 1] != '\n') {
    123                 mComment.append('\n');
    124             }
    125         }
    126 
    127         @Override
    128         public void startElement(String uri, String localName, String qName, Attributes attr) {
    129             if (TAG_RESOURCES.equals(localName)) {
    130                 init();
    131             } else if (TAG_STRING.equals(localName)) {
    132                 mName = attr.getValue(ATTR_NAME);
    133                 mValue.setLength(0);
    134             }
    135         }
    136 
    137         @Override
    138         public void characters(char[] ch, int start, int length) {
    139             mValue.append(ch, start, length);
    140         }
    141 
    142         @Override
    143         public void endElement(String uri, String localName, String qName) throws SAXException {
    144             if (TAG_STRING.equals(localName)) {
    145                 if (mName == null)
    146                     throw new SAXException(TAG_STRING + " doesn't have name");
    147                 final String comment = mComment.length() > 0 ? mComment.toString() : null;
    148                 String value = mValue.toString();
    149                 if (value.startsWith("\"") && value.endsWith("\"")) {
    150                     // Trim surroundings double quote.
    151                     value = value.substring(1, value.length() - 1);
    152                 }
    153                 mResources.add(new StringResource(mName, value, comment));
    154                 init();
    155             }
    156         }
    157     }
    158 }
    159