17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/*
27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
3bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * Copyright (C) 2004-2015, International Business Machines Corporation and
47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * others. All Rights Reserved.
57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.impl;
87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.nio.ByteBuffer;
107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.HashMap;
117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Set;
127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.TreeSet;
137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
14f8a0c400bbd62a2ea4ee9b77641f79cb443d2187Neil Fullerimport com.ibm.icu.impl.ICUResourceBundleReader.ReaderValue;
157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.UResourceBundle;
167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.UResourceTypeMismatchException;
177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertclass ICUResourceBundleImpl extends ICUResourceBundle {
197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected ICUResourceBundleImpl(ICUResourceBundleImpl container, String key) {
207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        super(container, key);
217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    ICUResourceBundleImpl(WholeBundle wholeBundle) {
237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        super(wholeBundle);
247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected final ICUResourceBundle createBundleObject(String _key,
267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                                         int _resource,
277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                                         HashMap<String, String> aliasesVisited,
287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                                         UResourceBundle requested) {
297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        switch(ICUResourceBundleReader.RES_GET_TYPE(_resource)) {
307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case STRING :
317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case STRING_V2:
327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return new ICUResourceBundleImpl.ResourceString(this, _key, _resource);
337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case BINARY:
347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return new ICUResourceBundleImpl.ResourceBinary(this, _key, _resource);
357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case ALIAS:
367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return getAliasedResource(this, null, 0, _key, _resource, aliasesVisited, requested);
377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case INT:
387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return new ICUResourceBundleImpl.ResourceInt(this, _key, _resource);
397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case INT_VECTOR:
407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return new ICUResourceBundleImpl.ResourceIntVector(this, _key, _resource);
417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case ARRAY:
427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case ARRAY16:
437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return new ICUResourceBundleImpl.ResourceArray(this, _key, _resource);
447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case TABLE:
457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case TABLE16:
467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case TABLE32:
477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return new ICUResourceBundleImpl.ResourceTable(this, _key, _resource);
487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        default :
497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            throw new IllegalStateException("The resource type is unknown");
507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Scalar values ------------------------------------------------------- ***
547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final class ResourceBinary extends ICUResourceBundleImpl {
567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private int resource;
577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public int getType() {
587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return BINARY;
597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public ByteBuffer getBinary() {
617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return wholeBundle.reader.getBinary(resource);
627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public byte [] getBinary(byte []ba) {
647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return wholeBundle.reader.getBinary(resource, ba);
657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ResourceBinary(ICUResourceBundleImpl container, String key, int resource) {
677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super(container, key);
687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            this.resource = resource;
697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final class ResourceInt extends ICUResourceBundleImpl {
727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private int resource;
737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public int getType() {
747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return INT;
757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public int getInt() {
777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return ICUResourceBundleReader.RES_GET_INT(resource);
787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public int getUInt() {
807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return ICUResourceBundleReader.RES_GET_UINT(resource);
817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ResourceInt(ICUResourceBundleImpl container, String key, int resource) {
837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super(container, key);
847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            this.resource = resource;
857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final class ResourceString extends ICUResourceBundleImpl {
887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private int resource;
897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private String value;
907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public int getType() {
917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return STRING;
927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public String getString() {
947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (value != null) {
957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return value;
967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return wholeBundle.reader.getString(resource);
987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ResourceString(ICUResourceBundleImpl container, String key, int resource) {
1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super(container, key);
1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            this.resource = resource;
1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String s = wholeBundle.reader.getString(resource);
1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Allow the reader cache's SoftReference to do its job.
10450522aa3c3343ab032b43a0ad44ece0a1f5194ceMarkus Scherer            if (s.length() < ICUResourceBundleReader.LARGE_SIZE / 2 ||
10550522aa3c3343ab032b43a0ad44ece0a1f5194ceMarkus Scherer                    CacheValue.futureInstancesWillBeStrong()) {
1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                value = s;
1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final class ResourceIntVector extends ICUResourceBundleImpl {
1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private int resource;
1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public int getType() {
1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return INT_VECTOR;
1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public int[] getIntVector() {
1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return wholeBundle.reader.getIntVector(resource);
1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ResourceIntVector(ICUResourceBundleImpl container, String key, int resource) {
1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super(container, key);
1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            this.resource = resource;
1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Container values ---------------------------------------------------- ***
1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static abstract class ResourceContainer extends ICUResourceBundleImpl {
1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected ICUResourceBundleReader.Container value;
1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public int getSize() {
1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return value.getSize();
1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @Override
1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public String getString(int index) {
1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int res = value.getContainerResource(wholeBundle.reader, index);
1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (res == RES_BOGUS) {
1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                throw new IndexOutOfBoundsException();
1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String s = wholeBundle.reader.getString(res);
1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (s != null) {
1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return s;
1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return super.getString(index);
1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected int getContainerResource(int index) {
1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return value.getContainerResource(wholeBundle.reader, index);
1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected UResourceBundle createBundleObject(int index, String resKey, HashMap<String, String> aliasesVisited,
1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                                     UResourceBundle requested) {
1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int item = getContainerResource(index);
1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (item == RES_BOGUS) {
1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                throw new IndexOutOfBoundsException();
1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return createBundleObject(resKey, item, aliasesVisited, requested);
1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ResourceContainer(ICUResourceBundleImpl container, String key) {
1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super(container, key);
1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ResourceContainer(WholeBundle wholeBundle) {
1607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super(wholeBundle);
1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
163f8a0c400bbd62a2ea4ee9b77641f79cb443d2187Neil Fuller    static class ResourceArray extends ResourceContainer {
1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public int getType() {
1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return ARRAY;
1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected String[] handleGetStringArray() {
1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            ICUResourceBundleReader reader = wholeBundle.reader;
1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int length = value.getSize();
1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String[] strings = new String[length];
1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (int i = 0; i < length; ++i) {
1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                String s = reader.getString(value.getContainerResource(reader, i));
1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (s == null) {
1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    throw new UResourceTypeMismatchException("");
1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                strings[i] = s;
1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return strings;
1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public String[] getStringArray() {
1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return handleGetStringArray();
1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @Override
1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected UResourceBundle handleGet(String indexStr, HashMap<String, String> aliasesVisited,
1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                            UResourceBundle requested) {
1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int i = Integer.parseInt(indexStr);
1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return createBundleObject(i, indexStr, aliasesVisited, requested);
1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @Override
1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected UResourceBundle handleGet(int index, HashMap<String, String> aliasesVisited,
1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                            UResourceBundle requested) {
1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return createBundleObject(index, Integer.toString(index), aliasesVisited, requested);
1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
194f8a0c400bbd62a2ea4ee9b77641f79cb443d2187Neil Fuller        /**
195f8a0c400bbd62a2ea4ee9b77641f79cb443d2187Neil Fuller         * @param key will be set during enumeration; input contents is ignored
196f8a0c400bbd62a2ea4ee9b77641f79cb443d2187Neil Fuller         * @param readerValue will be set during enumeration; input contents is ignored
197f8a0c400bbd62a2ea4ee9b77641f79cb443d2187Neil Fuller         * @param sink receives all array item values
198f8a0c400bbd62a2ea4ee9b77641f79cb443d2187Neil Fuller         */
1996cbfb9f6af6edc42d5636ce65b7b90d2301d8279Markus Scherer        void getAllItems(UResource.Key key, ReaderValue readerValue, UResource.ArraySink sink) {
200f8a0c400bbd62a2ea4ee9b77641f79cb443d2187Neil Fuller            ICUResourceBundleReader reader = wholeBundle.reader;
201f8a0c400bbd62a2ea4ee9b77641f79cb443d2187Neil Fuller            readerValue.reader = reader;
202f8a0c400bbd62a2ea4ee9b77641f79cb443d2187Neil Fuller            ((ICUResourceBundleReader.Array)value).getAllItems(reader, key, readerValue, sink);
203f8a0c400bbd62a2ea4ee9b77641f79cb443d2187Neil Fuller        }
2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ResourceArray(ICUResourceBundleImpl container, String key, int resource) {
2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super(container, key);
2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            value = wholeBundle.reader.getArray(resource);
2077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static class ResourceTable extends ResourceContainer {
2107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public int getType() {
2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return TABLE;
2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected String getKey(int index) {
2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return ((ICUResourceBundleReader.Table)value).getKey(wholeBundle.reader, index);
2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected Set<String> handleKeySet() {
2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            ICUResourceBundleReader reader = wholeBundle.reader;
2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            TreeSet<String> keySet = new TreeSet<String>();
2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            ICUResourceBundleReader.Table table = (ICUResourceBundleReader.Table)value;
2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (int i = 0; i < table.getSize(); ++i) {
2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                keySet.add(table.getKey(reader, i));
2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return keySet;
2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @Override
2267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected UResourceBundle handleGet(String resKey, HashMap<String, String> aliasesVisited,
2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                            UResourceBundle requested) {
2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int i = ((ICUResourceBundleReader.Table)value).findTableItem(wholeBundle.reader, resKey);
2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (i < 0) {
2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return null;
2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return createBundleObject(resKey, getContainerResource(i), aliasesVisited, requested);
2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @Override
2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected UResourceBundle handleGet(int index, HashMap<String, String> aliasesVisited,
2367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                            UResourceBundle requested) {
2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String itemKey = ((ICUResourceBundleReader.Table)value).getKey(wholeBundle.reader, index);
2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (itemKey == null) {
2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                throw new IndexOutOfBoundsException();
2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return createBundleObject(itemKey, getContainerResource(index), aliasesVisited, requested);
2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @Override
2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected Object handleGetObject(String key) {
2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Fast path for common cases: Avoid creating UResourceBundles if possible.
2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // It would be even better if we could override getString(key)/getStringArray(key),
2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // so that we know the expected object type,
2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // but those are final in java.util.ResourceBundle.
2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            ICUResourceBundleReader reader = wholeBundle.reader;
2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int index = ((ICUResourceBundleReader.Table)value).findTableItem(reader, key);
2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (index >= 0) {
2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int res = value.getContainerResource(reader, index);
2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // getString(key)
2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                String s = reader.getString(res);
2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (s != null) {
2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    return s;
2577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
2587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // getStringArray(key)
2597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                ICUResourceBundleReader.Container array = reader.getArray(res);
2607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (array != null) {
2617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    int length = array.getSize();
2627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    String[] strings = new String[length];
2637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    for (int j = 0;; ++j) {
2647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (j == length) {
2657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            return strings;
2667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
2677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        s = reader.getString(array.getContainerResource(reader, j));
2687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (s == null) {
2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // Equivalent to resolveObject(key, requested):
2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // If this is not a string array,
2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // then build and return a UResourceBundle.
2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
2737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
2747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        strings[j] = s;
2757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
2767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
2777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return super.handleGetObject(key);
2797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /**
2817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * Returns a String if found, or null if not found or if the key item is not a string.
2827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         */
2837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String findString(String key) {
2847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            ICUResourceBundleReader reader = wholeBundle.reader;
2857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int index = ((ICUResourceBundleReader.Table)value).findTableItem(reader, key);
2867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (index < 0) {
2877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return null;
2887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return reader.getString(value.getContainerResource(reader, index));
2907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
291f8a0c400bbd62a2ea4ee9b77641f79cb443d2187Neil Fuller        /**
292f8a0c400bbd62a2ea4ee9b77641f79cb443d2187Neil Fuller         * @param key will be set during enumeration; input contents is ignored
293f8a0c400bbd62a2ea4ee9b77641f79cb443d2187Neil Fuller         * @param readerValue will be set during enumeration; input contents is ignored
294f8a0c400bbd62a2ea4ee9b77641f79cb443d2187Neil Fuller         * @param sink receives all table item key-value pairs
295f8a0c400bbd62a2ea4ee9b77641f79cb443d2187Neil Fuller         */
2966cbfb9f6af6edc42d5636ce65b7b90d2301d8279Markus Scherer        void getAllItems(UResource.Key key, ReaderValue readerValue, UResource.TableSink sink) {
297f8a0c400bbd62a2ea4ee9b77641f79cb443d2187Neil Fuller            ICUResourceBundleReader reader = wholeBundle.reader;
298f8a0c400bbd62a2ea4ee9b77641f79cb443d2187Neil Fuller            readerValue.reader = reader;
299f8a0c400bbd62a2ea4ee9b77641f79cb443d2187Neil Fuller            ((ICUResourceBundleReader.Table)value).getAllItems(reader, key, readerValue, sink);
300f8a0c400bbd62a2ea4ee9b77641f79cb443d2187Neil Fuller        }
3017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ResourceTable(ICUResourceBundleImpl container, String key, int resource) {
3027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super(container, key);
3037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            value = wholeBundle.reader.getTable(resource);
3047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /**
3067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * Constructor for the root table of a bundle.
3077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         */
3087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ResourceTable(WholeBundle wholeBundle, int rootRes) {
3097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super(wholeBundle);
3107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            value = wholeBundle.reader.getTable(rootRes);
3117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}
314