1 package net.sf.openrocket.preset;
3 import java.util.HashMap;
6 import net.sf.openrocket.material.Material;
7 import net.sf.openrocket.motor.Manufacturer;
8 import net.sf.openrocket.rocketcomponent.BodyTube;
9 import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish;
10 import net.sf.openrocket.unit.UnitGroup;
11 import net.sf.openrocket.util.BugException;
15 * A model for a preset component.
17 * A preset component contains a component class type, manufacturer information,
18 * part information, and a method that returns a prototype of the preset component.
20 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
22 public class ComponentPreset {
24 private final TypedPropertyMap properties = new TypedPropertyMap();
27 // TODO - Implement clone.
34 public final static TypedKey<Manufacturer> MANUFACTURER = new TypedKey<Manufacturer>("Manufacturer", Manufacturer.class);
35 public final static TypedKey<String> PARTNO = new TypedKey<String>("PartNo",String.class);
36 public final static TypedKey<Type> TYPE = new TypedKey<Type>("Type",Type.class);
37 public final static TypedKey<Double> LENGTH = new TypedKey<Double>("Length", Double.class, UnitGroup.UNITS_LENGTH);
38 public final static TypedKey<Double> INNER_DIAMETER = new TypedKey<Double>("InnerDiameter", Double.class, UnitGroup.UNITS_LENGTH);
39 public final static TypedKey<Double> OUTER_DIAMETER = new TypedKey<Double>("OuterDiameter", Double.class, UnitGroup.UNITS_LENGTH);
40 public final static TypedKey<Material> MATERIAL = new TypedKey<Material>("Material", Material.class);
41 public final static TypedKey<Finish> FINISH = new TypedKey<Finish>("Finish", Finish.class);
42 public final static TypedKey<Double> THICKNESS = new TypedKey<Double>("Thickness", Double.class, UnitGroup.UNITS_LENGTH);
43 public final static TypedKey<Boolean> FILLED = new TypedKey<Boolean>("Filled", Boolean.class);
44 public final static TypedKey<Double> MASS = new TypedKey<Double>("Mass", Double.class, UnitGroup.UNITS_MASS);
46 public final static Map<String, TypedKey<?>> keyMap = new HashMap<String, TypedKey<?>>();
48 keyMap.put(MANUFACTURER.getName(), MANUFACTURER);
49 keyMap.put(PARTNO.getName(), PARTNO);
50 keyMap.put(TYPE.getName(), TYPE);
51 keyMap.put(LENGTH.getName(), LENGTH);
52 keyMap.put(INNER_DIAMETER.getName(), INNER_DIAMETER);
53 keyMap.put(OUTER_DIAMETER.getName(), OUTER_DIAMETER);
54 keyMap.put(MATERIAL.getName(), MATERIAL);
55 keyMap.put(FINISH.getName(), FINISH);
56 keyMap.put(THICKNESS.getName(), THICKNESS);
57 keyMap.put(FILLED.getName(), FILLED);
58 keyMap.put(MASS.getName(), MASS);
61 public static ComponentPreset create( TypedPropertyMap props ) throws InvalidComponentPresetException {
63 ComponentPreset preset = new ComponentPreset();
64 // First do validation.
65 if ( !props.containsKey(TYPE)) {
66 throw new InvalidComponentPresetException("No Type specified " + props.toString() );
69 if (!props.containsKey(MANUFACTURER)) {
70 throw new InvalidComponentPresetException("No Manufacturer specified " + props.toString() );
73 if (!props.containsKey(PARTNO)) {
74 throw new InvalidComponentPresetException("No PartNo specified " + props.toString() );
77 preset.properties.putAll(props);
79 // Should check for various bits of each of the types.
80 Type t = props.get(TYPE);
84 if ( !props.containsKey(LENGTH) ) {
85 throw new InvalidComponentPresetException( "No Length specified for body tube preset " + props.toString());
88 BodyTube bt = new BodyTube();
90 bt.setLength(props.get(LENGTH));
92 // Need to verify contains 2 of OD, thickness, ID. Compute the third.
93 boolean hasOd = props.containsKey(OUTER_DIAMETER);
94 boolean hasId = props.containsKey(INNER_DIAMETER);
95 boolean hasThickness = props.containsKey(THICKNESS);
98 double outerRadius = props.get(OUTER_DIAMETER)/2.0;
100 bt.setOuterRadius( outerRadius );
102 thickness = outerRadius - props.get(INNER_DIAMETER)/2.0;
103 } else if ( hasThickness ) {
104 thickness = props.get(THICKNESS);
106 throw new InvalidComponentPresetException("Body tube preset underspecified " + props.toString());
108 bt.setThickness( thickness );
110 if ( ! hasId && ! hasThickness ) {
111 throw new InvalidComponentPresetException("Body tube preset underspecified " + props.toString());
113 double innerRadius = props.get(INNER_DIAMETER)/2.0;
114 double thickness = props.get(THICKNESS);
115 bt.setOuterRadius(innerRadius + thickness);
116 bt.setThickness(thickness);
119 preset.properties.put(OUTER_DIAMETER, bt.getOuterRadius() *2.0);
120 preset.properties.put(INNER_DIAMETER, bt.getInnerRadius() *2.0);
121 preset.properties.put(THICKNESS, bt.getThickness());
123 // Need to translate Mass to Density.
124 if ( props.containsKey(MASS) ) {
125 String materialName = "TubeCustom";
126 if ( props.containsKey(MATERIAL) ) {
127 materialName = props.get(MATERIAL).getName();
129 Material m = Material.newMaterial(Material.Type.BULK, materialName, props.get(MASS)/bt.getComponentVolume(), false);
130 preset.properties.put(MATERIAL, m);
144 // Private constructor to encourage use of factory.
145 private ComponentPreset() {
149 public boolean has(Object key) {
150 return properties.containsKey(key);
153 public <T> T get(TypedKey<T> key) {
154 T value = properties.get(key);
156 throw new BugException("Preset did not contain key " + key + " " + properties.toString());
162 public String toString() {
163 return get(MANUFACTURER).toString() + " " + get(PARTNO);