Add preferredUnitListener
[sw/motorsim] / src / com / billkuker / rocketry / motorsim / RocketScience.java
1 package com.billkuker.rocketry.motorsim;\r
2 \r
3 import java.lang.reflect.Field;\r
4 import java.lang.reflect.Modifier;\r
5 import java.text.DecimalFormat;\r
6 import java.text.NumberFormat;\r
7 import java.util.HashSet;\r
8 import java.util.Set;\r
9 import java.util.prefs.Preferences;\r
10 \r
11 import javax.measure.quantity.Pressure;\r
12 import javax.measure.quantity.Quantity;\r
13 import javax.measure.unit.NonSI;\r
14 import javax.measure.unit.ProductUnit;\r
15 import javax.measure.unit.SI;\r
16 import javax.measure.unit.Unit;\r
17 import javax.measure.unit.UnitFormat;\r
18 \r
19 import org.jscience.physics.amount.Amount;\r
20 \r
21 public class RocketScience {\r
22         public static Unit<Pressure> PSI = new ProductUnit<Pressure>(NonSI.POUND_FORCE.divide(NonSI.INCH.pow(2)));\r
23         public static Unit<Impulse> NEWTON_SECOND = new ProductUnit<Impulse>(SI.NEWTON.times(SI.SECOND));\r
24         public static Unit<Impulse> POUND_SECOND = new ProductUnit<Impulse>(NonSI.POUND_FORCE.times(SI.SECOND));\r
25         static{\r
26                 UnitFormat.getInstance().label(PSI, "psi");\r
27                 UnitFormat.getInstance().label(NEWTON_SECOND, "Ns");\r
28         }\r
29 \r
30         public interface MolarWeight extends Quantity {\r
31                 public static final Unit<MolarWeight> UNIT = new ProductUnit<MolarWeight>(\r
32                                 SI.KILOGRAM.divide(SI.MOLE));\r
33         }\r
34         \r
35         public interface Impulse extends Quantity {\r
36                 public static Unit<Impulse> UNIT = NEWTON_SECOND;\r
37         }\r
38         \r
39         private static HashSet<UnitPreferenceListener> prefListeners = new HashSet<RocketScience.UnitPreferenceListener>();\r
40         public static interface UnitPreferenceListener{\r
41                 public void preferredUnitsChanged();\r
42         }\r
43         public static void addUnitPreferenceListener(UnitPreferenceListener l){\r
44                 prefListeners.add(l);\r
45         }\r
46 \r
47         public static enum UnitPreference{\r
48                 SI(new Unit[]{\r
49                                 javax.measure.unit.SI.MILLIMETER.pow(2),\r
50                                 javax.measure.unit.SI.MILLIMETER,\r
51                                 javax.measure.unit.SI.MILLIMETER.divide(javax.measure.unit.SI.SECOND),\r
52                                 javax.measure.unit.SI.NEWTON,\r
53                                 javax.measure.unit.SI.GRAM,\r
54                                 javax.measure.unit.SI.MEGA(javax.measure.unit.SI.PASCAL),\r
55                                 NEWTON_SECOND\r
56                 }),\r
57                 NONSI(new Unit[]{\r
58                                 javax.measure.unit.NonSI.INCH.pow(2),\r
59                                 javax.measure.unit.NonSI.INCH,\r
60                                 javax.measure.unit.NonSI.POUND_FORCE,\r
61                                 javax.measure.unit.NonSI.OUNCE,\r
62                                 javax.measure.unit.NonSI.INCH.divide(javax.measure.unit.SI.SECOND),\r
63                                 PSI,\r
64                                 POUND_SECOND\r
65                 });\r
66                 \r
67                 private static UnitPreference preference = SI;\r
68 \r
69                 static {\r
70                         Preferences prefs = Preferences.userNodeForPackage(RocketScience.class);\r
71                         String p = prefs.get("PreferedUnits", "SI");\r
72                         preference = UnitPreference.valueOf(p);\r
73                 }\r
74                 \r
75                 public static UnitPreference getUnitPreference(){\r
76                         return preference;\r
77                 }\r
78                 \r
79                 public static void setUnitPreference( final UnitPreference up ){\r
80                         if ( preference == up )\r
81                                 return;\r
82                         preference = up;\r
83                         Preferences prefs = Preferences.userNodeForPackage(RocketScience.class);\r
84                         prefs.put("PreferedUnits", up.toString());\r
85                         for ( UnitPreferenceListener l : prefListeners ){\r
86                                 l.preferredUnitsChanged();\r
87                         }\r
88                 }\r
89                 \r
90                 protected Set<Unit<?>> units = new HashSet<Unit<?>>();\r
91                 \r
92                 UnitPreference( Unit<?> u[] ){\r
93                         for ( Unit<?> uu : u )\r
94                                 units.add(uu);\r
95                 }\r
96                 \r
97                 @SuppressWarnings("unchecked")\r
98                 public <T extends Quantity> Unit<T> getPreferredUnit(Unit<T> u){\r
99                         if ( units.contains(u) )\r
100                                 return u;\r
101                         for( Unit<?> ret : units ){\r
102                                 if ( ret.isCompatible(u) ){\r
103                                         return (Unit<T>) ret;\r
104                                 }\r
105                         }\r
106                         return u;\r
107                 }\r
108                 \r
109                 @SuppressWarnings("unchecked")\r
110                 public <T extends Quantity> Unit<T> getPreferredUnit(Class<T> q){\r
111                         for( Unit<?> u : units ){\r
112                                 try {\r
113                                         return u.asType(q); \r
114                                 } catch ( ClassCastException e ) {\r
115                                         //Not compatible\r
116                                 }\r
117                         }\r
118                         try {\r
119                                 Field f = q.getDeclaredField("UNIT");\r
120                                 if ( Modifier.isStatic(f.getModifiers()) ){\r
121                                         if ( Unit.class.isAssignableFrom(f.getType())){\r
122                                                 return (Unit<T>)f.get(null);\r
123                                         }\r
124                                 }\r
125                         } catch (SecurityException e) {\r
126                                 e.printStackTrace();\r
127                         } catch (NoSuchFieldException e) {\r
128                                 e.printStackTrace();\r
129                         } catch (IllegalArgumentException e) {\r
130                                 // TODO Auto-generated catch block\r
131                                 e.printStackTrace();\r
132                         } catch (IllegalAccessException e) {\r
133                                 // TODO Auto-generated catch block\r
134                                 e.printStackTrace();\r
135                         }\r
136                         return null;\r
137                 }\r
138         }\r
139 \r
140         public static <T extends Quantity> String ammountToString(Amount<T> a) {\r
141                 if ( a == null )\r
142                         return "Null";\r
143                 final NumberFormat nf = new DecimalFormat("##########.###");\r
144                 return nf.format(a.doubleValue(a.getUnit())) + " " + a.getUnit();\r
145         }\r
146         \r
147         public static <T extends Quantity> String ammountToRoundedString(Amount<T> a) {\r
148                 if (a == null)\r
149                         return "Null";\r
150                 Unit<T> u = RocketScience.UnitPreference.preference.getPreferredUnit(a\r
151                                 .getUnit());\r
152                 double d = a.doubleValue(u);\r
153 \r
154                 DecimalFormat df;\r
155 \r
156                 if (Math.abs(d) < 10.0) {\r
157                         df = new DecimalFormat("#.##");\r
158                 } else if (Math.abs(d) < 100.0) {\r
159                         df = new DecimalFormat("#.#");\r
160                 } else {\r
161                         df = new DecimalFormat("#");\r
162                 }\r
163 \r
164                 return df.format(d) + " " + u.toString();\r
165         }\r
166 \r
167 }\r