| /* |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| */ |
| |
| package org.apache.cordova.globalization; |
| |
| import java.text.DateFormat; |
| import java.text.DecimalFormat; |
| import java.text.SimpleDateFormat; |
| import java.util.ArrayList; |
| import java.util.Calendar; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.Currency; |
| import java.util.Date; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.TimeZone; |
| |
| import org.apache.cordova.CallbackContext; |
| import org.apache.cordova.CordovaPlugin; |
| import org.apache.cordova.PluginResult; |
| import org.json.JSONArray; |
| import org.json.JSONException; |
| import org.json.JSONObject; |
| |
| import android.annotation.TargetApi; |
| import android.text.format.Time; |
| |
| /** |
| * |
| */ |
| public class Globalization extends CordovaPlugin { |
| //GlobalizationCommand Plugin Actions |
| public static final String GETLOCALENAME = "getLocaleName"; |
| public static final String DATETOSTRING = "dateToString"; |
| public static final String STRINGTODATE = "stringToDate"; |
| public static final String GETDATEPATTERN = "getDatePattern"; |
| public static final String GETDATENAMES = "getDateNames"; |
| public static final String ISDAYLIGHTSAVINGSTIME = "isDayLightSavingsTime"; |
| public static final String GETFIRSTDAYOFWEEK = "getFirstDayOfWeek"; |
| public static final String NUMBERTOSTRING = "numberToString"; |
| public static final String STRINGTONUMBER = "stringToNumber"; |
| public static final String GETNUMBERPATTERN = "getNumberPattern"; |
| public static final String GETCURRENCYPATTERN = "getCurrencyPattern"; |
| public static final String GETPREFERREDLANGUAGE = "getPreferredLanguage"; |
| |
| //GlobalizationCommand Option Parameters |
| public static final String OPTIONS = "options"; |
| public static final String FORMATLENGTH = "formatLength"; |
| //public static final String SHORT = "short"; //default for dateToString format |
| public static final String MEDIUM = "medium"; |
| public static final String LONG = "long"; |
| public static final String FULL = "full"; |
| public static final String SELECTOR = "selector"; |
| //public static final String DATEANDTIME = "date and time"; //default for dateToString |
| public static final String DATE = "date"; |
| public static final String TIME = "time"; |
| public static final String DATESTRING = "dateString"; |
| public static final String TYPE = "type"; |
| public static final String ITEM = "item"; |
| public static final String NARROW = "narrow"; |
| public static final String WIDE = "wide"; |
| public static final String MONTHS = "months"; |
| public static final String DAYS = "days"; |
| //public static final String DECMIAL = "wide"; //default for numberToString |
| public static final String NUMBER = "number"; |
| public static final String NUMBERSTRING = "numberString"; |
| public static final String PERCENT = "percent"; |
| public static final String CURRENCY = "currency"; |
| public static final String CURRENCYCODE = "currencyCode"; |
| |
| @Override |
| public boolean execute(String action, JSONArray data, CallbackContext callbackContext) { |
| JSONObject obj = new JSONObject(); |
| |
| try{ |
| if (action.equals(GETLOCALENAME)){ |
| obj = getLocaleName(); |
| }else if (action.equals(GETPREFERREDLANGUAGE)){ |
| obj = getPreferredLanguage(); |
| } else if (action.equalsIgnoreCase(DATETOSTRING)) { |
| obj = getDateToString(data); |
| }else if(action.equalsIgnoreCase(STRINGTODATE)){ |
| obj = getStringtoDate(data); |
| }else if(action.equalsIgnoreCase(GETDATEPATTERN)){ |
| obj = getDatePattern(data); |
| }else if(action.equalsIgnoreCase(GETDATENAMES)){ |
| if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.GINGERBREAD) { |
| throw new GlobalizationError(GlobalizationError.UNKNOWN_ERROR); |
| } else { |
| obj = getDateNames(data); |
| } |
| }else if(action.equalsIgnoreCase(ISDAYLIGHTSAVINGSTIME)){ |
| obj = getIsDayLightSavingsTime(data); |
| }else if(action.equalsIgnoreCase(GETFIRSTDAYOFWEEK)){ |
| obj = getFirstDayOfWeek(data); |
| }else if(action.equalsIgnoreCase(NUMBERTOSTRING)){ |
| obj = getNumberToString(data); |
| }else if(action.equalsIgnoreCase(STRINGTONUMBER)){ |
| obj = getStringToNumber(data); |
| }else if(action.equalsIgnoreCase(GETNUMBERPATTERN)){ |
| obj = getNumberPattern(data); |
| }else if(action.equalsIgnoreCase(GETCURRENCYPATTERN)){ |
| obj = getCurrencyPattern(data); |
| }else { |
| return false; |
| } |
| |
| callbackContext.success(obj); |
| }catch (GlobalizationError ge){ |
| callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, ge.toJson())); |
| }catch (Exception e){ |
| callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION)); |
| } |
| return true; |
| } |
| /* |
| * @Description: Returns a well-formed ITEF BCP 47 language tag representing |
| * the locale identifier for the client's current locale |
| * |
| * @Return: String: The BCP 47 language tag for the current locale |
| */ |
| private String toBcp47Language(Locale loc){ |
| final char SEP = '-'; // we will use a dash as per BCP 47 |
| String language = loc.getLanguage(); |
| String region = loc.getCountry(); |
| String variant = loc.getVariant(); |
| |
| // special case for Norwegian Nynorsk since "NY" cannot be a variant as per BCP 47 |
| // this goes before the string matching since "NY" wont pass the variant checks |
| if( language.equals("no") && region.equals("NO") && variant.equals("NY")){ |
| language = "nn"; |
| region = "NO"; |
| variant = ""; |
| } |
| |
| if( language.isEmpty() || !language.matches("\\p{Alpha}{2,8}")){ |
| language = "und"; // Follow the Locale#toLanguageTag() implementation |
| // which says to return "und" for Undetermined |
| }else if(language.equals("iw")){ |
| language = "he"; // correct deprecated "Hebrew" |
| }else if(language.equals("in")){ |
| language = "id"; // correct deprecated "Indonesian" |
| }else if(language.equals("ji")){ |
| language = "yi"; // correct deprecated "Yiddish" |
| } |
| |
| // ensure valid country code, if not well formed, it's omitted |
| if (!region.matches("\\p{Alpha}{2}|\\p{Digit}{3}")) { |
| region = ""; |
| } |
| |
| // variant subtags that begin with a letter must be at least 5 characters long |
| if (!variant.matches("\\p{Alnum}{5,8}|\\p{Digit}\\p{Alnum}{3}")) { |
| variant = ""; |
| } |
| |
| StringBuilder bcp47Tag = new StringBuilder(language); |
| if (!region.isEmpty()) { |
| bcp47Tag.append(SEP).append(region); |
| } |
| if (!variant.isEmpty()) { |
| bcp47Tag.append(SEP).append(variant); |
| } |
| |
| return bcp47Tag.toString(); |
| } |
| /* |
| * @Description: Returns the BCP 47 Unicode locale identifier for current locale setting |
| * The locale is defined by a language code, a country code, and a variant, separated |
| * by a hyphen, for example, "en-US", "fr-CA", etc., |
| * |
| * @Return: JSONObject |
| * Object.value {String}: The locale identifier |
| * |
| * @throws: GlobalizationError.UNKNOWN_ERROR |
| */ |
| private JSONObject getLocaleName() throws GlobalizationError{ |
| JSONObject obj = new JSONObject(); |
| try{ |
| obj.put("value", toBcp47Language(Locale.getDefault())); |
| return obj; |
| }catch(Exception e){ |
| throw new GlobalizationError(GlobalizationError.UNKNOWN_ERROR); |
| } |
| } |
| /* |
| * @Description: Returns the BCP 47 language tag for the client's |
| * current language. Currently in Android this is the same as locale, |
| * since Java does not distinguish between locale and language. |
| * |
| * @Return: JSONObject |
| * Object.value {String}: The language identifier |
| * |
| * @throws: GlobalizationError.UNKNOWN_ERROR |
| */ |
| private JSONObject getPreferredLanguage() throws GlobalizationError { |
| JSONObject obj = new JSONObject(); |
| try { |
| obj.put("value", toBcp47Language(Locale.getDefault())); |
| return obj; |
| } catch (Exception e) { |
| throw new GlobalizationError(GlobalizationError.UNKNOWN_ERROR); |
| } |
| } |
| /* |
| * @Description: Returns a date formatted as a string according to the client's user preferences and |
| * calendar using the time zone of the client. |
| * |
| * @Return: JSONObject |
| * Object.value {String}: The localized date string |
| * |
| * @throws: GlobalizationError.FORMATTING_ERROR |
| */ |
| private JSONObject getDateToString(JSONArray options) throws GlobalizationError{ |
| JSONObject obj = new JSONObject(); |
| try{ |
| Date date = new Date((Long)options.getJSONObject(0).get(DATE)); |
| |
| //get formatting pattern from android device (Will only have device specific formatting for short form of date) or options supplied |
| JSONObject datePattern = getDatePattern(options); |
| SimpleDateFormat fmt = new SimpleDateFormat(datePattern.getString("pattern")); |
| |
| //return formatted date |
| return obj.put("value",fmt.format(date)); |
| }catch(Exception ge){ |
| throw new GlobalizationError(GlobalizationError.FORMATTING_ERROR); |
| } |
| } |
| |
| /* |
| * @Description: Parses a date formatted as a string according to the client's user |
| * preferences and calendar using the time zone of the client and returns |
| * the corresponding date object |
| * @Return: JSONObject |
| * Object.year {Number}: The four digit year |
| * Object.month {Number}: The month from (0 - 11) |
| * Object.day {Number}: The day from (1 - 31) |
| * Object.hour {Number}: The hour from (0 - 23) |
| * Object.minute {Number}: The minute from (0 - 59) |
| * Object.second {Number}: The second from (0 - 59) |
| * Object.millisecond {Number}: The milliseconds (from 0 - 999), not available on all platforms |
| * |
| * @throws: GlobalizationError.PARSING_ERROR |
| */ |
| private JSONObject getStringtoDate(JSONArray options)throws GlobalizationError{ |
| JSONObject obj = new JSONObject(); |
| Date date; |
| try{ |
| //get format pattern from android device (Will only have device specific formatting for short form of date) or options supplied |
| DateFormat fmt = new SimpleDateFormat(getDatePattern(options).getString("pattern")); |
| |
| //attempt parsing string based on user preferences |
| date = fmt.parse(options.getJSONObject(0).get(DATESTRING).toString()); |
| |
| //set Android Time object |
| Time time = new Time(); |
| time.set(date.getTime()); |
| |
| //return properties; |
| obj.put("year", time.year); |
| obj.put("month", time.month); |
| obj.put("day", time.monthDay); |
| obj.put("hour", time.hour); |
| obj.put("minute", time.minute); |
| obj.put("second", time.second); |
| obj.put("millisecond", Long.valueOf(0)); |
| return obj; |
| }catch(Exception ge){ |
| throw new GlobalizationError(GlobalizationError.PARSING_ERROR); |
| } |
| } |
| |
| /* |
| * @Description: Returns a pattern string for formatting and parsing dates according to the client's |
| * user preferences. |
| * @Return: JSONObject |
| * |
| * Object.pattern {String}: The date and time pattern for formatting and parsing dates. |
| * The patterns follow Unicode Technical Standard #35 |
| * http://unicode.org/reports/tr35/tr35-4.html |
| * Object.timezone {String}: The abbreviated name of the time zone on the client |
| * Object.utc_offset {Number}: The current difference in seconds between the client's |
| * time zone and coordinated universal time. |
| * Object.dst_offset {Number}: The current daylight saving time offset in seconds |
| * between the client's non-daylight saving's time zone |
| * and the client's daylight saving's time zone. |
| * |
| * @throws: GlobalizationError.PATTERN_ERROR |
| */ |
| private JSONObject getDatePattern(JSONArray options) throws GlobalizationError{ |
| JSONObject obj = new JSONObject(); |
| |
| try{ |
| SimpleDateFormat fmtDate = (SimpleDateFormat)android.text.format.DateFormat.getDateFormat(this.cordova.getActivity()); //default user preference for date |
| SimpleDateFormat fmtTime = (SimpleDateFormat)android.text.format.DateFormat.getTimeFormat(this.cordova.getActivity()); //default user preference for time |
| |
| String fmt = fmtDate.toLocalizedPattern() + " " + fmtTime.toLocalizedPattern(); //default SHORT date/time format. ex. dd/MM/yyyy h:mm a |
| |
| //get Date value + options (if available) |
| if (options.getJSONObject(0).has(OPTIONS)){ |
| //options were included |
| |
| JSONObject innerOptions = options.getJSONObject(0).getJSONObject(OPTIONS); |
| //get formatLength option |
| if (!innerOptions.isNull(FORMATLENGTH)){ |
| String fmtOpt = innerOptions.getString(FORMATLENGTH); |
| if (fmtOpt.equalsIgnoreCase(MEDIUM)){//medium |
| fmtDate = (SimpleDateFormat)android.text.format.DateFormat.getMediumDateFormat(this.cordova.getActivity()); |
| }else if (fmtOpt.equalsIgnoreCase(LONG) || fmtOpt.equalsIgnoreCase(FULL)){ //long/full |
| fmtDate = (SimpleDateFormat)android.text.format.DateFormat.getLongDateFormat(this.cordova.getActivity()); |
| } |
| } |
| |
| //return pattern type |
| fmt = fmtDate.toLocalizedPattern() + " " + fmtTime.toLocalizedPattern(); |
| if (!innerOptions.isNull(SELECTOR)){ |
| String selOpt = innerOptions.getString(SELECTOR); |
| if (selOpt.equalsIgnoreCase(DATE)){ |
| fmt = fmtDate.toLocalizedPattern(); |
| }else if (selOpt.equalsIgnoreCase(TIME)){ |
| fmt = fmtTime.toLocalizedPattern(); |
| } |
| } |
| } |
| |
| //TimeZone from users device |
| //TimeZone tz = Calendar.getInstance(Locale.getDefault()).getTimeZone(); //substitute method |
| TimeZone tz = TimeZone.getTimeZone(Time.getCurrentTimezone()); |
| |
| obj.put("pattern", fmt); |
| obj.put("timezone", tz.getDisplayName(tz.inDaylightTime(Calendar.getInstance().getTime()),TimeZone.SHORT)); |
| obj.put("utc_offset", tz.getRawOffset()/1000); |
| obj.put("dst_offset", tz.getDSTSavings()/1000); |
| return obj; |
| |
| }catch(Exception ge){ |
| throw new GlobalizationError(GlobalizationError.PATTERN_ERROR); |
| } |
| } |
| |
| /* |
| * @Description: Returns an array of either the names of the months or days of the week |
| * according to the client's user preferences and calendar |
| * @Return: JSONObject |
| * Object.value {Array{String}}: The array of names starting from either |
| * the first month in the year or the |
| * first day of the week. |
| * |
| * @throws: GlobalizationError.UNKNOWN_ERROR |
| */ |
| @TargetApi(9) |
| private JSONObject getDateNames(JSONArray options) throws GlobalizationError{ |
| JSONObject obj = new JSONObject(); |
| //String[] value; |
| JSONArray value = new JSONArray(); |
| List<String> namesList = new ArrayList<String>(); |
| final Map<String,Integer> namesMap; // final needed for sorting with anonymous comparator |
| try{ |
| int type = 0; //default wide |
| int item = 0; //default months |
| |
| //get options if available |
| if (options.getJSONObject(0).length() > 0){ |
| //get type if available |
| if (!((JSONObject)options.getJSONObject(0).get(OPTIONS)).isNull(TYPE)){ |
| String t = (String)((JSONObject)options.getJSONObject(0).get(OPTIONS)).get(TYPE); |
| if (t.equalsIgnoreCase(NARROW)){type++;} //DateUtils.LENGTH_MEDIUM |
| } |
| //get item if available |
| if (!((JSONObject)options.getJSONObject(0).get(OPTIONS)).isNull(ITEM)){ |
| String t = (String)((JSONObject)options.getJSONObject(0).get(OPTIONS)).get(ITEM); |
| if (t.equalsIgnoreCase(DAYS)){item += 10;} //Days of week start at 1 |
| } |
| } |
| //determine return value |
| int method = item + type; |
| if (method == 1) { //months and narrow |
| namesMap = Calendar.getInstance().getDisplayNames(Calendar.MONTH, Calendar.SHORT, Locale.getDefault()); |
| } else if (method == 10) { //days and wide |
| namesMap = Calendar.getInstance().getDisplayNames(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.getDefault()); |
| } else if (method == 11) { //days and narrow |
| namesMap = Calendar.getInstance().getDisplayNames(Calendar.DAY_OF_WEEK, Calendar.SHORT, Locale.getDefault()); |
| } else { //default: months and wide |
| namesMap = Calendar.getInstance().getDisplayNames(Calendar.MONTH, Calendar.LONG, Locale.getDefault()); |
| } |
| |
| // save names as a list |
| for(String name : namesMap.keySet()) { |
| namesList.add(name); |
| } |
| |
| // sort the list according to values in namesMap |
| Collections.sort(namesList, new Comparator<String>() { |
| public int compare(String arg0, String arg1) { |
| return namesMap.get(arg0).compareTo(namesMap.get(arg1)); |
| } |
| }); |
| |
| // convert nameList into JSONArray of String objects |
| for (int i = 0; i < namesList.size(); i ++){ |
| value.put(namesList.get(i)); |
| } |
| |
| //return array of names |
| return obj.put("value", value); |
| }catch(Exception ge){ |
| throw new GlobalizationError(GlobalizationError.UNKNOWN_ERROR); |
| } |
| } |
| |
| /* |
| * @Description: Returns whether daylight savings time is in effect for a given date using the client's |
| * time zone and calendar. |
| * @Return: JSONObject |
| * Object.dst {Boolean}: The value "true" indicates that daylight savings time is |
| * in effect for the given date and "false" indicate that it is not. * |
| * |
| * @throws: GlobalizationError.UNKNOWN_ERROR |
| */ |
| private JSONObject getIsDayLightSavingsTime(JSONArray options) throws GlobalizationError{ |
| JSONObject obj = new JSONObject(); |
| boolean dst = false; |
| try{ |
| Date date = new Date((Long)options.getJSONObject(0).get(DATE)); |
| //TimeZone tz = Calendar.getInstance(Locale.getDefault()).getTimeZone(); |
| TimeZone tz = TimeZone.getTimeZone(Time.getCurrentTimezone()); |
| dst = tz.inDaylightTime(date); //get daylight savings data from date object and user timezone settings |
| |
| return obj.put("dst",dst); |
| }catch(Exception ge){ |
| throw new GlobalizationError(GlobalizationError.UNKNOWN_ERROR); |
| } |
| } |
| |
| /* |
| * @Description: Returns the first day of the week according to the client's user preferences and calendar. |
| * The days of the week are numbered starting from 1 where 1 is considered to be Sunday. |
| * @Return: JSONObject |
| * Object.value {Number}: The number of the first day of the week. |
| * |
| * @throws: GlobalizationError.UNKNOWN_ERROR |
| */ |
| private JSONObject getFirstDayOfWeek(JSONArray options) throws GlobalizationError{ |
| JSONObject obj = new JSONObject(); |
| try{ |
| int value = Calendar.getInstance(Locale.getDefault()).getFirstDayOfWeek(); //get first day of week based on user locale settings |
| return obj.put("value", value); |
| }catch(Exception ge){ |
| throw new GlobalizationError(GlobalizationError.UNKNOWN_ERROR); |
| } |
| } |
| |
| /* |
| * @Description: Returns a number formatted as a string according to the client's user preferences. |
| * @Return: JSONObject |
| * Object.value {String}: The formatted number string. |
| * |
| * @throws: GlobalizationError.FORMATTING_ERROR |
| */ |
| private JSONObject getNumberToString(JSONArray options) throws GlobalizationError{ |
| JSONObject obj = new JSONObject(); |
| String value = ""; |
| try{ |
| DecimalFormat fmt = getNumberFormatInstance(options);//returns Decimal/Currency/Percent instance |
| value = fmt.format(options.getJSONObject(0).get(NUMBER)); |
| return obj.put("value", value); |
| }catch(Exception ge){ |
| throw new GlobalizationError(GlobalizationError.FORMATTING_ERROR); |
| } |
| } |
| |
| /* |
| * @Description: Parses a number formatted as a string according to the client's user preferences and |
| * returns the corresponding number. |
| * @Return: JSONObject |
| * Object.value {Number}: The parsed number. |
| * |
| * @throws: GlobalizationError.PARSING_ERROR |
| */ |
| private JSONObject getStringToNumber(JSONArray options) throws GlobalizationError{ |
| JSONObject obj = new JSONObject(); |
| Number value; |
| try{ |
| DecimalFormat fmt = getNumberFormatInstance(options); //returns Decimal/Currency/Percent instance |
| value = fmt.parse((String)options.getJSONObject(0).get(NUMBERSTRING)); |
| return obj.put("value", value); |
| }catch(Exception ge){ |
| throw new GlobalizationError(GlobalizationError.PARSING_ERROR); |
| } |
| } |
| |
| /* |
| * @Description: Returns a pattern string for formatting and parsing numbers according to the client's user |
| * preferences. |
| * @Return: JSONObject |
| * Object.pattern {String}: The number pattern for formatting and parsing numbers. |
| * The patterns follow Unicode Technical Standard #35. |
| * http://unicode.org/reports/tr35/tr35-4.html |
| * Object.symbol {String}: The symbol to be used when formatting and parsing |
| * e.g., percent or currency symbol. |
| * Object.fraction {Number}: The number of fractional digits to use when parsing and |
| * formatting numbers. |
| * Object.rounding {Number}: The rounding increment to use when parsing and formatting. |
| * Object.positive {String}: The symbol to use for positive numbers when parsing and formatting. |
| * Object.negative: {String}: The symbol to use for negative numbers when parsing and formatting. |
| * Object.decimal: {String}: The decimal symbol to use for parsing and formatting. |
| * Object.grouping: {String}: The grouping symbol to use for parsing and formatting. |
| * |
| * @throws: GlobalizationError.PATTERN_ERROR |
| */ |
| private JSONObject getNumberPattern(JSONArray options) throws GlobalizationError{ |
| JSONObject obj = new JSONObject(); |
| try{ |
| //uses java.text.DecimalFormat to format value |
| DecimalFormat fmt = (DecimalFormat) DecimalFormat.getInstance(Locale.getDefault()); //default format |
| String symbol = String.valueOf(fmt.getDecimalFormatSymbols().getDecimalSeparator()); |
| //get Date value + options (if available) |
| if (options.getJSONObject(0).length() > 0){ |
| //options were included |
| if (!((JSONObject)options.getJSONObject(0).get(OPTIONS)).isNull(TYPE)){ |
| String fmtOpt = (String)((JSONObject)options.getJSONObject(0).get(OPTIONS)).get(TYPE); |
| if (fmtOpt.equalsIgnoreCase(CURRENCY)){ |
| fmt = (DecimalFormat) DecimalFormat.getCurrencyInstance(Locale.getDefault()); |
| symbol = fmt.getDecimalFormatSymbols().getCurrencySymbol(); |
| }else if(fmtOpt.equalsIgnoreCase(PERCENT)){ |
| fmt = (DecimalFormat) DecimalFormat.getPercentInstance(Locale.getDefault()); |
| symbol = String.valueOf(fmt.getDecimalFormatSymbols().getPercent()); |
| } |
| } |
| } |
| |
| //return properties |
| obj.put("pattern", fmt.toPattern()); |
| obj.put("symbol", symbol); |
| obj.put("fraction", fmt.getMinimumFractionDigits()); |
| obj.put("rounding", Integer.valueOf(0)); |
| obj.put("positive", fmt.getPositivePrefix()); |
| obj.put("negative", fmt.getNegativePrefix()); |
| obj.put("decimal", String.valueOf(fmt.getDecimalFormatSymbols().getDecimalSeparator())); |
| obj.put("grouping", String.valueOf(fmt.getDecimalFormatSymbols().getGroupingSeparator())); |
| |
| return obj; |
| }catch(Exception ge){ |
| throw new GlobalizationError(GlobalizationError.PATTERN_ERROR); |
| } |
| } |
| |
| /* |
| * @Description: Returns a pattern string for formatting and parsing currency values according to the client's |
| * user preferences and ISO 4217 currency code. |
| * @Return: JSONObject |
| * Object.pattern {String}: The currency pattern for formatting and parsing currency values. |
| * The patterns follow Unicode Technical Standard #35 |
| * http://unicode.org/reports/tr35/tr35-4.html |
| * Object.code {String}: The ISO 4217 currency code for the pattern. |
| * Object.fraction {Number}: The number of fractional digits to use when parsing and |
| * formatting currency. |
| * Object.rounding {Number}: The rounding increment to use when parsing and formatting. |
| * Object.decimal: {String}: The decimal symbol to use for parsing and formatting. |
| * Object.grouping: {String}: The grouping symbol to use for parsing and formatting. |
| * |
| * @throws: GlobalizationError.FORMATTING_ERROR |
| */ |
| private JSONObject getCurrencyPattern(JSONArray options) throws GlobalizationError{ |
| JSONObject obj = new JSONObject(); |
| try{ |
| //get ISO 4217 currency code |
| String code = options.getJSONObject(0).getString(CURRENCYCODE); |
| |
| //uses java.text.DecimalFormat to format value |
| DecimalFormat fmt = (DecimalFormat) DecimalFormat.getCurrencyInstance(Locale.getDefault()); |
| |
| //set currency format |
| Currency currency = Currency.getInstance(code); |
| fmt.setCurrency(currency); |
| |
| //return properties |
| obj.put("pattern", fmt.toPattern()); |
| obj.put("code", currency.getCurrencyCode()); |
| obj.put("fraction", fmt.getMinimumFractionDigits()); |
| obj.put("rounding", Integer.valueOf(0)); |
| obj.put("decimal", String.valueOf(fmt.getDecimalFormatSymbols().getDecimalSeparator())); |
| obj.put("grouping", String.valueOf(fmt.getDecimalFormatSymbols().getGroupingSeparator())); |
| |
| return obj; |
| }catch(Exception ge){ |
| throw new GlobalizationError(GlobalizationError.FORMATTING_ERROR); |
| } |
| } |
| |
| /* |
| * @Description: Parses a JSONArray from user options and returns the correct Instance of Decimal/Percent/Currency. |
| * @Return: DecimalFormat : The Instance to use. |
| * |
| * @throws: JSONException |
| */ |
| private DecimalFormat getNumberFormatInstance(JSONArray options) throws JSONException{ |
| DecimalFormat fmt = (DecimalFormat)DecimalFormat.getInstance(Locale.getDefault()); //default format |
| try{ |
| if (options.getJSONObject(0).length() > 1){ |
| //options were included |
| if (!((JSONObject)options.getJSONObject(0).get(OPTIONS)).isNull(TYPE)){ |
| String fmtOpt = (String)((JSONObject)options.getJSONObject(0).get(OPTIONS)).get(TYPE); |
| if (fmtOpt.equalsIgnoreCase(CURRENCY)){ |
| fmt = (DecimalFormat)DecimalFormat.getCurrencyInstance(Locale.getDefault()); |
| }else if(fmtOpt.equalsIgnoreCase(PERCENT)){ |
| fmt = (DecimalFormat)DecimalFormat.getPercentInstance(Locale.getDefault()); |
| } |
| } |
| } |
| |
| }catch (JSONException je){} |
| return fmt; |
| } |
| } |