Here it is...
Code: Select all
/*
*
* -----------------------
* TreasuryPriceFormat.java
* -----------------------
*
*/
// package org.jfree.chart.util;
import java.text.FieldPosition;
import java.text.NumberFormat;
import java.text.ParsePosition;
import java.util.HashMap;
/**
* A custom number formatter that formats futures
* prices in 32nds of a point as described here:
* <p/>
* http://en.wikipedia.org/wiki/Commodity_tick
* and here:
* http://www.cmegroup.com/trading/interest-rates/files/IR147_USTreasuryRevised_Final_low_client.pdf
*
*/
public class TreasuryPriceFormat extends NumberFormat {
private boolean decimalIncluded;
private boolean trailingZeroIncluded;
private HashMap<String, String> m = new HashMap<String, String>();
/**
* Creates a new instance. if {@code trailingZeroIncluded} is false {@code decimalIncluded}
* is ignored.
*
* @param decimalIncluded Specify if a decimal should
* appear prior to any fraction of a 32nd. ie.,
* 123.3125 could be formatted as 123-100 or 123-10.0
*
* @param trailingZeroIncluded Specify if a trailing 0 should
* appear after a whole 32nd. ie.,
* 123.3125 could be formatted as 123-100 or 123-10.
* This should likely be {@code false} for displaying
* 30 year Treasury bond prices.
*/
public TreasuryPriceFormat(boolean decimalIncluded, boolean trailingZeroIncluded) {
super();
this.decimalIncluded = decimalIncluded;
this.trailingZeroIncluded = trailingZeroIncluded;
populateHashMap();
}
/**
* Returns if a trailing 0 will be shown.
*
* @return if a trailing 0 will be shown.
*/
public final boolean isTrailingZeroIncluded() {
return this.trailingZeroIncluded;
}
/**
* Returns if a decimal is included in formatted output.
*
* @return usingDecimal
*/
public final boolean isDecimalIncluded() {
return this.decimalIncluded;
}
@Override
public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos) {
return null;
}
/**
* Formats the specified double as a futures price in 32nds of a point
*
* @param number the number to format.
* @param toAppendTo the buffer to append to (ignored here).
* @param pos the field position (ignored here).
* @return The string buffer.
*/
public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
return format(number + "", toAppendTo, pos);
}
/**
* Formats the specified String as a futures price in 32nds of a point
*
* @param number the number to format.
* @param toAppendTo the buffer to append to (ignored here).
* @param pos the field position (ignored here).
* @return The string buffer.
*/
public StringBuffer format(String number, StringBuffer toAppendTo, FieldPosition pos) {
StringBuffer sb = new StringBuffer();
int decimalIndex = number.indexOf('.');
if (decimalIndex == -1) {
sb.append(number);
noFraction(sb);
} else {
String whole = number.substring(0, decimalIndex);
String frac = number.substring(decimalIndex + 1);
frac = frac.trim();
//remove trailing zeros.
while (frac.endsWith("0")) frac = frac.substring(0, frac.length() - 1);
sb.append(whole);
if (frac.length() == 0) {
noFraction(sb);
} else {
String s = m.get(frac);
if (s == null) throw new NumberFormatException("Invalid futures price " + number + ".");
sb.append(s);
}
}
return sb;
}
private void noFraction(StringBuffer sb) {
if (trailingZeroIncluded) {
if (decimalIncluded) {
sb.append("-00.0");
} else {
sb.append("-000");
}
} else {
sb.append("-00");
}
}
/**
* Parsing is not implemented, so this method always returns
* <code>null</code>.
*
* @param source ignored.
* @param parsePosition ignored.
* @return Always <code>null</code>.
*/
public Number parse(String source, ParsePosition parsePosition) {
return null;
}
private String f(String s) {
if (trailingZeroIncluded) {
if (decimalIncluded) {
return s;
} else {
return s.replace(".", "");
}
} else {
return s.replace(".0", "");
}
}
private void populateHashMap() {
m.put("0078125", f("-00.2"));
m.put("015625", f("-00.5"));
m.put("0234375", f("-00.7"));
m.put("03125", f("-01.0"));
m.put("0390625", f("-01.2"));
m.put("046875", f("-01.5"));
m.put("0546875", f("-01.7"));
m.put("0625", f("-02.0"));
m.put("0703125", f("-02.2"));
m.put("078125", f("-02.5"));
m.put("0859375", f("-02.7"));
m.put("09375", f("-03.0"));
m.put("1015625", f("-03.2"));
m.put("109375", f("-03.5"));
m.put("1171875", f("-03.7"));
m.put("125", f("-04.0"));
m.put("1328125", f("-04.2"));
m.put("140625", f("-04.5"));
m.put("1484375", f("-04.7"));
m.put("15625", f("-05.0"));
m.put("1640625", f("-05.2"));
m.put("171875", f("-05.5"));
m.put("1796875", f("-05.7"));
m.put("1875", f("-06.0"));
m.put("1953125", f("-06.2"));
m.put("203125", f("-06.5"));
m.put("2109375", f("-06.7"));
m.put("21875", f("-07.0"));
m.put("2265625", f("-07.2"));
m.put("234375", f("-07.5"));
m.put("2421875", f("-07.7"));
m.put("25", f("-08.0"));
m.put("2578125", f("-08.2"));
m.put("265625", f("-08.5"));
m.put("2734375", f("-08.7"));
m.put("28125", f("-09.0"));
m.put("2890625", f("-09.2"));
m.put("296875", f("-09.5"));
m.put("3046875", f("-09.7"));
m.put("3125", f("-10.0"));
m.put("3203125", f("-10.2"));
m.put("328125", f("-10.5"));
m.put("3359375", f("-10.7"));
m.put("34375", f("-11.0"));
m.put("3515625", f("-11.2"));
m.put("359375", f("-11.5"));
m.put("3671875", f("-11.7"));
m.put("375", f("-12.0"));
m.put("3828125", f("-12.2"));
m.put("390625", f("-12.5"));
m.put("3984375", f("-12.7"));
m.put("40625", f("-13.0"));
m.put("4140625", f("-13.2"));
m.put("421875", f("-13.5"));
m.put("4296875", f("-13.7"));
m.put("4375", f("-14.0"));
m.put("4453125", f("-14.2"));
m.put("453125", f("-14.5"));
m.put("4609375", f("-14.7"));
m.put("46875", f("-15.0"));
m.put("4765625", f("-15.2"));
m.put("484375", f("-15.5"));
m.put("4921875", f("-15.7"));
m.put("5", f("-16.0"));
m.put("5078125", f("-16.2"));
m.put("515625", f("-16.5"));
m.put("5234375", f("-16.7"));
m.put("53125", f("-17.0"));
m.put("5390625", f("-17.2"));
m.put("546875", f("-17.5"));
m.put("5546875", f("-17.7"));
m.put("5625", f("-18.0"));
m.put("5703125", f("-18.2"));
m.put("578125", f("-18.5"));
m.put("5859375", f("-18.7"));
m.put("59375", f("-19.0"));
m.put("6015625", f("-19.2"));
m.put("609375", f("-19.5"));
m.put("6171875", f("-19.7"));
m.put("625", f("-20.0"));
m.put("6328125", f("-20.2"));
m.put("640625", f("-20.5"));
m.put("6484375", f("-20.7"));
m.put("65625", f("-21.0"));
m.put("6640625", f("-21.2"));
m.put("671875", f("-21.5"));
m.put("6796875", f("-21.7"));
m.put("6875", f("-22.0"));
m.put("6953125", f("-22.2"));
m.put("703125", f("-22.5"));
m.put("7109375", f("-22.7"));
m.put("71875", f("-23.0"));
m.put("7265625", f("-23.2"));
m.put("734375", f("-23.5"));
m.put("7421875", f("-23.7"));
m.put("75", f("-24.0"));
m.put("7578125", f("-24.2"));
m.put("765625", f("-24.5"));
m.put("7734375", f("-24.7"));
m.put("78125", f("-25.0"));
m.put("7890625", f("-25.2"));
m.put("796875", f("-25.5"));
m.put("8046875", f("-25.7"));
m.put("8125", f("-26.0"));
m.put("8203125", f("-26.2"));
m.put("828125", f("-26.5"));
m.put("8359375", f("-26.7"));
m.put("84375", f("-27.0"));
m.put("8515625", f("-27.2"));
m.put("859375", f("-27.5"));
m.put("8671875", f("-27.7"));
m.put("875", f("-28.0"));
m.put("8828125", f("-28.2"));
m.put("890625", f("-28.5"));
m.put("8984375", f("-28.7"));
m.put("90625", f("-29.0"));
m.put("9140625", f("-29.2"));
m.put("921875", f("-29.5"));
m.put("9296875", f("-29.7"));
m.put("9375", f("-30.0"));
m.put("9453125", f("-30.2"));
m.put("953125", f("-30.5"));
m.put("9609375", f("-30.7"));
m.put("96875", f("-31.0"));
m.put("9765625", f("-31.2"));
m.put("984375", f("-31.5"));
m.put("9921875", f("-31.7"));
}
/**
* Returns a new {@code TreasuryPriceFormat} with the same
* properties as this {@code TreasuryPriceFormat}.
*/
@Override
public Object clone() {
TreasuryPriceFormat clone = (TreasuryPriceFormat) super.clone();
clone.decimalIncluded = decimalIncluded;
clone.trailingZeroIncluded = trailingZeroIncluded;
return clone;
}
}
Feel free to modify it or add it if you think it would help helpful.