Home | History | Annotate | Download | only in impl
      1 //  2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html#License
      3 /*
      4  *******************************************************************************
      5  * Copyright (C) 2004-2016, International Business Machines Corporation and
      6  * others. All Rights Reserved.
      7  *******************************************************************************
      8  */
      9 package com.ibm.icu.impl;
     10 
     11 import java.nio.ByteBuffer;
     12 import java.util.HashMap;
     13 import java.util.Set;
     14 import java.util.TreeSet;
     15 
     16 import com.ibm.icu.util.UResourceBundle;
     17 import com.ibm.icu.util.UResourceTypeMismatchException;
     18 
     19 class ICUResourceBundleImpl extends ICUResourceBundle {
     20     protected int resource;
     21 
     22     protected ICUResourceBundleImpl(ICUResourceBundleImpl container, String key, int resource) {
     23         super(container, key);
     24         this.resource = resource;
     25     }
     26     ICUResourceBundleImpl(WholeBundle wholeBundle) {
     27         super(wholeBundle);
     28         resource = wholeBundle.reader.getRootResource();
     29     }
     30     public int getResource() {
     31         return resource;
     32     }
     33     protected final ICUResourceBundle createBundleObject(String _key,
     34                                                          int _resource,
     35                                                          HashMap<String, String> aliasesVisited,
     36                                                          UResourceBundle requested) {
     37         switch(ICUResourceBundleReader.RES_GET_TYPE(_resource)) {
     38         case STRING :
     39         case STRING_V2:
     40             return new ICUResourceBundleImpl.ResourceString(this, _key, _resource);
     41         case BINARY:
     42             return new ICUResourceBundleImpl.ResourceBinary(this, _key, _resource);
     43         case ALIAS:
     44             return getAliasedResource(this, null, 0, _key, _resource, aliasesVisited, requested);
     45         case INT:
     46             return new ICUResourceBundleImpl.ResourceInt(this, _key, _resource);
     47         case INT_VECTOR:
     48             return new ICUResourceBundleImpl.ResourceIntVector(this, _key, _resource);
     49         case ARRAY:
     50         case ARRAY16:
     51             return new ICUResourceBundleImpl.ResourceArray(this, _key, _resource);
     52         case TABLE:
     53         case TABLE16:
     54         case TABLE32:
     55             return new ICUResourceBundleImpl.ResourceTable(this, _key, _resource);
     56         default :
     57             throw new IllegalStateException("The resource type is unknown");
     58         }
     59     }
     60 
     61     // Scalar values ------------------------------------------------------- ***
     62 
     63     private static final class ResourceBinary extends ICUResourceBundleImpl {
     64         @Override
     65         public int getType() {
     66             return BINARY;
     67         }
     68         @Override
     69         public ByteBuffer getBinary() {
     70             return wholeBundle.reader.getBinary(resource);
     71         }
     72         @Override
     73         public byte [] getBinary(byte []ba) {
     74             return wholeBundle.reader.getBinary(resource, ba);
     75         }
     76         ResourceBinary(ICUResourceBundleImpl container, String key, int resource) {
     77             super(container, key, resource);
     78         }
     79     }
     80     private static final class ResourceInt extends ICUResourceBundleImpl {
     81         @Override
     82         public int getType() {
     83             return INT;
     84         }
     85         @Override
     86         public int getInt() {
     87             return ICUResourceBundleReader.RES_GET_INT(resource);
     88         }
     89         @Override
     90         public int getUInt() {
     91             return ICUResourceBundleReader.RES_GET_UINT(resource);
     92         }
     93         ResourceInt(ICUResourceBundleImpl container, String key, int resource) {
     94             super(container, key, resource);
     95         }
     96     }
     97     private static final class ResourceString extends ICUResourceBundleImpl {
     98         private String value;
     99         @Override
    100         public int getType() {
    101             return STRING;
    102         }
    103         @Override
    104         public String getString() {
    105             if (value != null) {
    106                 return value;
    107             }
    108             return wholeBundle.reader.getString(resource);
    109         }
    110         ResourceString(ICUResourceBundleImpl container, String key, int resource) {
    111             super(container, key, resource);
    112             String s = wholeBundle.reader.getString(resource);
    113             // Allow the reader cache's SoftReference to do its job.
    114             if (s.length() < ICUResourceBundleReader.LARGE_SIZE / 2 ||
    115                     CacheValue.futureInstancesWillBeStrong()) {
    116                 value = s;
    117             }
    118         }
    119     }
    120     private static final class ResourceIntVector extends ICUResourceBundleImpl {
    121         @Override
    122         public int getType() {
    123             return INT_VECTOR;
    124         }
    125         @Override
    126         public int[] getIntVector() {
    127             return wholeBundle.reader.getIntVector(resource);
    128         }
    129         ResourceIntVector(ICUResourceBundleImpl container, String key, int resource) {
    130             super(container, key, resource);
    131         }
    132     }
    133 
    134     // Container values ---------------------------------------------------- ***
    135 
    136     static abstract class ResourceContainer extends ICUResourceBundleImpl {
    137         protected ICUResourceBundleReader.Container value;
    138 
    139         @Override
    140         public int getSize() {
    141             return value.getSize();
    142         }
    143         @Override
    144         public String getString(int index) {
    145             int res = value.getContainerResource(wholeBundle.reader, index);
    146             if (res == RES_BOGUS) {
    147                 throw new IndexOutOfBoundsException();
    148             }
    149             String s = wholeBundle.reader.getString(res);
    150             if (s != null) {
    151                 return s;
    152             }
    153             return super.getString(index);
    154         }
    155         protected int getContainerResource(int index) {
    156             return value.getContainerResource(wholeBundle.reader, index);
    157         }
    158         protected UResourceBundle createBundleObject(int index, String resKey, HashMap<String, String> aliasesVisited,
    159                                                      UResourceBundle requested) {
    160             int item = getContainerResource(index);
    161             if (item == RES_BOGUS) {
    162                 throw new IndexOutOfBoundsException();
    163             }
    164             return createBundleObject(resKey, item, aliasesVisited, requested);
    165         }
    166 
    167         ResourceContainer(ICUResourceBundleImpl container, String key, int resource) {
    168             super(container, key, resource);
    169         }
    170         ResourceContainer(WholeBundle wholeBundle) {
    171             super(wholeBundle);
    172         }
    173     }
    174     static class ResourceArray extends ResourceContainer {
    175         @Override
    176         public int getType() {
    177             return ARRAY;
    178         }
    179         @Override
    180         protected String[] handleGetStringArray() {
    181             ICUResourceBundleReader reader = wholeBundle.reader;
    182             int length = value.getSize();
    183             String[] strings = new String[length];
    184             for (int i = 0; i < length; ++i) {
    185                 String s = reader.getString(value.getContainerResource(reader, i));
    186                 if (s == null) {
    187                     throw new UResourceTypeMismatchException("");
    188                 }
    189                 strings[i] = s;
    190             }
    191             return strings;
    192         }
    193         @Override
    194         public String[] getStringArray() {
    195             return handleGetStringArray();
    196         }
    197         @Override
    198         protected UResourceBundle handleGet(String indexStr, HashMap<String, String> aliasesVisited,
    199                                             UResourceBundle requested) {
    200             int i = Integer.parseInt(indexStr);
    201             return createBundleObject(i, indexStr, aliasesVisited, requested);
    202         }
    203         @Override
    204         protected UResourceBundle handleGet(int index, HashMap<String, String> aliasesVisited,
    205                                             UResourceBundle requested) {
    206             return createBundleObject(index, Integer.toString(index), aliasesVisited, requested);
    207         }
    208         ResourceArray(ICUResourceBundleImpl container, String key, int resource) {
    209             super(container, key, resource);
    210             value = wholeBundle.reader.getArray(resource);
    211         }
    212     }
    213     static class ResourceTable extends ResourceContainer {
    214         @Override
    215         public int getType() {
    216             return TABLE;
    217         }
    218         protected String getKey(int index) {
    219             return ((ICUResourceBundleReader.Table)value).getKey(wholeBundle.reader, index);
    220         }
    221         @Override
    222         protected Set<String> handleKeySet() {
    223             ICUResourceBundleReader reader = wholeBundle.reader;
    224             TreeSet<String> keySet = new TreeSet<String>();
    225             ICUResourceBundleReader.Table table = (ICUResourceBundleReader.Table)value;
    226             for (int i = 0; i < table.getSize(); ++i) {
    227                 keySet.add(table.getKey(reader, i));
    228             }
    229             return keySet;
    230         }
    231         @Override
    232         protected UResourceBundle handleGet(String resKey, HashMap<String, String> aliasesVisited,
    233                                             UResourceBundle requested) {
    234             int i = ((ICUResourceBundleReader.Table)value).findTableItem(wholeBundle.reader, resKey);
    235             if (i < 0) {
    236                 return null;
    237             }
    238             return createBundleObject(resKey, getContainerResource(i), aliasesVisited, requested);
    239         }
    240         @Override
    241         protected UResourceBundle handleGet(int index, HashMap<String, String> aliasesVisited,
    242                                             UResourceBundle requested) {
    243             String itemKey = ((ICUResourceBundleReader.Table)value).getKey(wholeBundle.reader, index);
    244             if (itemKey == null) {
    245                 throw new IndexOutOfBoundsException();
    246             }
    247             return createBundleObject(itemKey, getContainerResource(index), aliasesVisited, requested);
    248         }
    249         @Override
    250         protected Object handleGetObject(String key) {
    251             // Fast path for common cases: Avoid creating UResourceBundles if possible.
    252             // It would be even better if we could override getString(key)/getStringArray(key),
    253             // so that we know the expected object type,
    254             // but those are final in java.util.ResourceBundle.
    255             ICUResourceBundleReader reader = wholeBundle.reader;
    256             int index = ((ICUResourceBundleReader.Table)value).findTableItem(reader, key);
    257             if (index >= 0) {
    258                 int res = value.getContainerResource(reader, index);
    259                 // getString(key)
    260                 String s = reader.getString(res);
    261                 if (s != null) {
    262                     return s;
    263                 }
    264                 // getStringArray(key)
    265                 ICUResourceBundleReader.Container array = reader.getArray(res);
    266                 if (array != null) {
    267                     int length = array.getSize();
    268                     String[] strings = new String[length];
    269                     for (int j = 0;; ++j) {
    270                         if (j == length) {
    271                             return strings;
    272                         }
    273                         s = reader.getString(array.getContainerResource(reader, j));
    274                         if (s == null) {
    275                             // Equivalent to resolveObject(key, requested):
    276                             // If this is not a string array,
    277                             // then build and return a UResourceBundle.
    278                             break;
    279                         }
    280                         strings[j] = s;
    281                     }
    282                 }
    283             }
    284             return super.handleGetObject(key);
    285         }
    286         /**
    287          * Returns a String if found, or null if not found or if the key item is not a string.
    288          */
    289         String findString(String key) {
    290             ICUResourceBundleReader reader = wholeBundle.reader;
    291             int index = ((ICUResourceBundleReader.Table)value).findTableItem(reader, key);
    292             if (index < 0) {
    293                 return null;
    294             }
    295             return reader.getString(value.getContainerResource(reader, index));
    296         }
    297         ResourceTable(ICUResourceBundleImpl container, String key, int resource) {
    298             super(container, key, resource);
    299             value = wholeBundle.reader.getTable(resource);
    300         }
    301         /**
    302          * Constructor for the root table of a bundle.
    303          */
    304         ResourceTable(WholeBundle wholeBundle, int rootRes) {
    305             super(wholeBundle);
    306             value = wholeBundle.reader.getTable(rootRes);
    307         }
    308     }
    309 }
    310