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