First useable commit
This commit is contained in:
parent
0ff5251e34
commit
86bb91a4fe
|
@ -22,8 +22,14 @@
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
package java.text;
|
package com.moparisthebest.text;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.text.AttributedCharacterIterator;
|
||||||
|
import java.text.AttributedString;
|
||||||
|
import java.text.Format;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,9 +37,28 @@ import java.util.ArrayList;
|
||||||
* into a resulting <code>AttributedCharacterIterator</code>. The resulting
|
* into a resulting <code>AttributedCharacterIterator</code>. The resulting
|
||||||
* <code>AttributedCharacterIterator</code> can be retrieved by way of
|
* <code>AttributedCharacterIterator</code> can be retrieved by way of
|
||||||
* the <code>getIterator</code> method.
|
* the <code>getIterator</code> method.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
class CharacterIteratorFieldDelegate implements Format.FieldDelegate {
|
class CharacterIteratorFieldDelegate extends FieldDelegate {
|
||||||
|
|
||||||
|
private static final Constructor<AttributedString> iterableConstructor;
|
||||||
|
private static final Method length;
|
||||||
|
|
||||||
|
static {
|
||||||
|
Constructor<AttributedString> cons = null;
|
||||||
|
Method l = null;
|
||||||
|
try {
|
||||||
|
cons = AttributedString.class.getDeclaredConstructor(AttributedCharacterIterator[].class);
|
||||||
|
cons.setAccessible(true);
|
||||||
|
|
||||||
|
l = AttributedString.class.getDeclaredMethod("length");
|
||||||
|
l.setAccessible(true);
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
throw new RuntimeException(DecimalFormat.DECIMAL_FORMAT_EXCEPTION, e);
|
||||||
|
}
|
||||||
|
iterableConstructor = cons;
|
||||||
|
length = l;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array of AttributeStrings. Whenever <code>formatted</code> is invoked
|
* Array of AttributeStrings. Whenever <code>formatted</code> is invoked
|
||||||
* for a region > size, a new instance of AttributedString is added to
|
* for a region > size, a new instance of AttributedString is added to
|
||||||
|
@ -50,6 +75,7 @@ class CharacterIteratorFieldDelegate implements Format.FieldDelegate {
|
||||||
|
|
||||||
|
|
||||||
CharacterIteratorFieldDelegate() {
|
CharacterIteratorFieldDelegate() {
|
||||||
|
super((Object)null);
|
||||||
attributedStrings = new ArrayList<>();
|
attributedStrings = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,13 +89,19 @@ class CharacterIteratorFieldDelegate implements Format.FieldDelegate {
|
||||||
|
|
||||||
while (start < index) {
|
while (start < index) {
|
||||||
AttributedString as = attributedStrings.
|
AttributedString as = attributedStrings.
|
||||||
get(asIndex--);
|
get(asIndex--);
|
||||||
int newIndex = index - as.length();
|
int asLength;
|
||||||
|
try {
|
||||||
|
asLength = (Integer) length.invoke(as); // was: as.length();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
throw new RuntimeException(DecimalFormat.DECIMAL_FORMAT_EXCEPTION, e);
|
||||||
|
}
|
||||||
|
int newIndex = index - asLength;
|
||||||
int aStart = Math.max(0, start - newIndex);
|
int aStart = Math.max(0, start - newIndex);
|
||||||
|
|
||||||
as.addAttribute(attr, value, aStart, Math.min(
|
as.addAttribute(attr, value, aStart, Math.min(
|
||||||
end - start, as.length() - aStart) +
|
end - start, asLength - aStart) +
|
||||||
aStart);
|
aStart);
|
||||||
index = newIndex;
|
index = newIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,6 +151,11 @@ class CharacterIteratorFieldDelegate implements Format.FieldDelegate {
|
||||||
iterators[counter] = attributedStrings.
|
iterators[counter] = attributedStrings.
|
||||||
get(counter).getIterator();
|
get(counter).getIterator();
|
||||||
}
|
}
|
||||||
return new AttributedString(iterators).getIterator();
|
try {
|
||||||
|
return iterableConstructor.newInstance(iterators).getIterator(); // was: new AttributedString(iterators).getIterator();
|
||||||
|
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||||
|
throw new RuntimeException(DecimalFormat.DECIMAL_FORMAT_EXCEPTION, e);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,25 +36,23 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package java.text;
|
package com.moparisthebest.text;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InvalidObjectException;
|
import java.io.InvalidObjectException;
|
||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
|
import java.text.*;
|
||||||
import java.text.spi.NumberFormatProvider;
|
import java.text.spi.NumberFormatProvider;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Currency;
|
import java.util.Currency;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.ResourceBundle;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
|
||||||
import sun.util.locale.provider.ResourceBundleBasedAdapter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>DecimalFormat</code> is a concrete subclass of
|
* <code>DecimalFormat</code> is a concrete subclass of
|
||||||
|
@ -378,7 +376,40 @@ import sun.util.locale.provider.ResourceBundleBasedAdapter;
|
||||||
* @author Mark Davis
|
* @author Mark Davis
|
||||||
* @author Alan Liu
|
* @author Alan Liu
|
||||||
*/
|
*/
|
||||||
public class DecimalFormat extends NumberFormat {
|
public class DecimalFormat extends java.text.DecimalFormat {
|
||||||
|
|
||||||
|
public static final String DECIMAL_FORMAT_EXCEPTION = "com.moparisthebest.text.DecimalFormat will not function";
|
||||||
|
private static final FieldPosition dontCareFieldPositionInstance; // = DontCareFieldPosition.INSTANCE
|
||||||
|
|
||||||
|
private static final Class<?> resourceBundleBasedAdapter;
|
||||||
|
private static final Method getAdapter, getResourceBundleBased, getLocaleResources, getNumberPatterns;
|
||||||
|
|
||||||
|
static {
|
||||||
|
FieldPosition dcfpi = null;
|
||||||
|
Class<?> rbba = null;
|
||||||
|
Method ga = null, grbb = null, glr = null, gnp = null;
|
||||||
|
try {
|
||||||
|
final java.lang.reflect.Field instance = Class.forName("java.text.DontCareFieldPosition").getDeclaredField("INSTANCE");
|
||||||
|
instance.setAccessible(true);
|
||||||
|
dcfpi = (FieldPosition) instance.get(null);
|
||||||
|
|
||||||
|
final Class<?> localeProviderAdapter = Class.forName("sun.util.locale.provider.LocaleProviderAdapter");
|
||||||
|
rbba = Class.forName("sun.util.locale.provider.ResourceBundleBasedAdapter");
|
||||||
|
ga = localeProviderAdapter.getMethod("getAdapter", java.lang.Class.class, Locale.class);
|
||||||
|
grbb = localeProviderAdapter.getMethod("getResourceBundleBased");
|
||||||
|
glr = localeProviderAdapter.getMethod("getLocaleResources", Locale.class);
|
||||||
|
final Class<?> localeResources = Class.forName("sun.util.locale.provider.LocaleResources");
|
||||||
|
gnp = localeResources.getMethod("getNumberPatterns");
|
||||||
|
} catch (Throwable e) {
|
||||||
|
throw new RuntimeException(DECIMAL_FORMAT_EXCEPTION, e);
|
||||||
|
}
|
||||||
|
dontCareFieldPositionInstance = dcfpi;
|
||||||
|
resourceBundleBasedAdapter = rbba;
|
||||||
|
getAdapter = ga;
|
||||||
|
getResourceBundleBased = grbb;
|
||||||
|
getLocaleResources = glr;
|
||||||
|
getNumberPatterns = gnp;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a DecimalFormat using the default pattern and symbols
|
* Creates a DecimalFormat using the default pattern and symbols
|
||||||
|
@ -399,12 +430,39 @@ public class DecimalFormat extends NumberFormat {
|
||||||
public DecimalFormat() {
|
public DecimalFormat() {
|
||||||
// Get the pattern for the default locale.
|
// Get the pattern for the default locale.
|
||||||
Locale def = Locale.getDefault(Locale.Category.FORMAT);
|
Locale def = Locale.getDefault(Locale.Category.FORMAT);
|
||||||
|
String[] all;
|
||||||
|
/*
|
||||||
|
// cannot use this code because javac refuses to let us use these classes...
|
||||||
LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(NumberFormatProvider.class, def);
|
LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(NumberFormatProvider.class, def);
|
||||||
if (!(adapter instanceof ResourceBundleBasedAdapter)) {
|
if (!(adapter instanceof ResourceBundleBasedAdapter)) {
|
||||||
adapter = LocaleProviderAdapter.getResourceBundleBased();
|
adapter = LocaleProviderAdapter.getResourceBundleBased();
|
||||||
}
|
}
|
||||||
String[] all = adapter.getLocaleResources(def).getNumberPatterns();
|
String[] all = adapter.getLocaleResources(def).getNumberPatterns();
|
||||||
|
|
||||||
|
// original prints:
|
||||||
|
// all: [#,##0.###;-#,##0.###, ¤#,##0.00;(¤#,##0.00), #,##0%]
|
||||||
|
// all[0]: #,##0.###;-#,##0.###
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
// must recreate the above code using reflection, yuck
|
||||||
|
Object adapter = getAdapter.invoke(null, NumberFormatProvider.class, def);
|
||||||
|
if (!resourceBundleBasedAdapter.isInstance(adapter)) {
|
||||||
|
adapter = getResourceBundleBased.invoke(null);
|
||||||
|
}
|
||||||
|
all = (String[]) getNumberPatterns.invoke(getLocaleResources.invoke(adapter, def));
|
||||||
|
} catch (InvocationTargetException | IllegalAccessException e) {
|
||||||
|
throw new RuntimeException(DECIMAL_FORMAT_EXCEPTION, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
System.out.println("all: "+java.util.Arrays.toString(all));
|
||||||
|
System.out.println("all[0]: "+all[0]);
|
||||||
|
|
||||||
|
// reflection prints:
|
||||||
|
// all: [#,##0.###;-#,##0.###, ¤#,##0.00;(¤#,##0.00), #,##0%]
|
||||||
|
// all[0]: #,##0.###;-#,##0.###
|
||||||
|
*/
|
||||||
|
|
||||||
// Always applyPattern after the symbols are set
|
// Always applyPattern after the symbols are set
|
||||||
this.symbols = DecimalFormatSymbols.getInstance(def);
|
this.symbols = DecimalFormatSymbols.getInstance(def);
|
||||||
applyPattern(all[0], false);
|
applyPattern(all[0], false);
|
||||||
|
@ -464,50 +522,6 @@ public class DecimalFormat extends NumberFormat {
|
||||||
applyPattern(pattern, false);
|
applyPattern(pattern, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Overrides
|
|
||||||
/**
|
|
||||||
* Formats a number and appends the resulting text to the given string
|
|
||||||
* buffer.
|
|
||||||
* The number can be of any subclass of {@link java.lang.Number}.
|
|
||||||
* <p>
|
|
||||||
* This implementation uses the maximum precision permitted.
|
|
||||||
* @param number the number to format
|
|
||||||
* @param toAppendTo the <code>StringBuffer</code> to which the formatted
|
|
||||||
* text is to be appended
|
|
||||||
* @param pos On input: an alignment field, if desired.
|
|
||||||
* On output: the offsets of the alignment field.
|
|
||||||
* @return the value passed in as <code>toAppendTo</code>
|
|
||||||
* @exception IllegalArgumentException if <code>number</code> is
|
|
||||||
* null or not an instance of <code>Number</code>.
|
|
||||||
* @exception NullPointerException if <code>toAppendTo</code> or
|
|
||||||
* <code>pos</code> is null
|
|
||||||
* @exception ArithmeticException if rounding is needed with rounding
|
|
||||||
* mode being set to RoundingMode.UNNECESSARY
|
|
||||||
* @see java.text.FieldPosition
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public final StringBuffer format(Object number,
|
|
||||||
StringBuffer toAppendTo,
|
|
||||||
FieldPosition pos) {
|
|
||||||
if (number instanceof Long || number instanceof Integer ||
|
|
||||||
number instanceof Short || number instanceof Byte ||
|
|
||||||
number instanceof AtomicInteger ||
|
|
||||||
number instanceof AtomicLong ||
|
|
||||||
(number instanceof BigInteger &&
|
|
||||||
((BigInteger)number).bitLength () < 64)) {
|
|
||||||
return format(((Number)number).longValue(), toAppendTo, pos);
|
|
||||||
} else if (number instanceof BigDecimal) {
|
|
||||||
return format((BigDecimal)number, toAppendTo, pos);
|
|
||||||
} else if (number instanceof BigInteger) {
|
|
||||||
return format((BigInteger)number, toAppendTo, pos);
|
|
||||||
} else if (number instanceof Number) {
|
|
||||||
return format(((Number)number).doubleValue(), toAppendTo, pos);
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Cannot format given Object as a Number");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats a double to produce a string.
|
* Formats a double to produce a string.
|
||||||
* @param number The double to format
|
* @param number The double to format
|
||||||
|
@ -525,7 +539,7 @@ public class DecimalFormat extends NumberFormat {
|
||||||
// If fieldPosition is a DontCareFieldPosition instance we can
|
// If fieldPosition is a DontCareFieldPosition instance we can
|
||||||
// try to go to fast-path code.
|
// try to go to fast-path code.
|
||||||
boolean tryFastPath = false;
|
boolean tryFastPath = false;
|
||||||
if (fieldPosition == DontCareFieldPosition.INSTANCE)
|
if (fieldPosition == dontCareFieldPositionInstance)
|
||||||
tryFastPath = true;
|
tryFastPath = true;
|
||||||
else {
|
else {
|
||||||
fieldPosition.setBeginIndex(0);
|
fieldPosition.setBeginIndex(0);
|
||||||
|
@ -541,7 +555,7 @@ public class DecimalFormat extends NumberFormat {
|
||||||
}
|
}
|
||||||
|
|
||||||
// if fast-path could not work, we fallback to standard code.
|
// if fast-path could not work, we fallback to standard code.
|
||||||
return format(number, result, fieldPosition.getFieldDelegate());
|
return format(number, result, new FieldDelegate(fieldPosition));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -643,7 +657,7 @@ public class DecimalFormat extends NumberFormat {
|
||||||
fieldPosition.setBeginIndex(0);
|
fieldPosition.setBeginIndex(0);
|
||||||
fieldPosition.setEndIndex(0);
|
fieldPosition.setEndIndex(0);
|
||||||
|
|
||||||
return format(number, result, fieldPosition.getFieldDelegate());
|
return format(number, result, new FieldDelegate(fieldPosition));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -729,7 +743,7 @@ public class DecimalFormat extends NumberFormat {
|
||||||
FieldPosition fieldPosition) {
|
FieldPosition fieldPosition) {
|
||||||
fieldPosition.setBeginIndex(0);
|
fieldPosition.setBeginIndex(0);
|
||||||
fieldPosition.setEndIndex(0);
|
fieldPosition.setEndIndex(0);
|
||||||
return format(number, result, fieldPosition.getFieldDelegate());
|
return format(number, result, new FieldDelegate(fieldPosition));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -783,7 +797,7 @@ public class DecimalFormat extends NumberFormat {
|
||||||
fieldPosition.setBeginIndex(0);
|
fieldPosition.setBeginIndex(0);
|
||||||
fieldPosition.setEndIndex(0);
|
fieldPosition.setEndIndex(0);
|
||||||
|
|
||||||
return format(number, result, fieldPosition.getFieldDelegate(), false);
|
return format(number, result, new FieldDelegate(fieldPosition), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1994,8 +2008,8 @@ public class DecimalFormat extends NumberFormat {
|
||||||
@Override
|
@Override
|
||||||
public Number parse(String text, ParsePosition pos) {
|
public Number parse(String text, ParsePosition pos) {
|
||||||
// special case NaN
|
// special case NaN
|
||||||
if (text.regionMatches(pos.index, symbols.getNaN(), 0, symbols.getNaN().length())) {
|
if (text.regionMatches(pos.getIndex(), symbols.getNaN(), 0, symbols.getNaN().length())) {
|
||||||
pos.index = pos.index + symbols.getNaN().length();
|
pos.setIndex(pos.getIndex() + symbols.getNaN().length());
|
||||||
return new Double(Double.NaN);
|
return new Double(Double.NaN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2140,8 +2154,8 @@ public class DecimalFormat extends NumberFormat {
|
||||||
String positivePrefix, String negativePrefix,
|
String positivePrefix, String negativePrefix,
|
||||||
DigitList digits, boolean isExponent,
|
DigitList digits, boolean isExponent,
|
||||||
boolean status[]) {
|
boolean status[]) {
|
||||||
int position = parsePosition.index;
|
int position = parsePosition.getIndex();
|
||||||
int oldStart = parsePosition.index;
|
int oldStart = parsePosition.getIndex();
|
||||||
int backup;
|
int backup;
|
||||||
boolean gotPositive, gotNegative;
|
boolean gotPositive, gotNegative;
|
||||||
|
|
||||||
|
@ -2164,7 +2178,7 @@ public class DecimalFormat extends NumberFormat {
|
||||||
} else if (gotNegative) {
|
} else if (gotNegative) {
|
||||||
position += negativePrefix.length();
|
position += negativePrefix.length();
|
||||||
} else {
|
} else {
|
||||||
parsePosition.errorIndex = position;
|
parsePosition.setErrorIndex(position);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2271,7 +2285,7 @@ public class DecimalFormat extends NumberFormat {
|
||||||
|
|
||||||
if (subparse(text, pos, "", Character.toString(symbols.getMinusSign()), exponentDigits, true, stat) &&
|
if (subparse(text, pos, "", Character.toString(symbols.getMinusSign()), exponentDigits, true, stat) &&
|
||||||
exponentDigits.fitsIntoLong(stat[STATUS_POSITIVE], true)) {
|
exponentDigits.fitsIntoLong(stat[STATUS_POSITIVE], true)) {
|
||||||
position = pos.index; // Advance past the exponent
|
position = pos.getIndex(); // Advance past the exponent
|
||||||
exponent = (int)exponentDigits.getLong();
|
exponent = (int)exponentDigits.getLong();
|
||||||
if (!stat[STATUS_POSITIVE]) {
|
if (!stat[STATUS_POSITIVE]) {
|
||||||
exponent = -exponent;
|
exponent = -exponent;
|
||||||
|
@ -2301,8 +2315,8 @@ public class DecimalFormat extends NumberFormat {
|
||||||
// parse "$" with pattern "$#0.00". (return index 0 and error
|
// parse "$" with pattern "$#0.00". (return index 0 and error
|
||||||
// index 1).
|
// index 1).
|
||||||
if (!sawDigit && digitCount == 0) {
|
if (!sawDigit && digitCount == 0) {
|
||||||
parsePosition.index = oldStart;
|
parsePosition.setIndex(oldStart);
|
||||||
parsePosition.errorIndex = oldStart;
|
parsePosition.setIndex(oldStart);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2329,19 +2343,19 @@ public class DecimalFormat extends NumberFormat {
|
||||||
|
|
||||||
// fail if neither or both
|
// fail if neither or both
|
||||||
if (gotPositive == gotNegative) {
|
if (gotPositive == gotNegative) {
|
||||||
parsePosition.errorIndex = position;
|
parsePosition.setErrorIndex(position);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
parsePosition.index = position +
|
parsePosition.setIndex(position +
|
||||||
(gotPositive ? positiveSuffix.length() : negativeSuffix.length()); // mark success!
|
(gotPositive ? positiveSuffix.length() : negativeSuffix.length())); // mark success!
|
||||||
} else {
|
} else {
|
||||||
parsePosition.index = position;
|
parsePosition.setIndex(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
status[STATUS_POSITIVE] = gotPositive;
|
status[STATUS_POSITIVE] = gotPositive;
|
||||||
if (parsePosition.index == oldStart) {
|
if (parsePosition.getIndex() == oldStart) {
|
||||||
parsePosition.errorIndex = position;
|
parsePosition.setErrorIndex(position);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package java.text;
|
package com.moparisthebest.text;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
@ -62,12 +62,11 @@ import java.math.RoundingMode;
|
||||||
* derived by placing all the digits of the list to the right of the
|
* derived by placing all the digits of the list to the right of the
|
||||||
* decimal point, by 10^exponent.
|
* decimal point, by 10^exponent.
|
||||||
*
|
*
|
||||||
* @see Locale
|
* @see java.text.Format
|
||||||
* @see Format
|
* @see java.text.NumberFormat
|
||||||
* @see NumberFormat
|
|
||||||
* @see DecimalFormat
|
* @see DecimalFormat
|
||||||
* @see ChoiceFormat
|
* @see java.text.ChoiceFormat
|
||||||
* @see MessageFormat
|
* @see java.text.MessageFormat
|
||||||
* @author Mark Davis, Alan Liu
|
* @author Mark Davis, Alan Liu
|
||||||
*/
|
*/
|
||||||
final class DigitList implements Cloneable {
|
final class DigitList implements Cloneable {
|
||||||
|
|
|
@ -36,9 +36,17 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package java.text;
|
package com.moparisthebest.text;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.text.FieldPosition;
|
||||||
|
import java.text.Format;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This implementation delegates to the real interface/implementation
|
||||||
|
* found in java.text.Format$FieldDelegate
|
||||||
|
* <p/>
|
||||||
* FieldDelegate is notified by the various <code>Format</code>
|
* FieldDelegate is notified by the various <code>Format</code>
|
||||||
* implementations as they are formatting the Objects. This allows for
|
* implementations as they are formatting the Objects. This allows for
|
||||||
* storage of the individual sections of the formatted String for
|
* storage of the individual sections of the formatted String for
|
||||||
|
@ -48,10 +56,54 @@ package java.text;
|
||||||
* Delegates should NOT assume that the <code>Format</code> will notify
|
* Delegates should NOT assume that the <code>Format</code> will notify
|
||||||
* the delegate of fields in any particular order.
|
* the delegate of fields in any particular order.
|
||||||
*
|
*
|
||||||
* @see FieldPosition#getFieldDelegate
|
* @see java.text.FieldPosition#getFieldDelegate
|
||||||
* @see CharacterIteratorFieldDelegate
|
* @see java.text.CharacterIteratorFieldDelegate
|
||||||
*/
|
*/
|
||||||
interface FieldDelegate {
|
public class FieldDelegate {
|
||||||
|
|
||||||
|
private static final Method getFieldDelegate;
|
||||||
|
private static final Method format1;
|
||||||
|
private static final Method format2;
|
||||||
|
|
||||||
|
static {
|
||||||
|
Method gfd = null, f1 = null, f2 = null;
|
||||||
|
try {
|
||||||
|
gfd = FieldPosition.class.getDeclaredMethod("getFieldDelegate");
|
||||||
|
gfd.setAccessible(true);
|
||||||
|
|
||||||
|
final Class<?> realFieldDelegate = Class.forName("java.text.Format$FieldDelegate");
|
||||||
|
|
||||||
|
f1 = realFieldDelegate.getDeclaredMethod("formatted", Format.Field.class, Object.class, int.class, int.class, StringBuffer.class);
|
||||||
|
f1.setAccessible(true);
|
||||||
|
|
||||||
|
f2 = realFieldDelegate.getDeclaredMethod("formatted", int.class, Format.Field.class, Object.class, int.class, int.class, StringBuffer.class);
|
||||||
|
f2.setAccessible(true);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
throw new RuntimeException(DecimalFormat.DECIMAL_FORMAT_EXCEPTION, e);
|
||||||
|
}
|
||||||
|
getFieldDelegate = gfd;
|
||||||
|
format1 = f1;
|
||||||
|
format2 = f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Object fieldDelegate;
|
||||||
|
|
||||||
|
public FieldDelegate(final FieldPosition fieldPosition) {
|
||||||
|
//this(fieldPosition.getFieldDelegate());
|
||||||
|
Object fieldDelegate = null;
|
||||||
|
if (fieldPosition != null)
|
||||||
|
try {
|
||||||
|
fieldDelegate = getFieldDelegate.invoke(fieldPosition);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
throw new RuntimeException(DecimalFormat.DECIMAL_FORMAT_EXCEPTION, e);
|
||||||
|
}
|
||||||
|
this.fieldDelegate = fieldDelegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FieldDelegate(final Object fieldDelegate) {
|
||||||
|
this.fieldDelegate = fieldDelegate;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notified when a particular region of the String is formatted. This
|
* Notified when a particular region of the String is formatted. This
|
||||||
* method will be invoked if there is no corresponding integer field id
|
* method will be invoked if there is no corresponding integer field id
|
||||||
|
@ -65,7 +117,14 @@ interface FieldDelegate {
|
||||||
* NOT modify it.
|
* NOT modify it.
|
||||||
*/
|
*/
|
||||||
public void formatted(Format.Field attr, Object value, int start,
|
public void formatted(Format.Field attr, Object value, int start,
|
||||||
int end, StringBuffer buffer);
|
int end, StringBuffer buffer) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
format1.invoke(this.fieldDelegate, attr, value, start, end, buffer);
|
||||||
|
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||||
|
throw new RuntimeException(DecimalFormat.DECIMAL_FORMAT_EXCEPTION, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notified when a particular region of the String is formatted.
|
* Notified when a particular region of the String is formatted.
|
||||||
|
@ -79,5 +138,11 @@ interface FieldDelegate {
|
||||||
* NOT modify it.
|
* NOT modify it.
|
||||||
*/
|
*/
|
||||||
public void formatted(int fieldID, Format.Field attr, Object value,
|
public void formatted(int fieldID, Format.Field attr, Object value,
|
||||||
int start, int end, StringBuffer buffer);
|
int start, int end, StringBuffer buffer) {
|
||||||
|
try {
|
||||||
|
format2.invoke(this.fieldDelegate, fieldID, attr, value, start, end, buffer);
|
||||||
|
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||||
|
throw new RuntimeException(DecimalFormat.DECIMAL_FORMAT_EXCEPTION, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue