/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.motorolamobility.preflighting.core.applicationdata; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /*** * This class is intended to be used to represent strings.xml files under values folders in a Android Application */ public class StringsElement extends XMLElement { private static final String RESOURCES_ELEMENT = "resources"; private static final String STRING_ELEMENT = "string"; private static final String STRING_ARRAY_ELEMENT = "string-array"; private static final String STRING_NAME_ATTRIBUTE = "name"; private Map<String, LocalizationValue> map; /** * Constructor which sets the minimum basic data. * * @param name Name of the element. * @param parent String element's Parent. */ public StringsElement(String name, Element parent) { super(name, parent, Element.Type.FILE_STRINGS); map = new HashMap<String, LocalizationValue>(); } /** * Set the {@link Document} and load the Map. */ @Override public void setDocument(Document document) { super.setDocument(document); loadMap(); } /*** * Loads the document nodes in a map */ private void loadMap() { Document doc = getDocument(); if (doc != null) { NodeList list = doc.getElementsByTagName(RESOURCES_ELEMENT); if (list.getLength() > 0) { //Get first resource element Node rootNode = list.item(0); //Get strings entries NodeList nodes = rootNode.getChildNodes(); Node node; if (nodes.getLength() > 0) { int length = nodes.getLength(); int i; String key; LocalizationValue value; List<String> valuesList; //For each entry of strings.xml, here represented by the document, create an entry in the map for (i = 0; i < length; i++) { node = nodes.item(i); if (node instanceof org.w3c.dom.Element) { //Single Value if (node.getNodeName().equals(STRING_ELEMENT)) { key = node.getAttributes().getNamedItem(STRING_NAME_ATTRIBUTE) .getNodeValue(); value = new LocalizationValue(ValueType.SINGLE, node.getTextContent(), null); this.addEntry(key, value); } //String-array else if (node.getNodeName().equals(STRING_ARRAY_ELEMENT)) { key = node.getAttributes().getNamedItem(STRING_NAME_ATTRIBUTE) .getNodeValue(); valuesList = new ArrayList<String>(); //Read Array items NodeList itemNodes = node.getChildNodes(); if (itemNodes.getLength() > 0) { int j; for (j = 0; j < length; j++) { if (itemNodes.item(j) instanceof org.w3c.dom.Element) { if (itemNodes.item(j).getTextContent().length() > 0) { valuesList.add(itemNodes.item(j).getTextContent()); } } } } value = new LocalizationValue(ValueType.ARRAY, null, valuesList); this.addEntry(key, value); } } } } } } } /*** * Gets a list of keys from strings.xml represented by this element. * * @return Returns a list of keys. */ public List<String> getKeyList() { List<String> result = new ArrayList<String>(); result.addAll(map.keySet()); return result; } /** * Adds an entry to the map. * Intend to be used for creation of elements that does not represent a existing file. * (e.g. Union of many strings.xml of the same language). * * @param key The string that represents the key. * @param value A single string value or a List of strings in case the value is an array */ @SuppressWarnings("unchecked") public void addEntry(String key, Object value) { if (value instanceof String) { map.put(key, new LocalizationValue(ValueType.SINGLE, (String) value, null)); } else if (value instanceof List) { map.put(key, new LocalizationValue(ValueType.ARRAY, null, (List<String>) value)); } else if (value instanceof LocalizationValue) { map.put(key, (LocalizationValue) value); } } /*** * Check if the element contains a specific key. * * @param key The key to be checked. * @return Returns <code>true</code> if yes, <code>false</code> otherwise. */ public boolean containsKey(String key) { return map.containsKey(key); } /*** * Check if the element contains values for a specific key. * * @param key Key to be checked. * @return Returns <code>true</code> if yes, <code>false</code> otherwise. */ public boolean containsValue(String key) { return (getValue(key) != null); } /** * Given a certain key, its value is returned. * * @param key Key which is related to the value to be retrieved. * * @return Returns a certain value based on a key. */ public Object getValue(String key) { Object result = null; if (map != null) { LocalizationValue value = map.get(key); if (value != null) { if (value.getType() == ValueType.SINGLE) { result = value.getValue(); } else if (value.getType() == ValueType.ARRAY) { result = value.getValues(); } } } return result; } //Localization value /*** * Enumeration that represents the possible types of a value. */ public enum ValueType { /** * The value is a single element. */ SINGLE, /** * The value is an array of values. */ ARRAY, /** * The value is a plural representation of value. */ PLURAL }; /** * Class that represents a localization value. Can be a single value, an array or a plural */ class LocalizationValue { /** * Constructor which sets the minimum necessary data. * * @param type The type of Location value. * @param value The value. * @param values List of values. */ public LocalizationValue(ValueType type, String value, List<String> values) { this.type = type; this.value = value; this.values = values; } private final ValueType type; private final String value; private List<String> values = new ArrayList<String>(); /** * Gets the type. * * @return Returns the {@link ValueType}. */ public ValueType getType() { return type; } /** * Gets the value. * * @return Returns the value. */ public String getValue() { return value; } /** * Gets the list of values. * * @return Returns the list of values. */ public List<String> getValues() { return values; } } /** * Clean the create Map. */ @Override public void clean() { super.clean(); if (map != null) { map.clear(); } this.map = null; } }