| /* |
| ******************************************************************************* |
| * Copyright (C) 2004-2014, International Business Machines Corporation and |
| * others. All Rights Reserved. |
| ******************************************************************************* |
| */ |
| package com.ibm.icu.impl; |
| |
| import java.nio.ByteBuffer; |
| import java.util.HashMap; |
| import java.util.Set; |
| import java.util.TreeSet; |
| |
| import com.ibm.icu.util.UResourceBundle; |
| import com.ibm.icu.util.UResourceTypeMismatchException; |
| |
| class ICUResourceBundleImpl extends ICUResourceBundle { |
| protected ICUResourceBundleImpl(ICUResourceBundleImpl container, String key) { |
| super(container, key); |
| } |
| ICUResourceBundleImpl(WholeBundle wholeBundle) { |
| super(wholeBundle); |
| } |
| protected final ICUResourceBundle createBundleObject(String _key, |
| int _resource, |
| HashMap<String, String> aliasesVisited, |
| UResourceBundle requested) { |
| switch(ICUResourceBundleReader.RES_GET_TYPE(_resource)) { |
| case STRING : |
| case STRING_V2: |
| return new ICUResourceBundleImpl.ResourceString(this, _key, _resource); |
| case BINARY: |
| return new ICUResourceBundleImpl.ResourceBinary(this, _key, _resource); |
| case ALIAS: |
| return getAliasedResource(this, null, 0, _key, _resource, aliasesVisited, requested); |
| case INT: |
| return new ICUResourceBundleImpl.ResourceInt(this, _key, _resource); |
| case INT_VECTOR: |
| return new ICUResourceBundleImpl.ResourceIntVector(this, _key, _resource); |
| case ARRAY: |
| case ARRAY16: |
| return new ICUResourceBundleImpl.ResourceArray(this, _key, _resource); |
| case TABLE: |
| case TABLE16: |
| case TABLE32: |
| return new ICUResourceBundleImpl.ResourceTable(this, _key, _resource); |
| default : |
| throw new IllegalStateException("The resource type is unknown"); |
| } |
| } |
| |
| // Scalar values ------------------------------------------------------- *** |
| |
| private static final class ResourceBinary extends ICUResourceBundleImpl { |
| private int resource; |
| public int getType() { |
| return BINARY; |
| } |
| public ByteBuffer getBinary() { |
| return wholeBundle.reader.getBinary(resource); |
| } |
| public byte [] getBinary(byte []ba) { |
| return wholeBundle.reader.getBinary(resource, ba); |
| } |
| ResourceBinary(ICUResourceBundleImpl container, String key, int resource) { |
| super(container, key); |
| this.resource = resource; |
| } |
| } |
| private static final class ResourceInt extends ICUResourceBundleImpl { |
| private int resource; |
| public int getType() { |
| return INT; |
| } |
| public int getInt() { |
| return ICUResourceBundleReader.RES_GET_INT(resource); |
| } |
| public int getUInt() { |
| return ICUResourceBundleReader.RES_GET_UINT(resource); |
| } |
| ResourceInt(ICUResourceBundleImpl container, String key, int resource) { |
| super(container, key); |
| this.resource = resource; |
| } |
| } |
| private static final class ResourceString extends ICUResourceBundleImpl { |
| private int resource; |
| private String value; |
| public int getType() { |
| return STRING; |
| } |
| public String getString() { |
| if (value != null) { |
| return value; |
| } |
| return wholeBundle.reader.getString(resource); |
| } |
| ResourceString(ICUResourceBundleImpl container, String key, int resource) { |
| super(container, key); |
| this.resource = resource; |
| String s = wholeBundle.reader.getString(resource); |
| // Allow the reader cache's SoftReference to do its job. |
| if (s.length() < ICUResourceBundleReader.LARGE_SIZE / 2) { |
| value = s; |
| } |
| } |
| } |
| private static final class ResourceIntVector extends ICUResourceBundleImpl { |
| private int resource; |
| public int getType() { |
| return INT_VECTOR; |
| } |
| public int[] getIntVector() { |
| return wholeBundle.reader.getIntVector(resource); |
| } |
| ResourceIntVector(ICUResourceBundleImpl container, String key, int resource) { |
| super(container, key); |
| this.resource = resource; |
| } |
| } |
| |
| // Container values ---------------------------------------------------- *** |
| |
| static abstract class ResourceContainer extends ICUResourceBundleImpl { |
| protected ICUResourceBundleReader.Container value; |
| |
| public int getSize() { |
| return value.getSize(); |
| } |
| @Override |
| public String getString(int index) { |
| int res = value.getContainerResource(wholeBundle.reader, index); |
| if (res == RES_BOGUS) { |
| throw new IndexOutOfBoundsException(); |
| } |
| String s = wholeBundle.reader.getString(res); |
| if (s != null) { |
| return s; |
| } |
| return super.getString(index); |
| } |
| protected int getContainerResource(int index) { |
| return value.getContainerResource(wholeBundle.reader, index); |
| } |
| protected UResourceBundle createBundleObject(int index, String resKey, HashMap<String, String> aliasesVisited, |
| UResourceBundle requested) { |
| int item = getContainerResource(index); |
| if (item == RES_BOGUS) { |
| throw new IndexOutOfBoundsException(); |
| } |
| return createBundleObject(resKey, item, aliasesVisited, requested); |
| } |
| |
| ResourceContainer(ICUResourceBundleImpl container, String key) { |
| super(container, key); |
| } |
| ResourceContainer(WholeBundle wholeBundle) { |
| super(wholeBundle); |
| } |
| } |
| private static class ResourceArray extends ResourceContainer { |
| public int getType() { |
| return ARRAY; |
| } |
| protected String[] handleGetStringArray() { |
| ICUResourceBundleReader reader = wholeBundle.reader; |
| int length = value.getSize(); |
| String[] strings = new String[length]; |
| for (int i = 0; i < length; ++i) { |
| String s = reader.getString(value.getContainerResource(reader, i)); |
| if (s == null) { |
| throw new UResourceTypeMismatchException(""); |
| } |
| strings[i] = s; |
| } |
| return strings; |
| } |
| public String[] getStringArray() { |
| return handleGetStringArray(); |
| } |
| @Override |
| protected UResourceBundle handleGet(String indexStr, HashMap<String, String> aliasesVisited, |
| UResourceBundle requested) { |
| int i = Integer.parseInt(indexStr); |
| return createBundleObject(i, indexStr, aliasesVisited, requested); |
| } |
| @Override |
| protected UResourceBundle handleGet(int index, HashMap<String, String> aliasesVisited, |
| UResourceBundle requested) { |
| return createBundleObject(index, Integer.toString(index), aliasesVisited, requested); |
| } |
| ResourceArray(ICUResourceBundleImpl container, String key, int resource) { |
| super(container, key); |
| value = wholeBundle.reader.getArray(resource); |
| } |
| } |
| static class ResourceTable extends ResourceContainer { |
| public int getType() { |
| return TABLE; |
| } |
| protected String getKey(int index) { |
| return ((ICUResourceBundleReader.Table)value).getKey(wholeBundle.reader, index); |
| } |
| protected Set<String> handleKeySet() { |
| ICUResourceBundleReader reader = wholeBundle.reader; |
| TreeSet<String> keySet = new TreeSet<String>(); |
| ICUResourceBundleReader.Table table = (ICUResourceBundleReader.Table)value; |
| for (int i = 0; i < table.getSize(); ++i) { |
| keySet.add(table.getKey(reader, i)); |
| } |
| return keySet; |
| } |
| @Override |
| protected UResourceBundle handleGet(String resKey, HashMap<String, String> aliasesVisited, |
| UResourceBundle requested) { |
| int i = ((ICUResourceBundleReader.Table)value).findTableItem(wholeBundle.reader, resKey); |
| if (i < 0) { |
| return null; |
| } |
| return createBundleObject(resKey, getContainerResource(i), aliasesVisited, requested); |
| } |
| @Override |
| protected UResourceBundle handleGet(int index, HashMap<String, String> aliasesVisited, |
| UResourceBundle requested) { |
| String itemKey = ((ICUResourceBundleReader.Table)value).getKey(wholeBundle.reader, index); |
| if (itemKey == null) { |
| throw new IndexOutOfBoundsException(); |
| } |
| return createBundleObject(itemKey, getContainerResource(index), aliasesVisited, requested); |
| } |
| @Override |
| protected Object handleGetObject(String key) { |
| // Fast path for common cases: Avoid creating UResourceBundles if possible. |
| // It would be even better if we could override getString(key)/getStringArray(key), |
| // so that we know the expected object type, |
| // but those are final in java.util.ResourceBundle. |
| ICUResourceBundleReader reader = wholeBundle.reader; |
| int index = ((ICUResourceBundleReader.Table)value).findTableItem(reader, key); |
| if (index >= 0) { |
| int res = value.getContainerResource(reader, index); |
| // getString(key) |
| String s = reader.getString(res); |
| if (s != null) { |
| return s; |
| } |
| // getStringArray(key) |
| ICUResourceBundleReader.Container array = reader.getArray(res); |
| if (array != null) { |
| int length = array.getSize(); |
| String[] strings = new String[length]; |
| for (int j = 0;; ++j) { |
| if (j == length) { |
| return strings; |
| } |
| s = reader.getString(array.getContainerResource(reader, j)); |
| if (s == null) { |
| // Equivalent to resolveObject(key, requested): |
| // If this is not a string array, |
| // then build and return a UResourceBundle. |
| break; |
| } |
| strings[j] = s; |
| } |
| } |
| } |
| return super.handleGetObject(key); |
| } |
| /** |
| * Returns a String if found, or null if not found or if the key item is not a string. |
| */ |
| String findString(String key) { |
| ICUResourceBundleReader reader = wholeBundle.reader; |
| int index = ((ICUResourceBundleReader.Table)value).findTableItem(reader, key); |
| if (index < 0) { |
| return null; |
| } |
| return reader.getString(value.getContainerResource(reader, index)); |
| } |
| ResourceTable(ICUResourceBundleImpl container, String key, int resource) { |
| super(container, key); |
| value = wholeBundle.reader.getTable(resource); |
| } |
| /** |
| * Constructor for the root table of a bundle. |
| */ |
| ResourceTable(WholeBundle wholeBundle, int rootRes) { |
| super(wholeBundle); |
| value = wholeBundle.reader.getTable(rootRes); |
| } |
| } |
| } |