]> granicus.if.org Git - icu/blob
7f70fbf4e18b887c231d8ad371dc85529aaadc15
[icu] /
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) 2007-2015, International Business Machines Corporation and
6  * others. All Rights Reserved.
7  ******************************************************************************
8  */
9
10 package com.ibm.icu.impl.duration.impl;
11
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;
22 import java.util.Map;
23 import java.util.MissingResourceException;
24
25 import com.ibm.icu.impl.ICUData;
26 import com.ibm.icu.util.ICUUncheckedIOException;
27
28 /**
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.
33  */
34 public class ResourceBasedPeriodFormatterDataService extends
35         PeriodFormatterDataService {
36     private Collection<String> availableLocales; // of String
37
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;
42
43     private static final String PATH = "data/";
44
45     private static final ResourceBasedPeriodFormatterDataService singleton = new ResourceBasedPeriodFormatterDataService();
46
47     /**
48      * Returns the singleton instance of this class.
49      */
50     public static ResourceBasedPeriodFormatterDataService getInstance() {
51         return singleton;
52     }
53
54     /**
55      * Constructs the service.
56      */
57     private ResourceBasedPeriodFormatterDataService() {
58         List<String> localeNames = new ArrayList<String>(); // of String
59         InputStream is = ICUData.getRequiredStream(getClass(), PATH
60                 + "index.txt");
61         try {
62             BufferedReader br = new BufferedReader(new InputStreamReader(is,
63                     "UTF-8"));
64             String string = null;
65             while (null != (string = br.readLine())) {
66                 string = string.trim();
67                 if (string.startsWith("#") || string.length() == 0) {
68                     continue;
69                 }
70                 localeNames.add(string);
71             }
72             br.close();
73         } catch (IOException e) {
74             throw new IllegalStateException("IO Error reading " + PATH
75                     + "index.txt: " + e.toString());
76         } finally {
77             try {
78                 is.close();
79             } catch (IOException ignored) {
80             }
81         }
82         availableLocales = Collections.unmodifiableList(localeNames);
83     }
84
85     public PeriodFormatterData get(String localeName) {
86         // remove tag info including calendar, we don't use the calendar
87         int x = localeName.indexOf('@');
88         if (x != -1) {
89             localeName = localeName.substring(0, x);
90         }
91
92         synchronized (this) {
93             if (lastLocale != null && lastLocale.equals(localeName)) {
94                 return lastData;
95             }
96
97             PeriodFormatterData ld = cache.get(localeName);
98             if (ld == null) {
99                 String ln = localeName;
100                 while (!availableLocales.contains(ln)) {
101                     int ix = ln.lastIndexOf("_");
102                     if (ix > -1) {
103                         ln = ln.substring(0, ix);
104                     } else if (!"test".equals(ln)) {
105                         ln = "test";
106                     } else {
107                         ln = null;
108                         break;
109                     }
110                 }
111                 if (ln != null) {
112                     String name = PATH + "pfd_" + ln + ".xml";
113                     try {
114                         InputStreamReader reader = new InputStreamReader(
115                                 ICUData.getRequiredStream(getClass(), name), "UTF-8");
116                         DataRecord dr = DataRecord.read(ln, new XMLRecordReader(reader));
117                         reader.close();
118                         if (dr != null) {
119                             // debug
120                             // if (false && ln.equals("ar_EG")) {
121                             // OutputStreamWriter osw = new
122                             // OutputStreamWriter(System.out, "UTF-8");
123                             // XMLRecordWriter xrw = new
124                             // XMLRecordWriter(osw);
125                             // dr.write(xrw);
126                             // osw.flush();
127                             // }
128                             ld = new PeriodFormatterData(localeName, dr);
129                         }
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);
136                     }
137                 } else {
138                     throw new MissingResourceException(
139                             "Duration data not found for  " + localeName, PATH,
140                             localeName);
141                 }
142
143                 // if (ld == null) {
144                 // ld = getFallbackFormatterData();
145                 // }
146                 cache.put(localeName, ld);
147             }
148             lastData = ld;
149             lastLocale = localeName;
150
151             return ld;
152         }
153     }
154
155     public Collection<String> getAvailableLocales() {
156         return availableLocales;
157     }
158
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);
164     // }
165     // return fallbackFormatterData;
166     // }
167     // }
168 }