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.latin.maketext; 18 19import org.xml.sax.Attributes; 20import org.xml.sax.SAXException; 21import org.xml.sax.ext.DefaultHandler2; 22 23import java.io.IOException; 24import java.io.InputStream; 25import java.util.ArrayList; 26import java.util.Collections; 27import java.util.HashMap; 28import java.util.List; 29import java.util.Map; 30 31import javax.xml.parsers.ParserConfigurationException; 32import javax.xml.parsers.SAXParser; 33import javax.xml.parsers.SAXParserFactory; 34 35public class StringResourceMap { 36 // String resource list. 37 private final List<StringResource> mResources; 38 // Name to string resource map. 39 private final Map<String, StringResource> mResourcesMap; 40 41 public StringResourceMap(final InputStream is) { 42 final StringResourceHandler handler = new StringResourceHandler(); 43 final SAXParserFactory factory = SAXParserFactory.newInstance(); 44 factory.setNamespaceAware(true); 45 try { 46 final SAXParser parser = factory.newSAXParser(); 47 // In order to get comment tag. 48 parser.setProperty("http://xml.org/sax/properties/lexical-handler", handler); 49 parser.parse(is, handler); 50 } catch (ParserConfigurationException e) { 51 } catch (SAXException e) { 52 throw new RuntimeException(e.getMessage()); 53 } catch (IOException e) { 54 } 55 56 mResources = Collections.unmodifiableList(handler.mResources); 57 final HashMap<String,StringResource> map = new HashMap<String,StringResource>(); 58 for (final StringResource res : mResources) { 59 map.put(res.mName, res); 60 } 61 mResourcesMap = map; 62 } 63 64 public List<StringResource> getResources() { 65 return mResources; 66 } 67 68 public boolean contains(final String name) { 69 return mResourcesMap.containsKey(name); 70 } 71 72 public StringResource get(final String name) { 73 return mResourcesMap.get(name); 74 } 75 76 static class StringResourceHandler extends DefaultHandler2 { 77 private static final String TAG_RESOURCES = "resources"; 78 private static final String TAG_STRING = "string"; 79 private static final String ATTR_NAME = "name"; 80 81 final ArrayList<StringResource> mResources = new ArrayList<StringResource>(); 82 83 private String mName; 84 private final StringBuilder mValue = new StringBuilder(); 85 private final StringBuilder mComment = new StringBuilder(); 86 87 private void init() { 88 mName = null; 89 mComment.setLength(0); 90 } 91 92 @Override 93 public void comment(char[] ch, int start, int length) { 94 mComment.append(ch, start, length); 95 if (ch[start + length - 1] != '\n') { 96 mComment.append('\n'); 97 } 98 } 99 100 @Override 101 public void startElement(String uri, String localName, String qName, Attributes attr) { 102 if (TAG_RESOURCES.equals(localName)) { 103 init(); 104 } else if (TAG_STRING.equals(localName)) { 105 mName = attr.getValue(ATTR_NAME); 106 mValue.setLength(0); 107 } 108 } 109 110 @Override 111 public void characters(char[] ch, int start, int length) { 112 mValue.append(ch, start, length); 113 } 114 115 @Override 116 public void endElement(String uri, String localName, String qName) throws SAXException { 117 if (TAG_STRING.equals(localName)) { 118 if (mName == null) 119 throw new SAXException(TAG_STRING + " doesn't have name"); 120 final String comment = mComment.length() > 0 ? mComment.toString() : null; 121 String value = mValue.toString(); 122 if (value.startsWith("\"") && value.endsWith("\"")) { 123 // Trim surroundings double quote. 124 value = value.substring(1, value.length() - 1); 125 } 126 mResources.add(new StringResource(mName, value, comment)); 127 init(); 128 } 129 } 130 } 131} 132