updates for 0.9.4
[debian/openrocket] / src / net / sf / openrocket / unit / UnitGroup.java
1 package net.sf.openrocket.unit;
2
3 import static net.sf.openrocket.util.MathUtil.pow2;
4
5 import java.util.ArrayList;
6 import java.util.Collections;
7 import java.util.HashMap;
8 import java.util.Map;
9 import java.util.regex.Matcher;
10 import java.util.regex.Pattern;
11
12 import net.sf.openrocket.rocketcomponent.Configuration;
13 import net.sf.openrocket.rocketcomponent.Rocket;
14
15
16 /**
17  * A group of units (eg. length, mass etc.).  Contains a list of different units of a same
18  * quantity.
19  * 
20  * @author Sampo Niskanen <sampo.niskanen@iki.fi>
21  */
22
23 public class UnitGroup {
24
25         public static final UnitGroup UNITS_NONE;
26         
27         public static final UnitGroup UNITS_MOTOR_DIMENSIONS;
28         public static final UnitGroup UNITS_LENGTH;
29         public static final UnitGroup UNITS_DISTANCE;
30         
31         public static final UnitGroup UNITS_AREA;
32         public static final UnitGroup UNITS_STABILITY;
33         public static final UnitGroup UNITS_VELOCITY;
34         public static final UnitGroup UNITS_ACCELERATION;
35         public static final UnitGroup UNITS_MASS;
36         public static final UnitGroup UNITS_ANGLE;
37         public static final UnitGroup UNITS_DENSITY_BULK;
38         public static final UnitGroup UNITS_DENSITY_SURFACE;
39         public static final UnitGroup UNITS_DENSITY_LINE;
40         public static final UnitGroup UNITS_FORCE;
41         public static final UnitGroup UNITS_IMPULSE;
42         
43         /** Time in the order of less than a second (time step etc). */
44         public static final UnitGroup UNITS_TIME_STEP;
45         
46         /** Time in the order of seconds (motor delay etc). */
47         public static final UnitGroup UNITS_SHORT_TIME;
48         
49         /** Time in the order of the flight time of a rocket. */
50         public static final UnitGroup UNITS_FLIGHT_TIME;
51         public static final UnitGroup UNITS_ROLL;
52         public static final UnitGroup UNITS_TEMPERATURE;
53         public static final UnitGroup UNITS_PRESSURE;
54         public static final UnitGroup UNITS_RELATIVE;
55         public static final UnitGroup UNITS_ROUGHNESS;
56         
57         public static final UnitGroup UNITS_COEFFICIENT;
58         
59         
60         public static final Map<String, UnitGroup> UNITS;
61         
62         
63         /*
64          * Note:  Units may not use HTML tags.
65          */
66         static {
67                 UNITS_NONE = new UnitGroup();
68                 UNITS_NONE.addUnit(Unit.NOUNIT2);
69                 
70                 UNITS_LENGTH = new UnitGroup();
71                 UNITS_LENGTH.addUnit(new GeneralUnit(0.001,"mm"));
72                 UNITS_LENGTH.addUnit(new GeneralUnit(0.01,"cm"));
73                 UNITS_LENGTH.addUnit(new GeneralUnit(1,"m"));
74                 UNITS_LENGTH.addUnit(new GeneralUnit(0.0254,"in"));
75                 UNITS_LENGTH.addUnit(new GeneralUnit(0.3048,"ft"));
76                 UNITS_LENGTH.setDefaultUnit(1);
77                 
78                 UNITS_MOTOR_DIMENSIONS = new UnitGroup();
79                 UNITS_MOTOR_DIMENSIONS.addUnit(new GeneralUnit(0.001,"mm"));
80                 UNITS_MOTOR_DIMENSIONS.addUnit(new GeneralUnit(0.01,"cm"));
81                 UNITS_MOTOR_DIMENSIONS.addUnit(new GeneralUnit(0.0254,"in"));
82                 UNITS_MOTOR_DIMENSIONS.setDefaultUnit(0);
83                 
84                 UNITS_DISTANCE = new UnitGroup();
85                 UNITS_DISTANCE.addUnit(new GeneralUnit(1,"m"));
86                 UNITS_DISTANCE.addUnit(new GeneralUnit(1000,"km"));
87                 UNITS_DISTANCE.addUnit(new GeneralUnit(0.3048,"ft"));
88                 UNITS_DISTANCE.addUnit(new GeneralUnit(0.9144,"yd"));
89                 UNITS_DISTANCE.addUnit(new GeneralUnit(1609.344,"mi"));
90                 
91                 UNITS_AREA = new UnitGroup();
92                 UNITS_AREA.addUnit(new GeneralUnit(pow2(0.001),"mm\u00b2"));
93                 UNITS_AREA.addUnit(new GeneralUnit(pow2(0.01),"cm\u00b2"));
94                 UNITS_AREA.addUnit(new GeneralUnit(1,"m\u00b2"));
95                 UNITS_AREA.addUnit(new GeneralUnit(pow2(0.0254),"in\u00b2"));
96                 UNITS_AREA.addUnit(new GeneralUnit(pow2(0.3048),"ft\u00b2"));
97                 UNITS_AREA.setDefaultUnit(1);
98                 
99                 
100                 UNITS_STABILITY = new UnitGroup();
101                 UNITS_STABILITY.addUnit(new GeneralUnit(0.001,"mm"));
102                 UNITS_STABILITY.addUnit(new GeneralUnit(0.01,"cm"));
103                 UNITS_STABILITY.addUnit(new GeneralUnit(0.0254,"in"));
104                 UNITS_STABILITY.addUnit(new CaliberUnit((Rocket)null));
105                 UNITS_STABILITY.setDefaultUnit(3);
106                 
107                 UNITS_VELOCITY = new UnitGroup();
108                 UNITS_VELOCITY.addUnit(new GeneralUnit(1, "m/s"));
109                 UNITS_VELOCITY.addUnit(new GeneralUnit(1/3.6, "km/h"));
110                 UNITS_VELOCITY.addUnit(new GeneralUnit(0.3048, "ft/s"));
111                 UNITS_VELOCITY.addUnit(new GeneralUnit(0.44704, "mph"));
112                 
113                 UNITS_ACCELERATION = new UnitGroup();
114                 UNITS_ACCELERATION.addUnit(new GeneralUnit(1, "m/s\u00b2"));
115                 UNITS_ACCELERATION.addUnit(new GeneralUnit(0.3048, "ft/s\u00b2"));
116                 
117
118                 UNITS_MASS = new UnitGroup();
119                 UNITS_MASS.addUnit(new GeneralUnit(0.001,"g"));
120                 UNITS_MASS.addUnit(new GeneralUnit(1,"kg"));
121                 UNITS_MASS.addUnit(new GeneralUnit(0.0283495231,"oz"));
122                 UNITS_MASS.addUnit(new GeneralUnit(0.45359237,"lb"));
123                 
124                 UNITS_ANGLE = new UnitGroup();
125                 UNITS_ANGLE.addUnit(new DegreeUnit());
126                 UNITS_ANGLE.addUnit(new FixedPrecisionUnit("rad",0.01));
127                 
128                 UNITS_DENSITY_BULK = new UnitGroup();
129                 UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1000,"g/cm\u00b3"));
130                 UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1,"kg/m\u00b3"));
131                 UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1729.99404,"oz/in\u00b3"));
132                 UNITS_DENSITY_BULK.addUnit(new GeneralUnit(16.0184634,"lb/ft\u00b3"));
133
134                 UNITS_DENSITY_SURFACE = new UnitGroup();
135                 UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(10,"g/cm\u00b2"));
136                 UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(0.001,"g/m\u00b2"));
137                 UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(1,"kg/m\u00b2"));
138                 UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(43.9418487,"oz/in\u00b2"));
139                 UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(0.305151727,"oz/ft\u00b2"));
140                 UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(4.88242764,"lb/ft\u00b2"));
141                 UNITS_DENSITY_SURFACE.setDefaultUnit(1);
142
143                 UNITS_DENSITY_LINE = new UnitGroup();
144                 UNITS_DENSITY_LINE.addUnit(new GeneralUnit(0.001,"g/m"));
145                 UNITS_DENSITY_LINE.addUnit(new GeneralUnit(1,"kg/m"));
146                 UNITS_DENSITY_LINE.addUnit(new GeneralUnit(0.0930102465,"oz/ft"));
147
148                 UNITS_FORCE = new UnitGroup();
149                 UNITS_FORCE.addUnit(new GeneralUnit(1,"N"));
150                 UNITS_FORCE.addUnit(new GeneralUnit(4.44822162,"lbf"));
151                 UNITS_FORCE.addUnit(new GeneralUnit(9.80665,"kgf"));
152
153                 UNITS_IMPULSE = new UnitGroup();
154                 UNITS_IMPULSE.addUnit(new GeneralUnit(1,"Ns"));
155                 UNITS_IMPULSE.addUnit(new GeneralUnit(4.44822162, "lbf\u00b7s"));
156
157                 UNITS_TIME_STEP = new UnitGroup();
158                 UNITS_TIME_STEP.addUnit(new FixedPrecisionUnit("ms", 1, 0.001));
159                 UNITS_TIME_STEP.addUnit(new FixedPrecisionUnit("s", 0.01));
160                 UNITS_TIME_STEP.setDefaultUnit(1);
161
162                 UNITS_SHORT_TIME = new UnitGroup();
163                 UNITS_SHORT_TIME.addUnit(new GeneralUnit(1,"s"));
164
165                 UNITS_FLIGHT_TIME = new UnitGroup();
166                 UNITS_FLIGHT_TIME.addUnit(new GeneralUnit(1,"s"));
167                 UNITS_FLIGHT_TIME.addUnit(new GeneralUnit(60,"min"));
168                 
169                 UNITS_ROLL = new UnitGroup();
170                 UNITS_ROLL.addUnit(new GeneralUnit(1, "rad/s"));
171                 UNITS_ROLL.addUnit(new GeneralUnit(2*Math.PI, "r/s"));
172                 UNITS_ROLL.addUnit(new GeneralUnit(2*Math.PI/60, "rpm"));
173                 UNITS_ROLL.setDefaultUnit(1);
174
175                 UNITS_TEMPERATURE = new UnitGroup();
176                 UNITS_TEMPERATURE.addUnit(new FixedPrecisionUnit("K", 1));
177                 UNITS_TEMPERATURE.addUnit(new TemperatureUnit(1, 273.15, "\u00b0C"));
178                 UNITS_TEMPERATURE.addUnit(new TemperatureUnit(5.0/9.0, 459.67, "\u00b0F"));
179                 UNITS_TEMPERATURE.setDefaultUnit(1);
180                 
181                 UNITS_PRESSURE = new UnitGroup();
182                 UNITS_PRESSURE.addUnit(new FixedPrecisionUnit("mbar", 1, 1.0e2));
183                 UNITS_PRESSURE.addUnit(new FixedPrecisionUnit("bar", 0.001, 1.0e5));
184                 UNITS_PRESSURE.addUnit(new FixedPrecisionUnit("atm", 0.001, 1.01325e5));
185                 UNITS_PRESSURE.addUnit(new GeneralUnit(101325.0/760.0, "mmHg"));
186                 UNITS_PRESSURE.addUnit(new GeneralUnit(3386.389, "inHg"));
187                 UNITS_PRESSURE.addUnit(new GeneralUnit(6894.75729, "psi"));
188                 UNITS_PRESSURE.addUnit(new GeneralUnit(1, "Pa"));
189
190                 UNITS_RELATIVE = new UnitGroup();
191                 UNITS_RELATIVE.addUnit(new FixedPrecisionUnit("\u200b", 0.01));
192                 UNITS_RELATIVE.addUnit(new FixedPrecisionUnit("%", 1, 0.01));
193                 UNITS_RELATIVE.setDefaultUnit(1);
194
195                 
196                 UNITS_ROUGHNESS = new UnitGroup();
197                 UNITS_ROUGHNESS.addUnit(new GeneralUnit(0.000001, "\u03bcm"));
198                 UNITS_ROUGHNESS.addUnit(new GeneralUnit(0.0000254, "mil"));
199                 
200                 
201                 UNITS_COEFFICIENT = new UnitGroup();
202                 UNITS_COEFFICIENT.addUnit(new FixedPrecisionUnit("\u200b", 0.01));  // zero-width space
203                 
204
205                 HashMap<String,UnitGroup> map = new HashMap<String,UnitGroup>();
206                 map.put("NONE", UNITS_NONE);
207                 map.put("LENGTH", UNITS_LENGTH);
208                 map.put("MOTOR_DIMENSIONS", UNITS_MOTOR_DIMENSIONS);
209                 map.put("DISTANCE", UNITS_DISTANCE);
210                 map.put("VELOCITY", UNITS_VELOCITY);
211                 map.put("ACCELERATION", UNITS_ACCELERATION);
212                 map.put("AREA", UNITS_AREA);
213                 map.put("STABILITY", UNITS_STABILITY);
214                 map.put("MASS", UNITS_MASS);
215                 map.put("ANGLE", UNITS_ANGLE);
216                 map.put("DENSITY_BULK", UNITS_DENSITY_BULK);
217                 map.put("DENSITY_SURFACE", UNITS_DENSITY_SURFACE);
218                 map.put("DENSITY_LINE", UNITS_DENSITY_LINE);
219                 map.put("FORCE", UNITS_FORCE);
220                 map.put("IMPULSE", UNITS_IMPULSE);
221                 map.put("TIME_STEP", UNITS_TIME_STEP);
222                 map.put("SHORT_TIME", UNITS_SHORT_TIME);
223                 map.put("FLIGHT_TIME", UNITS_FLIGHT_TIME);
224                 map.put("ROLL", UNITS_ROLL);
225                 map.put("TEMPERATURE", UNITS_TEMPERATURE);
226                 map.put("PRESSURE", UNITS_PRESSURE);
227                 map.put("RELATIVE", UNITS_RELATIVE);
228                 map.put("ROUGHNESS", UNITS_ROUGHNESS);
229                 map.put("COEFFICIENT", UNITS_COEFFICIENT);
230
231                 UNITS = Collections.unmodifiableMap(map);
232         }
233         
234         public static void setDefaultMetricUnits() {
235                 UNITS_LENGTH.setDefaultUnit("cm");
236                 UNITS_MOTOR_DIMENSIONS.setDefaultUnit("mm");
237                 UNITS_DISTANCE.setDefaultUnit("m");
238                 UNITS_AREA.setDefaultUnit("cm\u00b2");
239                 UNITS_STABILITY.setDefaultUnit("cal");
240                 UNITS_VELOCITY.setDefaultUnit("m/s");
241                 UNITS_ACCELERATION.setDefaultUnit("m/s\u00b2");
242                 UNITS_MASS.setDefaultUnit("g");
243                 UNITS_ANGLE.setDefaultUnit(0);
244                 UNITS_DENSITY_BULK.setDefaultUnit("g/cm\u00b3");
245                 UNITS_DENSITY_SURFACE.setDefaultUnit("g/m\u00b2");
246                 UNITS_DENSITY_LINE.setDefaultUnit("g/m");
247                 UNITS_FORCE.setDefaultUnit("N");
248                 UNITS_IMPULSE.setDefaultUnit("Ns");
249                 UNITS_TIME_STEP.setDefaultUnit("s");
250                 UNITS_FLIGHT_TIME.setDefaultUnit("s");
251                 UNITS_ROLL.setDefaultUnit("r/s");
252                 UNITS_TEMPERATURE.setDefaultUnit(1);
253                 UNITS_PRESSURE.setDefaultUnit("mbar");
254                 UNITS_RELATIVE.setDefaultUnit("%");
255                 UNITS_ROUGHNESS.setDefaultUnit("\u03bcm");
256         }
257         
258         public static void setDefaultImperialUnits() {
259                 UNITS_LENGTH.setDefaultUnit("in");
260                 UNITS_MOTOR_DIMENSIONS.setDefaultUnit("in");
261                 UNITS_DISTANCE.setDefaultUnit("ft");
262                 UNITS_AREA.setDefaultUnit("in\u00b2");
263                 UNITS_STABILITY.setDefaultUnit("cal");
264                 UNITS_VELOCITY.setDefaultUnit("ft/s");
265                 UNITS_ACCELERATION.setDefaultUnit("ft/s\u00b2");
266                 UNITS_MASS.setDefaultUnit("oz");
267                 UNITS_ANGLE.setDefaultUnit(0);
268                 UNITS_DENSITY_BULK.setDefaultUnit("oz/in\u00b3");
269                 UNITS_DENSITY_SURFACE.setDefaultUnit("oz/ft\u00b2");
270                 UNITS_DENSITY_LINE.setDefaultUnit("oz/ft");
271                 UNITS_FORCE.setDefaultUnit("N");
272                 UNITS_IMPULSE.setDefaultUnit("Ns");
273                 UNITS_TIME_STEP.setDefaultUnit("s");
274                 UNITS_FLIGHT_TIME.setDefaultUnit("s");
275                 UNITS_ROLL.setDefaultUnit("r/s");
276                 UNITS_TEMPERATURE.setDefaultUnit(2);
277                 UNITS_PRESSURE.setDefaultUnit("mbar");
278                 UNITS_RELATIVE.setDefaultUnit("%");
279                 UNITS_ROUGHNESS.setDefaultUnit("mil");
280         }
281         
282         
283         
284         public static UnitGroup stabilityUnits(Rocket rocket) {
285                 return new StabilityUnitGroup(rocket);
286         }
287         
288         
289         public static UnitGroup stabilityUnits(Configuration config) {
290                 return new StabilityUnitGroup(config);
291         }
292         
293
294         //////////////////////////////////////////////////////
295
296         
297         private ArrayList<Unit> units = new ArrayList<Unit>();
298         private int defaultUnit = 0;
299         
300         public int getUnitCount() {
301                 return units.size();
302         }
303
304         public Unit getDefaultUnit() {
305                 return units.get(defaultUnit);
306         }
307         
308         public int getDefaultUnitIndex() {
309                 return defaultUnit;
310         }
311         
312         public void setDefaultUnit(int n) {
313                 if (n<0 || n>=units.size()) {
314                         throw new IllegalArgumentException("index out of range: "+n);
315                 }
316                 defaultUnit = n;
317         }
318         
319         
320         
321         /**
322          * Find a unit by approximate unit name.  Only letters and (ordinary) numbers are
323          * considered in the matching.  This method is mainly means for testing, allowing
324          * a simple means to obtain a particular unit.
325          * 
326          * @param str   the unit name.
327          * @return              the corresponding unit, or <code>null</code> if not found.
328          */
329         public Unit findApproximate(String str) {
330                 str = str.replaceAll("\\W", "").trim();
331                 for (Unit u: units) {
332                         String name = u.getUnit().replaceAll("\\W", "").trim();
333                         if (str.equalsIgnoreCase(name))
334                                 return u;
335                 }
336                 return null;
337         }
338         
339         /**
340          * Set the default unit based on the unit name.  Does nothing if the name
341          * does not match any of the units.
342          * 
343          * @param name  the unit name (<code>null</code> ok).
344          * @return              <code>true</code> if the the default was set, 
345          *                              <code>false</code> if a matching unit was not found.  
346          */
347         public boolean setDefaultUnit(String name) {
348                 if (name == null)
349                         return false;
350                 
351                 for (int i=0; i < units.size(); i++) {
352                         if (name.equals(units.get(i).getUnit())) {
353                                 setDefaultUnit(i);
354                                 return true;
355                         }
356                 }
357                 return false;
358         }
359
360         
361         public Unit getUnit(int n) {
362                 return units.get(n);
363         }
364         
365         public int getUnitIndex(Unit u) {
366                 return units.indexOf(u);
367         }
368         
369         public void addUnit(Unit u) {
370                 units.add(u);
371         }
372         
373         public void addUnit(int n, Unit u) {
374                 units.add(n,u);
375         }
376         
377         public void removeUnit(int n) {
378                 units.remove(n);
379         }
380         
381         public boolean contains(Unit u) {
382                 return units.contains(u);
383         }
384         
385         public Unit[] getUnits() {
386                 return units.toArray(new Unit[0]);
387         }
388         
389         
390         /**
391          * Return the value formatted by the default unit of this group.
392          * It is the same as calling <code>getDefaultUnit().toString(value)</code>.
393          * 
394          * @param value         the SI value to format.
395          * @return                      the formatted string.
396          * @see                         Unit#toString(double)
397          */
398         public String toString(double value) {
399                 return this.getDefaultUnit().toString(value);
400         }
401         
402         
403         /**
404          * Return the value formatted by the default unit of this group including the unit.
405          * It is the same as calling <code>getDefaultUnit().toStringUnit(value)</code>.
406          * 
407          * @param value         the SI value to format.
408          * @return                      the formatted string.
409          * @see                         Unit#toStringUnit(double)
410          */
411         public String toStringUnit(double value) {
412                 return this.getDefaultUnit().toStringUnit(value);
413         }
414         
415         
416
417         
418         
419         /**
420          * Creates a new Value object with the specified value and the default unit of this group.
421          * 
422          * @param value the value to set.
423          * @return              a new Value object.
424          */
425         public Value toValue(double value) {
426                 return this.getDefaultUnit().toValue(value);
427         }
428         
429         
430         
431         
432         private static final Pattern STRING_PATTERN = Pattern.compile("^\\s*([0-9.,-]+)(.*?)$");
433         /**
434          * Converts a string into an SI value.  If the string has one of the units in this
435          * group appended to it, that unit will be used in conversion.  Otherwise the default
436          * unit will be used.  If an unknown unit is specified or the value does not parse
437          * with <code>Double.parseDouble</code> then a <code>NumberFormatException</code> 
438          * is thrown.
439          * <p>
440          * This method is applicable only for simple units without e.g. powers.
441          * 
442          * @param str   the string to parse.
443          * @return              the SI value.
444          * @throws NumberFormatException   if the string cannot be parsed.
445          */
446         public double fromString(String str) {
447                 Matcher matcher = STRING_PATTERN.matcher(str);
448                 
449                 if (!matcher.matches()) {
450                         throw new NumberFormatException("string did not match required pattern");
451                 }
452                 
453                 double value = Double.parseDouble(matcher.group(1));
454                 String unit = matcher.group(2).trim();
455                 
456                 if (unit.equals("")) {
457                         value = this.getDefaultUnit().fromUnit(value);
458                 } else {
459                         int i;
460                         for (i=0; i < units.size(); i++) {
461                                 Unit u = units.get(i);
462                                 if (unit.equalsIgnoreCase(u.getUnit())) {
463                                         value = u.fromUnit(value);
464                                         break;
465                                 }
466                         }
467                         if (i >= units.size()) {
468                                 throw new NumberFormatException("unknown unit "+unit);
469                         }
470                 }
471                 
472                 return value;
473         }
474         
475         
476         ///////////////////////////
477         
478         
479         /**
480          * A private class that switches the CaliberUnit to a rocket-specific CaliberUnit.
481          * All other methods are passed through to UNITS_STABILITY.
482          */
483         private static class StabilityUnitGroup extends UnitGroup {
484                 
485                 private final CaliberUnit caliberUnit;
486                 
487                 
488                 public StabilityUnitGroup(Rocket rocket) {
489                         caliberUnit = new CaliberUnit(rocket);
490                 }
491                 
492                 public StabilityUnitGroup(Configuration config) {
493                         caliberUnit = new CaliberUnit(config);
494                 }
495                 
496
497                 ////  Modify CaliberUnit to use local variable
498                 
499                 @Override
500                 public Unit getDefaultUnit() {
501                         return getUnit(UNITS_STABILITY.getDefaultUnitIndex());
502                 }
503
504                 @Override
505                 public Unit getUnit(int n) {
506                         Unit u = UNITS_STABILITY.getUnit(n);
507                         if (u instanceof CaliberUnit) {
508                                 return caliberUnit;
509                         }
510                         return u;
511                 }
512
513                 @Override
514                 public int getUnitIndex(Unit u) {
515                         if (u instanceof CaliberUnit) {
516                                 for (int i=0; i < UNITS_STABILITY.getUnitCount(); i++) {
517                                         if (UNITS_STABILITY.getUnit(i) instanceof CaliberUnit)
518                                                 return i;
519                                 }
520                         }
521                         return UNITS_STABILITY.getUnitIndex(u);
522                 }
523
524                 
525
526                 ////  Pass on to UNITS_STABILITY
527                 
528                 @Override
529                 public int getDefaultUnitIndex() {
530                         return UNITS_STABILITY.getDefaultUnitIndex();
531                 }
532
533                 @Override
534                 public void setDefaultUnit(int n) {
535                         UNITS_STABILITY.setDefaultUnit(n);
536                 }
537
538                 @Override
539                 public int getUnitCount() {
540                         return UNITS_STABILITY.getUnitCount();
541                 }
542
543
544                 ////  Unsupported methods
545                 
546                 @Override
547                 public void addUnit(int n, Unit u) {
548                         throw new UnsupportedOperationException("StabilityUnitGroup must not be modified");
549                 }
550
551                 @Override
552                 public void addUnit(Unit u) {
553                         throw new UnsupportedOperationException("StabilityUnitGroup must not be modified");
554                 }
555
556                 @Override
557                 public void removeUnit(int n) {
558                         throw new UnsupportedOperationException("StabilityUnitGroup must not be modified");
559                 }
560         }
561 }