1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html#License
4 ******************************************************************************
5 * Copyright (C) 2007-2015, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ******************************************************************************
10 package com.ibm.icu.impl.duration.impl;
12 import java.io.BufferedReader;
13 import java.io.IOException;
14 import java.io.InputStream;
15 import java.io.InputStreamReader;
16 import java.io.UnsupportedEncodingException;
17 import java.util.ArrayList;
18 import java.util.Collection;
19 import java.util.Collections;
20 import java.util.HashMap;
21 import java.util.List;
23 import java.util.MissingResourceException;
25 import com.ibm.icu.impl.ICUData;
26 import com.ibm.icu.util.ICUUncheckedIOException;
29 * A PeriodFormatterDataService that serves PeriodFormatterData objects based on
30 * data files stored as resources in this directory. These are text files named
31 * after the locale, for example, 'pfd_he_IL.txt' specifies an period formatter
32 * data file for Hebrew as spoken in Israel. Data is in a JSON-like format.
34 public class ResourceBasedPeriodFormatterDataService extends
35 PeriodFormatterDataService {
36 private Collection<String> availableLocales; // of String
38 private PeriodFormatterData lastData = null;
39 private String lastLocale = null;
40 private Map<String, PeriodFormatterData> cache = new HashMap<String, PeriodFormatterData>(); // String -> PeriodFormatterData
41 // private PeriodFormatterData fallbackFormatterData;
43 private static final String PATH = "data/";
45 private static final ResourceBasedPeriodFormatterDataService singleton = new ResourceBasedPeriodFormatterDataService();
48 * Returns the singleton instance of this class.
50 public static ResourceBasedPeriodFormatterDataService getInstance() {
55 * Constructs the service.
57 private ResourceBasedPeriodFormatterDataService() {
58 List<String> localeNames = new ArrayList<String>(); // of String
59 InputStream is = ICUData.getRequiredStream(getClass(), PATH
62 BufferedReader br = new BufferedReader(new InputStreamReader(is,
65 while (null != (string = br.readLine())) {
66 string = string.trim();
67 if (string.startsWith("#") || string.length() == 0) {
70 localeNames.add(string);
73 } catch (IOException e) {
74 throw new IllegalStateException("IO Error reading " + PATH
75 + "index.txt: " + e.toString());
79 } catch (IOException ignored) {
82 availableLocales = Collections.unmodifiableList(localeNames);
85 public PeriodFormatterData get(String localeName) {
86 // remove tag info including calendar, we don't use the calendar
87 int x = localeName.indexOf('@');
89 localeName = localeName.substring(0, x);
93 if (lastLocale != null && lastLocale.equals(localeName)) {
97 PeriodFormatterData ld = cache.get(localeName);
99 String ln = localeName;
100 while (!availableLocales.contains(ln)) {
101 int ix = ln.lastIndexOf("_");
103 ln = ln.substring(0, ix);
104 } else if (!"test".equals(ln)) {
112 String name = PATH + "pfd_" + ln + ".xml";
114 InputStreamReader reader = new InputStreamReader(
115 ICUData.getRequiredStream(getClass(), name), "UTF-8");
116 DataRecord dr = DataRecord.read(ln, new XMLRecordReader(reader));
120 // if (false && ln.equals("ar_EG")) {
121 // OutputStreamWriter osw = new
122 // OutputStreamWriter(System.out, "UTF-8");
123 // XMLRecordWriter xrw = new
124 // XMLRecordWriter(osw);
128 ld = new PeriodFormatterData(localeName, dr);
130 } catch (UnsupportedEncodingException e) {
131 throw new MissingResourceException(
132 "Unhandled encoding for resource " + name, name, "");
133 } catch (IOException e) {
134 throw new ICUUncheckedIOException(
135 "Failed to close() resource " + name, e);
138 throw new MissingResourceException(
139 "Duration data not found for " + localeName, PATH,
144 // ld = getFallbackFormatterData();
146 cache.put(localeName, ld);
149 lastLocale = localeName;
155 public Collection<String> getAvailableLocales() {
156 return availableLocales;
159 // PeriodFormatterData getFallbackFormatterData() {
160 // synchronized (this) {
161 // if (fallbackFormatterData == null) {
162 // DataRecord dr = new DataRecord(); // hack, no default, will die if used
163 // fallbackFormatterData = new PeriodFormatterData(null, dr);
165 // return fallbackFormatterData;