/**************************************************************************
* Parts copyright (c) 2001 by Punch Telematix. All rights reserved. *
* Parts copyright (c) 2009 by Chris Gray, /k/ Embedded Java Solutions. *
* All rights reserved. *
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* 1. Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* 3. Neither the name of Punch Telematix or of /k/ Embedded Java Solutions*
* nor the names of other contributors may be used to endorse or promote*
* products derived from this software without specific prior written *
* permission. *
* *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED *
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
* IN NO EVENT SHALL PUNCH TELEMATIX, /K/ EMBEDDED JAVA SOLUTIONS OR OTHER *
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
**************************************************************************/
package wonka.resource;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.HashMap;
import java.util.ListResourceBundle;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
public class DateFormatSymbolBundle extends ListResourceBundle {
private static final String[] AMPMS = {"AM","PM"};
private static final String[] ERAS = {"BC","AD"};
private static final String[] MONTHS = {"January", "February", "March", "April", "May", "June", "July", "August",
"September", "October", "November", "December", ""};
private static final String[] SHORTMONTHS = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
"Aug", "Sep", "Oct", "Nov", "Dec", ""};
private static final String[] SHORTWEEKDAYS = {"", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
private static final String[] WEEKDAYS = {"", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
private static final String[][] STRINGS = {AMPMS, ERAS, MONTHS, SHORTMONTHS, WEEKDAYS, SHORTWEEKDAYS};
private static final HashMap lookup = new HashMap();
private static final String[][] ZONESTRINGS;
static {
// Each entry in 'lookup' maps a key string to a pair of indices into
// 'STRINGS': so {0, 0} is the first element of AMPMS, {2, 4} is the
// fourth element of MONTHS, etc..
// The key is always the lower-case English value of the item.
lookup.put("am", new int[]{0, 0});
lookup.put("pm", new int[]{0, 1});
lookup.put("bc", new int[]{1, 0});
lookup.put("ad", new int[]{1, 1});
lookup.put("january", new int[]{2, 0});
lookup.put("february", new int[]{2, 1});
lookup.put("march", new int[]{2, 2});
lookup.put("april", new int[]{2, 3});
lookup.put("maylong", new int[]{2, 4});
lookup.put("june", new int[]{2, 5});
lookup.put("july", new int[]{2, 6});
lookup.put("august", new int[]{2, 7});
lookup.put("september", new int[]{2, 8});
lookup.put("october", new int[]{2, 9});
lookup.put("november", new int[]{2, 10});
lookup.put("december", new int[]{2, 11});
lookup.put("jan", new int[]{3, 0});
lookup.put("feb", new int[]{3, 1});
lookup.put("mar", new int[]{3, 2});
lookup.put("apr", new int[]{3, 3});
lookup.put("may", new int[]{3, 4});
lookup.put("jun", new int[]{3, 5});
lookup.put("jul", new int[]{3, 6});
lookup.put("aug", new int[]{3, 7});
lookup.put("sep", new int[]{3, 8});
lookup.put("oct", new int[]{3, 9});
lookup.put("nov", new int[]{3, 10});
lookup.put("dec", new int[]{3, 11});
lookup.put("sunday", new int[]{4, 1});
lookup.put("monday", new int[]{4, 2});
lookup.put("tuesday", new int[]{4, 3});
lookup.put("wednesday", new int[]{4, 4});
lookup.put("thursday", new int[]{4, 5});
lookup.put("friday", new int[]{4, 6});
lookup.put("saturday", new int[]{4, 7});
lookup.put("sun", new int[]{5, 1});
lookup.put("mon", new int[]{5, 2});
lookup.put("tue", new int[]{5, 3});
lookup.put("wed", new int[]{5, 4});
lookup.put("thu", new int[]{5, 5});
lookup.put("fri", new int[]{5, 6});
lookup.put("sat", new int[]{5, 7});
InputStream dsis = ClassLoader.getSystemResourceAsStream(System.getProperty("mika.datesymbols", "mika.datesymbols"));
if (dsis != null) {
Locale locale = Locale.getDefault();
String language = locale.getLanguage();
String country = locale.getCountry();
if (language == null) {
language = "";
}
if (country == null) {
country = "";
}
String suffix1 = null;
String suffix2 = null;
if (language.length() == 0) {
suffix1 = country.length() == 0 ? "" : ("." + country);
}
else {
suffix1 = "." + language;
suffix2 = country.length() == 0 ? null : (suffix1 + "." + country);
}
HashMap work = new HashMap();
Properties dsprops = new Properties();
try {
dsprops.load(dsis);
processDateSymbols(dsprops, suffix1, suffix2, work);
} catch (IOException ioe) {
System.err.println("Error reading mika.datesymbols file");
ioe.printStackTrace();
}
updateStrings(suffix1, suffix2, work);
}
// TODO: [CG 20080207] This makes me a little nervous. Is it not possible
// that this static initialiser might execute before the timeZoneNames
// have been filled in?
// NOTE: we don't localise the timezone displays because it's easier to
// just translate the whole mika.timezones file into the user's language.
ArrayList zonestrings = new ArrayList();
Enumeration zonekeys = TimeZoneDisplayNameResourceBundle.timeZoneNames.keys();
while (zonekeys.hasMoreElements()) {
String key = (String)zonekeys.nextElement();
Object value = TimeZoneDisplayNameResourceBundle.timeZoneNames.get(key);
while (value instanceof String) {
value = TimeZoneDisplayNameResourceBundle.timeZoneNames.get(value);
}
String[] from = (String[])value;
String[] to = new String[5];
to[0] = key;
to[1] = from[1];
to[2] = from[0];
to[3] = from[3];
to[4] = from[2];
zonestrings.add(to);
}
ZONESTRINGS = new String[zonestrings.size()][];
zonestrings.toArray(ZONESTRINGS);
}
/**
* Process the mika.datesymbols file. The keys consist of a base
* key such as "mon" either on its own or followed by suffix1 or suffix2.
* If multiple keys with the same base are present then the one with the
* longest suffix will be used (suffix2 > suffix1).
*/
private static void processDateSymbols(Properties dsprops, String suffix1, String suffix2, HashMap work) {
Enumeration keys = dsprops.propertyNames();
while (keys.hasMoreElements()) {
String lhs = (String)keys.nextElement();
String rhs = dsprops.getProperty(lhs).trim();
if (rhs.length() == 0) {
System.err.println("mika.datesymbols key '" + lhs + "' has empty value");
continue;
}
String base = lhs;
String suffix = "";
int firstdot = lhs.indexOf('.');
if (firstdot >= 0) {
base = lhs.substring(0, firstdot);
suffix = lhs.substring(firstdot);
}
if (suffix.equals("") || suffix.equals(suffix1) || suffix.equals(suffix2)) {
work.put(lhs, rhs);
}
}
}
private static void updateStrings(String suffix1, String suffix2, HashMap work) {
Iterator iter = work.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
String lhs = (String) entry.getKey();
String rhs = (String) entry.getValue();
String base = lhs;
String suffix = "";
int firstdot = lhs.indexOf('.');
if (firstdot >= 0) {
base = lhs.substring(0, firstdot);
suffix = lhs.substring(firstdot);
}
boolean accept = false;
switch (suffix.length() / 3) {
case 0:
if (suffix1 != null && work.containsKey(base + suffix1)) break;
case 1:
if (suffix2 != null && work.containsKey(base + suffix2)) break;
default:
accept = true;
}
if (accept) {
int[] indices = (int[]) lookup.get(base.toLowerCase());
if (indices == null) {
return;
}
else {
int index0 = indices[0];
int index1 = indices[1];
STRINGS[index0][index1] = rhs;
}
}
}
}
public DateFormatSymbolBundle(){
super();
}
public Object[][] getContents(){
return new Object[][] {
{"ampms", AMPMS},
{"eras", ERAS},
{ "pattern", "GyMdkHmsSEDFwWahKz"},
{"months",MONTHS},
{"shortMonths",SHORTMONTHS},
{"shortDays",SHORTWEEKDAYS},
{"days",WEEKDAYS},
{"zones",ZONESTRINGS}
};
}
}