1 9 package org.jscience.physics.quantities; 10 11 import java.text.DecimalFormat ; 12 import java.text.ParseException ; 13 14 import javolution.realtime.LocalReference; 15 import javolution.util.FastMap; 16 import javolution.lang.MathLib; 17 import javolution.lang.Text; 18 import javolution.lang.TextFormat; 19 import javolution.lang.TypeFormat; 20 21 import org.jscience.physics.units.Unit; 22 23 30 public abstract class QuantityFormat extends TextFormat<Quantity> { 31 32 35 private static FastMap<Class , LocalReference<Unit>> CLASS_TO_DISPLAY_UNIT = new FastMap<Class , LocalReference<Unit>>(); 36 37 44 public static final QuantityFormat EXACT_DIGITS_ONLY = new ExactDigitsOnly(); 45 46 49 private static final LocalReference<QuantityFormat> CURRENT = new LocalReference<QuantityFormat>( 50 QuantityFormat.EXACT_DIGITS_ONLY); 51 52 55 protected QuantityFormat() { 56 } 57 58 64 public static QuantityFormat getInstance() { 65 return CURRENT.get(); 66 } 67 68 71 public static QuantityFormat current() { 72 return getInstance(); 73 } 74 75 80 public static void setCurrent(QuantityFormat format) { 81 CURRENT.set(format); 82 } 83 84 90 public Unit getOutputUnit(Quantity q) { 91 LocalReference<Unit> unit = CLASS_TO_DISPLAY_UNIT.get(q.getClass()); 92 if ((unit != null) && (unit.get() != null)) 93 return unit.get(); 94 return q.getUnit(); 95 } 96 97 100 private static class ExactDigitsOnly extends QuantityFormat { 101 102 105 private ExactDigitsOnly() { 106 } 107 108 public Text format(Quantity q) { 110 Unit u = getOutputUnit(q); 111 double error = MathLib.abs(q.getRelativeError()); 112 int digits = (int) -(MathLib.log10(error)); 113 if (digits <= 0) { 114 digits = 1; 115 } 116 double amount = q.to(u).getAmount(); 117 boolean scientific = (MathLib.abs(amount) >= 1E6) 118 || (MathLib.abs(amount) < 1E-6); 119 boolean showZeros = true; 120 return Text.valueOf(amount, digits, scientific, showZeros).concat( 121 Text.valueOf(' ').concat(u.toText())); 122 } 123 124 public Quantity parse(CharSequence csq, Cursor pos) { 126 int sepIndex = TypeFormat.indexOf(" ", csq, pos.getIndex()); 127 if (sepIndex <= 0) { 128 sepIndex = csq.length(); 129 } 130 double amount = TypeFormat.parseDouble(csq.subSequence(pos 131 .getIndex(), sepIndex)); 132 Unit unit = Unit.valueOf(csq.subSequence(sepIndex, csq.length())); 133 pos.setIndex(csq.length()); 134 return Quantity.valueOf(amount, unit); 135 } 136 137 } 138 139 145 public static class Decimal extends QuantityFormat { 146 147 150 private final DecimalFormat _decimalFormat; 151 152 159 public Decimal(String pattern) { 160 _decimalFormat = new DecimalFormat (pattern); 161 } 162 163 public Text format(Quantity q) { 165 Unit outputUnit = getOutputUnit(q); 166 double amount = q.to(outputUnit).getAmount(); 167 String amountStr = _decimalFormat.format(amount); 168 return Text.valueOf(amountStr).concat( 169 Text.valueOf(' ').concat(outputUnit.toText())); 170 } 171 172 public Quantity parse(CharSequence csq, Cursor pos) { 174 int sepIndex = TypeFormat.indexOf(" ", csq, pos.getIndex()); 175 if (sepIndex <= 0) { 176 sepIndex = csq.length(); 177 } 178 String amountStr = csq.subSequence(pos.getIndex(), sepIndex) 179 .toString(); 180 double amount; 181 try { 182 amount = _decimalFormat.parse(amountStr).doubleValue(); 183 } catch (ParseException e) { 184 throw new IllegalArgumentException (e); 185 } 186 Unit unit = Unit.valueOf(csq.subSequence(sepIndex, csq.length())); 187 pos.setIndex(csq.length()); 188 return Quantity.valueOf(amount, unit); 189 } 190 } 191 192 199 public static void show(Class < ? extends Quantity> clazz, Unit inUnit) { 200 synchronized (CLASS_TO_DISPLAY_UNIT) { 201 LocalReference<Unit> displayUnit = CLASS_TO_DISPLAY_UNIT.get(clazz); 202 if (displayUnit == null) { 203 displayUnit = new LocalReference(); 204 CLASS_TO_DISPLAY_UNIT.put(clazz, displayUnit); 205 } 206 displayUnit.set(inUnit); 207 } 208 } 209 } | Popular Tags |