Home | History | Annotate | Download | only in applicationdata
      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