blob: cd1ee7911497c0c59f45eb45c7749e288e471796 [file] [log] [blame]
// © 2018 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
package com.ibm.icu.impl.number;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.ObjectStreamException;
import java.text.AttributedCharacterIterator;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
import com.ibm.icu.number.FormattedNumber;
import com.ibm.icu.number.LocalizedNumberFormatter;
import com.ibm.icu.number.NumberFormatter;
import com.ibm.icu.util.ULocale;
/**
* A wrapper around LocalizedNumberFormatter implementing the Format interface, enabling improved
* compatibility with other APIs. This class is serializable.
*/
public class LocalizedNumberFormatterAsFormat extends Format {
private static final long serialVersionUID = 1L;
private final transient LocalizedNumberFormatter formatter;
// Even though the locale is inside the LocalizedNumberFormatter, we have to keep it here, too, because
// LocalizedNumberFormatter doesn't have a getLocale() method, and ICU-TC didn't want to add one.
private final transient ULocale locale;
public LocalizedNumberFormatterAsFormat(LocalizedNumberFormatter formatter, ULocale locale) {
this.formatter = formatter;
this.locale = locale;
}
/**
* Formats a Number using the wrapped LocalizedNumberFormatter. The provided object must be a Number.
*
* {@inheritDoc}
*/
@Override
public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
if (!(obj instanceof Number)) {
throw new IllegalArgumentException();
}
FormattedNumber result = formatter.format((Number) obj);
// always return first occurrence:
pos.setBeginIndex(0);
pos.setEndIndex(0);
boolean found = result.nextFieldPosition(pos);
if (found && toAppendTo.length() != 0) {
pos.setBeginIndex(pos.getBeginIndex() + toAppendTo.length());
pos.setEndIndex(pos.getEndIndex() + toAppendTo.length());
}
result.appendTo(toAppendTo);
return toAppendTo;
}
/**
* Formats a Number using the wrapped LocalizedNumberFormatter. The provided object must be a Number.
*
* {@inheritDoc}
*/
@Override
public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
if (!(obj instanceof Number)) {
throw new IllegalArgumentException();
}
return formatter.format((Number) obj).toCharacterIterator();
}
/**
* Not supported. This method will throw UnsupportedOperationException.
*/
@Override
public Object parseObject(String source, ParsePosition pos) {
throw new UnsupportedOperationException();
}
/**
* Gets the LocalizedNumberFormatter that this wrapper class uses to format numbers.
*
* @return The unwrapped LocalizedNumberFormatter.
*/
public LocalizedNumberFormatter getNumberFormatter() {
return formatter;
}
@Override
public int hashCode() {
return formatter.hashCode();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (other == null) {
return false;
}
if (!(other instanceof LocalizedNumberFormatterAsFormat)) {
return false;
}
return formatter.equals(((LocalizedNumberFormatterAsFormat) other).getNumberFormatter());
}
private Object writeReplace() throws ObjectStreamException {
Proxy proxy = new Proxy();
proxy.languageTag = locale.toLanguageTag();
proxy.skeleton = formatter.toSkeleton();
return proxy;
}
static class Proxy implements Externalizable {
private static final long serialVersionUID = 1L;
String languageTag;
String skeleton;
// Must have public constructor, to enable Externalizable
public Proxy() {
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeByte(0); // version
out.writeUTF(languageTag);
out.writeUTF(skeleton);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
in.readByte(); // version
languageTag = in.readUTF();
skeleton = in.readUTF();
}
private Object readResolve() throws ObjectStreamException {
return NumberFormatter.forSkeleton(skeleton)
.locale(ULocale.forLanguageTag(languageTag))
.toFormat();
}
}
}