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 package com.motorolamobility.preflighting.core.applicationdata; 17 18 import java.util.ArrayList; 19 import java.util.HashMap; 20 import java.util.List; 21 import java.util.Map; 22 23 import org.w3c.dom.Document; 24 import org.w3c.dom.Node; 25 import org.w3c.dom.NodeList; 26 27 /*** 28 * This class is intended to be used to represent strings.xml files under values folders in a Android Application 29 */ 30 public class StringsElement extends XMLElement 31 { 32 private static final String RESOURCES_ELEMENT = "resources"; 33 34 private static final String STRING_ELEMENT = "string"; 35 36 private static final String STRING_ARRAY_ELEMENT = "string-array"; 37 38 private static final String STRING_NAME_ATTRIBUTE = "name"; 39 40 private Map<String, LocalizationValue> map; 41 42 /** 43 * Constructor which sets the minimum basic data. 44 * 45 * @param name Name of the element. 46 * @param parent String element's Parent. 47 */ 48 public StringsElement(String name, Element parent) 49 { 50 super(name, parent, Element.Type.FILE_STRINGS); 51 map = new HashMap<String, LocalizationValue>(); 52 } 53 54 /** 55 * Set the {@link Document} and load the Map. 56 */ 57 @Override 58 public void setDocument(Document document) 59 { 60 super.setDocument(document); 61 loadMap(); 62 } 63 64 /*** 65 * Loads the document nodes in a map 66 */ 67 private void loadMap() 68 { 69 Document doc = getDocument(); 70 if (doc != null) 71 { 72 NodeList list = doc.getElementsByTagName(RESOURCES_ELEMENT); 73 if (list.getLength() > 0) 74 { 75 //Get first resource element 76 Node rootNode = list.item(0); 77 78 //Get strings entries 79 NodeList nodes = rootNode.getChildNodes(); 80 Node node; 81 82 if (nodes.getLength() > 0) 83 { 84 int length = nodes.getLength(); 85 int i; 86 87 String key; 88 LocalizationValue value; 89 List<String> valuesList; 90 91 //For each entry of strings.xml, here represented by the document, create an entry in the map 92 for (i = 0; i < length; i++) 93 { 94 node = nodes.item(i); 95 if (node instanceof org.w3c.dom.Element) 96 { 97 //Single Value 98 if (node.getNodeName().equals(STRING_ELEMENT)) 99 { 100 key = 101 node.getAttributes().getNamedItem(STRING_NAME_ATTRIBUTE) 102 .getNodeValue(); 103 value = 104 new LocalizationValue(ValueType.SINGLE, 105 node.getTextContent(), null); 106 107 this.addEntry(key, value); 108 } 109 //String-array 110 else if (node.getNodeName().equals(STRING_ARRAY_ELEMENT)) 111 { 112 key = 113 node.getAttributes().getNamedItem(STRING_NAME_ATTRIBUTE) 114 .getNodeValue(); 115 116 valuesList = new ArrayList<String>(); 117 118 //Read Array items 119 NodeList itemNodes = node.getChildNodes(); 120 if (itemNodes.getLength() > 0) 121 { 122 int j; 123 for (j = 0; j < length; j++) 124 { 125 if (itemNodes.item(j) instanceof org.w3c.dom.Element) 126 { 127 if (itemNodes.item(j).getTextContent().length() > 0) 128 { 129 valuesList.add(itemNodes.item(j).getTextContent()); 130 } 131 } 132 } 133 } 134 135 value = new LocalizationValue(ValueType.ARRAY, null, valuesList); 136 this.addEntry(key, value); 137 } 138 139 } 140 141 } 142 } 143 } 144 } 145 } 146 147 /*** 148 * Gets a list of keys from strings.xml represented by this element. 149 * 150 * @return Returns a list of keys. 151 */ 152 public List<String> getKeyList() 153 { 154 List<String> result = new ArrayList<String>(); 155 result.addAll(map.keySet()); 156 return result; 157 } 158 159 /** 160 * Adds an entry to the map. 161 * Intend to be used for creation of elements that does not represent a existing file. 162 * (e.g. Union of many strings.xml of the same language). 163 * 164 * @param key The string that represents the key. 165 * @param value A single string value or a List of strings in case the value is an array 166 */ 167 @SuppressWarnings("unchecked") 168 public void addEntry(String key, Object value) 169 { 170 if (value instanceof String) 171 { 172 map.put(key, new LocalizationValue(ValueType.SINGLE, (String) value, null)); 173 } 174 else if (value instanceof List) 175 { 176 map.put(key, new LocalizationValue(ValueType.ARRAY, null, (List<String>) value)); 177 } 178 else if (value instanceof LocalizationValue) 179 { 180 map.put(key, (LocalizationValue) value); 181 } 182 } 183 184 /*** 185 * Check if the element contains a specific key. 186 * 187 * @param key The key to be checked. 188 * @return Returns <code>true</code> if yes, <code>false</code> otherwise. 189 */ 190 public boolean containsKey(String key) 191 { 192 return map.containsKey(key); 193 } 194 195 /*** 196 * Check if the element contains values for a specific key. 197 * 198 * @param key Key to be checked. 199 * @return Returns <code>true</code> if yes, <code>false</code> otherwise. 200 */ 201 public boolean containsValue(String key) 202 { 203 return (getValue(key) != null); 204 } 205 206 /** 207 * Given a certain key, its value is returned. 208 * 209 * @param key Key which is related to the value to be retrieved. 210 * 211 * @return Returns a certain value based on a key. 212 */ 213 public Object getValue(String key) 214 { 215 Object result = null; 216 if (map != null) 217 { 218 LocalizationValue value = map.get(key); 219 if (value != null) 220 { 221 if (value.getType() == ValueType.SINGLE) 222 { 223 result = value.getValue(); 224 } 225 else if (value.getType() == ValueType.ARRAY) 226 { 227 result = value.getValues(); 228 } 229 } 230 } 231 return result; 232 } 233 234 //Localization value 235 236 /*** 237 * Enumeration that represents the possible types of a value. 238 */ 239 public enum ValueType 240 { 241 /** 242 * The value is a single element. 243 */ 244 SINGLE, 245 /** 246 * The value is an array of values. 247 */ 248 ARRAY, 249 /** 250 * The value is a plural representation of value. 251 */ 252 PLURAL 253 }; 254 255 /** 256 * Class that represents a localization value. Can be a single value, an array or a plural 257 */ 258 class LocalizationValue 259 { 260 /** 261 * Constructor which sets the minimum necessary data. 262 * 263 * @param type The type of Location value. 264 * @param value The value. 265 * @param values List of values. 266 */ 267 public LocalizationValue(ValueType type, String value, List<String> values) 268 { 269 this.type = type; 270 this.value = value; 271 this.values = values; 272 } 273 274 private final ValueType type; 275 276 private final String value; 277 278 private List<String> values = new ArrayList<String>(); 279 280 /** 281 * Gets the type. 282 * 283 * @return Returns the {@link ValueType}. 284 */ 285 public ValueType getType() 286 { 287 return type; 288 } 289 290 /** 291 * Gets the value. 292 * 293 * @return Returns the value. 294 */ 295 public String getValue() 296 { 297 return value; 298 } 299 300 /** 301 * Gets the list of values. 302 * 303 * @return Returns the list of values. 304 */ 305 public List<String> getValues() 306 { 307 return values; 308 } 309 } 310 311 /** 312 * Clean the create Map. 313 */ 314 @Override 315 public void clean() 316 { 317 super.clean(); 318 if (map != null) 319 { 320 map.clear(); 321 } 322 this.map = null; 323 } 324 325 } 326