package org.exist.xquery.util;
import org.exist.xquery.XPathException;
/**
* Formatter for numbers and dates. Concrete implementations are language-dependant.
*
* @author Wolfgang
*/
public abstract class NumberFormatter {
private static int[] zeroDigits = {
0x0030, 0x0660, 0x06f0, 0x0966, 0x09e6, 0x0a66, 0x0ae6, 0x0b66, 0x0be6, 0x0c66, 0x0ce6,
0x0d66, 0x0e50, 0x0ed0, 0x0f20, 0x1040, 0x17e0, 0x1810, 0x1946, 0x19d0, 0xff10,
0x104a0, 0x107ce, 0x107d8, 0x107e2, 0x107ec, 0x107f6 };
private static char OPTIONAL_DIGIT_SIGN = '#';
/**
* Get the zero digit corresponding to the digit family of the given value.
* This method was taken from saxon {@link <a href="http://saxon.sourceforge.net/">http://saxon.sourceforge.net/</a>}.
*
*/
public static int getZeroDigit(int val) {
for (int z = 0; z < zeroDigits.length; z++) {
if (val <= zeroDigits[z] + 9) {
if (val >= zeroDigits[z]) {
return zeroDigits[z];
} else {
return -1;
}
}
}
return -1;
}
public NumberFormatter() {
}
public abstract String getMonth(int month);
public abstract String getDay(int day);
public abstract String getAmPm(int hour);
public abstract String getOrdinalSuffix(long number);
public String formatNumber(long number, String picture) throws XPathException {
final int min = getMinDigits(picture);
final int max = getMaxDigits(picture);
return formatNumber(number, picture, min, max);
}
public String formatNumber(long number, String picture, int min, int max) throws XPathException {
if (picture == null)
{return "" + number;}
boolean ordinal = false;
if (picture.endsWith("o")) {
ordinal = true;
picture = picture.substring(0, picture.length() - 1);
} else if (picture.endsWith("c")) {
picture = picture.substring(0, picture.length() - 1);
}
final StringBuilder sb = new StringBuilder();
final int digitSign = getFirstDigit(picture);
final int zero = getZeroDigit(digitSign);
int count = 0;
long n = number;
while (n > 0) {
final int digit = zero + (int)n % 10;
sb.insert(0, (char)digit);
count++;
if (count == max)
{break;}
n = n / 10;
}
if (sb.length() < min) {
for (int i = sb.length(); i < min; i++) {
sb.insert(0, (char) zero);
}
}
if (ordinal)
{sb.append(getOrdinalSuffix(number));}
return sb.toString();
}
private int getFirstDigit(String picture) throws XPathException {
for (int i = 0; i < picture.length(); i++) {
final char ch = picture.charAt(i);
if (ch != OPTIONAL_DIGIT_SIGN)
{return ch;}
}
throw new XPathException("There should be at least one digit sign in the picture string: " + picture);
}
public static int getMinDigits(String picture) {
int count = 0;
for (int i = 0; i < picture.length(); i++) {
final char ch = picture.charAt(i);
if ((ch == 'o' || ch == 'c') && i == picture.length() - 1)
{break;}
if (ch != OPTIONAL_DIGIT_SIGN)
{count++;}
}
return count;
}
public static int getMaxDigits(String picture) {
int count = 0;
for (int i = 0; i < picture.length(); i++) {
final char ch = picture.charAt(i);
if ((ch == 'o' || ch == 'c') && i == picture.length() - 1)
{break;}
count++;
}
return count;
}
public static final NumberFormatter DEFAULT_FORMATTER = new NumberFormatter_en();
public static NumberFormatter getInstance(String language) {
final String className = NumberFormatter.class.getName() + "_" + language;
try {
final Class langClass = Class.forName(className);
return (NumberFormatter) langClass.newInstance();
} catch (final Exception e) {
return DEFAULT_FORMATTER;
}
}
}