* C++: Each inner sink class has a reference to the main outer sink.
* Java: Use non-static inner classes instead.
*/
- private static final class UnitDataSink extends UResource.TableSink {
- /**
- * Sink for a table of display patterns. For example,
- * unitsShort/duration/hour contains other{"{0} hrs"}.
- */
- class UnitPatternSink extends UResource.TableSink {
- String[] patterns;
-
- void setFormatterIfAbsent(int index, UResource.Value value, int minPlaceholders) {
- if (patterns == null) {
- EnumMap<FormatWidth, String[]> styleToPatterns =
- cacheData.unitToStyleToPatterns.get(unit);
- if (styleToPatterns == null) {
- styleToPatterns =
- new EnumMap<FormatWidth, String[]>(FormatWidth.class);
- cacheData.unitToStyleToPatterns.put(unit, styleToPatterns);
- } else {
- patterns = styleToPatterns.get(width);
- }
- if (patterns == null) {
- patterns = new String[MeasureFormatData.PATTERN_COUNT];
- styleToPatterns.put(width, patterns);
- }
+ private static final class UnitDataSink extends UResource.Sink {
+ void setFormatterIfAbsent(int index, UResource.Value value, int minPlaceholders) {
+ if (patterns == null) {
+ EnumMap<FormatWidth, String[]> styleToPatterns =
+ cacheData.unitToStyleToPatterns.get(unit);
+ if (styleToPatterns == null) {
+ styleToPatterns =
+ new EnumMap<FormatWidth, String[]>(FormatWidth.class);
+ cacheData.unitToStyleToPatterns.put(unit, styleToPatterns);
+ } else {
+ patterns = styleToPatterns.get(width);
}
- if (patterns[index] == null) {
- patterns[index] = SimpleFormatterImpl.compileToStringMinMaxArguments(
- value.getString(), sb, minPlaceholders, 1);
+ if (patterns == null) {
+ patterns = new String[MeasureFormatData.PATTERN_COUNT];
+ styleToPatterns.put(width, patterns);
}
}
+ if (patterns[index] == null) {
+ patterns[index] = SimpleFormatterImpl.compileToStringMinMaxArguments(
+ value.getString(), sb, minPlaceholders, 1);
+ }
+ }
- @Override
- public void put(UResource.Key key, UResource.Value value) {
- if (key.contentEquals("dnam")) {
- // Skip the unit display name for now.
- } else if (key.contentEquals("per")) {
- // For example, "{0}/h".
- setFormatterIfAbsent(MeasureFormatData.PER_UNIT_INDEX, value, 1);
- } else {
- // The key must be one of the plural form strings. For example:
- // one{"{0} hr"}
- // other{"{0} hrs"}
- setFormatterIfAbsent(StandardPlural.indexFromString(key), value, 0);
- }
+ /**
+ * Consume a display pattern. For example,
+ * unitsShort/duration/hour contains other{"{0} hrs"}.
+ */
+ void consumePattern(UResource.Key key, UResource.Value value) {
+ if (key.contentEquals("dnam")) {
+ // Skip the unit display name for now.
+ } else if (key.contentEquals("per")) {
+ // For example, "{0}/h".
+ setFormatterIfAbsent(MeasureFormatData.PER_UNIT_INDEX, value, 1);
+ } else {
+ // The key must be one of the plural form strings. For example:
+ // one{"{0} hr"}
+ // other{"{0} hrs"}
+ setFormatterIfAbsent(StandardPlural.indexFromString(key), value, 0);
}
}
- UnitPatternSink patternSink = new UnitPatternSink();
/**
- * Sink for a table of per-unit tables. For example,
+ * Consume a table of per-unit tables. For example,
* unitsShort/duration contains tables for duration-unit subtypes day & hour.
*/
- class UnitSubtypeSink extends UResource.TableSink {
- @Override
- public UResource.TableSink getOrCreateTableSink(UResource.Key key) {
- // Should we ignore or reject unknown units?
- unit = MeasureUnit.internalGetInstance(type, key.toString()); // never null
- // Trigger a fresh lookup of the patterns for this unit+width.
- patternSink.patterns = null;
- return patternSink;
+ void consumeSubtypeTable(UResource.Key key, UResource.Value value) {
+ unit = MeasureUnit.internalGetInstance(type, key.toString()); // never null
+ // Trigger a fresh lookup of the patterns for this unit+width.
+ patterns = null;
+
+ if (value.getType() == ICUResourceBundle.STRING) {
+ // Units like "coordinate" that don't have plural variants
+ setFormatterIfAbsent(StandardPlural.OTHER.ordinal(), value, 0);
+ } else if (value.getType() == ICUResourceBundle.TABLE) {
+ // Units that have plural variants
+ UResource.Table patternTableTable = value.getTable();
+ for (int i = 0; patternTableTable.getKeyAndValue(i, key, value); i++) {
+ consumePattern(key, value);
+ }
+ } else {
+ throw new ICUException("Data for unit '" + unit + "' is in an unknown format");
}
}
- UnitSubtypeSink subtypeSink = new UnitSubtypeSink();
/**
- * Sink for compound x-per-y display pattern. For example,
+ * Consume compound x-per-y display pattern. For example,
* unitsShort/compound/per may be "{0}/{1}".
*/
- class UnitCompoundSink extends UResource.TableSink {
- @Override
- public void put(UResource.Key key, UResource.Value value) {
- if (key.contentEquals("per")) {
- cacheData.styleToPerPattern.put(width,
- SimpleFormatterImpl.compileToStringMinMaxArguments(
- value.getString(), sb, 2, 2));
- }
+ void consumeCompoundPattern(UResource.Key key, UResource.Value value) {
+ if (key.contentEquals("per")) {
+ cacheData.styleToPerPattern.put(width,
+ SimpleFormatterImpl.compileToStringMinMaxArguments(
+ value.getString(), sb, 2, 2));
}
}
- UnitCompoundSink compoundSink = new UnitCompoundSink();
/**
- * Sink for a table of unit type tables. For example,
+ * Consume a table of unit type tables. For example,
* unitsShort contains tables for area & duration.
* It also contains a table for the compound/per pattern.
*/
- class UnitTypeSink extends UResource.TableSink {
- @Override
- public UResource.TableSink getOrCreateTableSink(UResource.Key key) {
- if (key.contentEquals("currency")) {
- // Skip.
- } else if (key.contentEquals("compound")) {
- if (!cacheData.hasPerFormatter(width)) {
- return compoundSink;
+ void consumeUnitTypesTable(UResource.Key key, UResource.Value value) {
+ if (key.contentEquals("currency")) {
+ // Skip.
+ } else if (key.contentEquals("compound")) {
+ if (!cacheData.hasPerFormatter(width)) {
+ UResource.Table compoundTable = value.getTable();
+ for (int i = 0; compoundTable.getKeyAndValue(i, key, value); i++) {
+ consumeCompoundPattern(key, value);
}
- } else {
- type = key.toString();
- return subtypeSink;
}
- return null;
+ } else {
+ type = key.toString();
+ UResource.Table subtypeTable = value.getTable();
+ for (int i = 0; subtypeTable.getKeyAndValue(i, key, value); i++) {
+ consumeSubtypeTable(key, value);
+ }
}
}
- UnitTypeSink typeSink = new UnitTypeSink();
UnitDataSink(MeasureFormatData outputData) {
cacheData = outputData;
}
- @Override
- public void put(UResource.Key key, UResource.Value value) {
+
+ void consumeAlias(UResource.Key key, UResource.Value value) {
// Handle aliases like
// units:alias{"/LOCALE/unitsShort"}
// which should only occur in the root bundle.
- if (value.getType() != ICUResourceBundle.ALIAS) { return; }
FormatWidth sourceWidth = widthFromKey(key);
if (sourceWidth == null) {
// Alias from something we don't care about.
}
cacheData.widthFallback[sourceWidth.ordinal()] = targetWidth;
}
- @Override
- public UResource.TableSink getOrCreateTableSink(UResource.Key key) {
+
+ public void consumeTable(UResource.Key key, UResource.Value value) {
if ((width = widthFromKey(key)) != null) {
- return typeSink;
+ UResource.Table unitTypesTable = value.getTable();
+ for (int i = 0; unitTypesTable.getKeyAndValue(i, key, value); i++) {
+ consumeUnitTypesTable(key, value);
+ }
}
- return null;
}
static FormatWidth widthFromKey(UResource.Key key) {
return null;
}
+ @Override
+ public void put(UResource.Key key, UResource.Value value, boolean noFallback) {
+ // Main entry point to sink
+ UResource.Table widthsTable = value.getTable();
+ for (int i = 0; widthsTable.getKeyAndValue(i, key, value); i++) {
+ if (value.getType() == ICUResourceBundle.ALIAS) {
+ consumeAlias(key, value);
+ } else {
+ consumeTable(key, value);
+ }
+ }
+ }
+
// Output data.
MeasureFormatData cacheData;
// Temporary
StringBuilder sb = new StringBuilder();
+ String[] patterns;
}
/**
(ICUResourceBundle)UResourceBundle.getBundleInstance(ICUData.ICU_UNIT_BASE_NAME, locale);
MeasureFormatData cacheData = new MeasureFormatData();
UnitDataSink sink = new UnitDataSink(cacheData);
- resource.getAllTableItemsWithFallback("", sink);
+ resource.getAllItemsWithFallback("", sink);
return cacheData;
}
private static final class MeasureUnitSink extends UResource.Sink {
@Override
public void put(UResource.Key key, UResource.Value value, boolean noFallback) {
- UResource.Table unitFormatsTable = value.getTable();
- for (int i1 = 0; unitFormatsTable.getKeyAndValue(i1, key, value); ++i1) {
-
- // Only consume the tables related to units, defined as those beginning with "units".
- if (!key.startsWith("units")) {
+ UResource.Table unitTypesTable = value.getTable();
+ for (int i2 = 0; unitTypesTable.getKeyAndValue(i2, key, value); ++i2) {
+ // Skip "compound" since it is treated differently from the other units
+ if (key.contentEquals("compound")) {
continue;
}
- UResource.Table unitTypesTable = value.getTable();
- for (int i2 = 0; unitTypesTable.getKeyAndValue(i2, key, value); ++i2) {
-
- // Special case: "compound" does not have plural variants.
- if (key.contentEquals("compound")) {
- continue;
- }
-
- String unitType = key.toString();
-
- UResource.Table unitNamesTable = value.getTable();
- for (int i3 = 0; unitNamesTable.getKeyAndValue(i3, key, value); ++i3) {
- String unitName = key.toString();
- internalGetInstance(unitType, unitName);
- }
+ String unitType = key.toString();
+ UResource.Table unitNamesTable = value.getTable();
+ for (int i3 = 0; unitNamesTable.getKeyAndValue(i3, key, value); ++i3) {
+ String unitName = key.toString();
+ internalGetInstance(unitType, unitName);
}
}
}
// Load the unit types. Use English, since we know that that is a superset.
ICUResourceBundle rb1 = (ICUResourceBundle) UResourceBundle.getBundleInstance(
- ICUData.ICU_BASE_NAME,
+ ICUData.ICU_UNIT_BASE_NAME,
"en");
- rb1.getAllItemsWithFallback("", new MeasureUnitSink());
+ rb1.getAllItemsWithFallback("units", new MeasureUnitSink());
// Load the currencies
ICUResourceBundle rb2 = (ICUResourceBundle) UResourceBundle.getBundleInstance(