/* * Copyright (C) 2008 The Android Open Source Project * * Licensed 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 com.ibm.icu4jni.text; import java.text.FieldPosition; import java.text.Format; import java.text.NumberFormat; import java.text.ParsePosition; import java.util.Locale; public class RuleBasedNumberFormat extends NumberFormat { /** * Enum of predefined RBNF types. */ public enum RBNFType { /** * This creates a spellout instance of RBNF. * It formats numbers into textual representation: * 15 -> 'fifteen' or 15.15 -> 'fifteen point one five' * and it can parse words into numbers: 'twenty' -> 20 */ SPELLOUT(0), /** * This creates an ordinal instance of RBNF. * It formats numbers into an ordinal text representation: * 15 -> '15th' and by parsing it also works in the other direction. */ ORDINAL(1), /** * This creates instance of RBNF that allows to format numbers into time * values: 15 -> '15 sec.' and by parsing it also works in the other * direction. */ DURATION(2); int type; RBNFType(int t) { type = t; } int getType() { return type; } } @Override protected void finalize(){ close(); } private int addr = 0; /** * Open a new rule based number format of selected type for the * default location * * @param type the type of rule based number format */ public void open(RBNFType type) { this.addr = openRBNFImpl(type.getType(), Locale.getDefault().toString()); } /** * Open a new rule based number format of selected type for the * given location * * @param type the type of rule based number format * @param locale the locale to use for this rule based number format */ public void open(RBNFType type, Locale locale) { String loc = locale.toString(); if (loc == null) { throw new NullPointerException(); } this.addr = openRBNFImpl(type.getType(), loc); } private static native int openRBNFImpl(int type, String loc); /** * Open a new rule based number format for the * default location. The rule passed to the method has to be of the form * described in the ibm icu documentation for RuleBasedNumberFormat. * * @param rule the rule for the rule based number format */ public void open(String rule) { if (rule == null) { throw new NullPointerException(); } this.addr = openRBNFImpl(rule, Locale.getDefault().toString()); } /** * Open a new rule based number format for the * given location. The rule passed to the method has to be of the form * described in the ibm icu documentation for RuleBasedNumberFormat. * * @param rule the rule for the rule based number format * @param locale the locale to use for this rule based number format */ public void open(String rule, Locale locale) { String loc = locale.toString(); if (loc == null || rule == null) { throw new NullPointerException(); } this.addr = openRBNFImpl(rule, locale.toString()); } private static native int openRBNFImpl(String rule, String loc); /** * close a RuleBasedNumberFormat */ public void close() { if(this.addr != 0) { closeRBNFImpl(this.addr); this.addr = 0; } } private static native void closeRBNFImpl(int addr); @Override public StringBuffer format(long value, StringBuffer buffer, FieldPosition field) { if(buffer == null) { throw new NullPointerException(); } String fieldType = null; if(field != null) { fieldType = getFieldType(field.getFieldAttribute()); } String result = formatRBNFImpl(this.addr, value, field, fieldType, null); buffer.append(result.toCharArray(), 0, result.length()); return buffer; } private static native String formatRBNFImpl(int addr, long value, FieldPosition field, String fieldType, StringBuffer buffer); @Override public StringBuffer format(double value, StringBuffer buffer, FieldPosition field) { if(buffer == null) { throw new NullPointerException(); } String fieldType = null; if(field != null) { fieldType = getFieldType(field.getFieldAttribute()); } String result = formatRBNFImpl(this.addr, value, field, fieldType, null); buffer.append(result.toCharArray(), 0, result.length()); return buffer; } private static native String formatRBNFImpl(int addr, double value, FieldPosition field, String fieldType, StringBuffer buffer); @Override public Number parse(String string, ParsePosition position) { if (string == null || position == null) { throw new NullPointerException(); } return parseRBNFImpl(this.addr, string, position, false); } /** * This method has the same functionality * as {@link #parse(String, ParsePosition)} * But it uses lenient parsing. This means it also accepts strings that * differ from the correct writing (e.g. case or umlaut differences). * * @param string the string to parse * @param position the ParsePosition, updated on return with the index * following the parsed text, or on error the index is unchanged and * the error index is set to the index where the error occurred * @return the Number resulting from the parse, or null if there is an error */ public Number parseLenient(String string, ParsePosition position) { if (string == null || position == null) { throw new NullPointerException(); } return parseRBNFImpl(this.addr, string, position, true); } static native Number parseRBNFImpl(int addr, String string, ParsePosition position, boolean lenient); static private String getFieldType(Format.Field field) { if(field == null) { return null; } if(field.equals(NumberFormat.Field.SIGN)) { return "sign"; } if(field.equals(NumberFormat.Field.INTEGER)) { return "integer"; } if(field.equals(NumberFormat.Field.FRACTION)) { return "fraction"; } if(field.equals(NumberFormat.Field.EXPONENT)) { return "exponent"; } if(field.equals(NumberFormat.Field.EXPONENT_SIGN)) { return "exponent_sign"; } if(field.equals(NumberFormat.Field.EXPONENT_SYMBOL)) { return "exponent_symbol"; } if(field.equals(NumberFormat.Field.CURRENCY)) { return "currency"; } if(field.equals(NumberFormat.Field.GROUPING_SEPARATOR)) { return "grouping_separator"; } if(field.equals(NumberFormat.Field.DECIMAL_SEPARATOR)) { return "decimal_separator"; } if(field.equals(NumberFormat.Field.PERCENT)) { return "percent"; } if(field.equals(NumberFormat.Field.PERMILLE)) { return "permille"; } return null; } }