package net.sf.openrocket.file.preset;
-import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.preset.TypedKey;
+import net.sf.openrocket.preset.TypedPropertyMap;
-public interface ColumnDefinition {
-
- public void setProperty( ComponentPreset preset, String value );
-
- public static class Manufactuer implements ColumnDefinition {
- @Override
- public void setProperty( ComponentPreset preset, String value ) {
- preset.setManufacturer(value);
- }
- }
- public static class PartNumber implements ColumnDefinition {
- @Override
- public void setProperty( ComponentPreset preset, String value ) {
- preset.setPartNo(value);
- }
- }
- public static class Type implements ColumnDefinition {
- @Override
- public void setProperty( ComponentPreset preset, String value ) {
- ComponentPreset.Type t = ComponentPreset.Type.valueOf(value);
- if ( t == null ) {
- throw new RuntimeException("Invalid ComponentPreset Type: " + value);
- }
- preset.setType(t);
- }
+public class ColumnDefinition<T> {
+ TypedKey<T> key;
+ public ColumnDefinition( TypedKey<T> key ) {
+ this.key = key;
}
- public static class Parameter implements ColumnDefinition {
- TypedKey key;
- public Parameter( TypedKey key ) {
- this.key = key;
- }
- @Override
- public void setProperty( ComponentPreset preset, String value ) {
- Object o = key.parseFromString(value);
- preset.put(key, o);
- }
+ public void setProperty( TypedPropertyMap preset, String value ) {
+ T o = (T) key.parseFromString(value);
+ preset.put(key, o);
}
-
-
-
}
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.preset.TypedKey;
+import net.sf.openrocket.preset.TypedPropertyMap;
import au.com.bytecode.opencsv.CSVReader;
public class PresetCSVReader {
-
+
private InputStream is;
- private ColumnDefinition[] columns;
-
+ private ColumnDefinition<?>[] columns;
+
public PresetCSVReader(InputStream is) {
this.is = is;
}
-
- public List<ComponentPreset> parse() throws IOException {
-
- List<ComponentPreset> templates = new ArrayList<ComponentPreset>();
-
+
+ public List<TypedPropertyMap> parse() throws IOException {
+
+ List<TypedPropertyMap> templates = new ArrayList<TypedPropertyMap>();
+
InputStreamReader r = new InputStreamReader(is);
-
+
// Create the CSV reader. Use comma separator and double-quote escaping.
CSVReader reader = new CSVReader(r, ',', '"');
-
+
String[] headers = reader.readNext();
if (headers == null || headers.length == 0) {
return templates;
}
-
+
columns = new ColumnDefinition[headers.length];
for (int i = 0; i < headers.length; i++) {
String h = headers[i];
- if ("Manufacturer".equals(h)) {
- columns[i] = new ColumnDefinition.Manufactuer();
- } else if ("PartNo".equals(h)) {
- columns[i] = new ColumnDefinition.PartNumber();
- } else if ("Type".equals(h)) {
- columns[i] = new ColumnDefinition.Type();
- } else {
- TypedKey key = ComponentPreset.keyMap.get(h);
- if (key == null) {
- throw new RuntimeException("Invalid parameter key " + h + " in file");
- }
- columns[i] = new ColumnDefinition.Parameter(key);
+ TypedKey key = ComponentPreset.keyMap.get(h);
+ if (key == null) {
+ throw new RuntimeException("Invalid parameter key " + h + " in file");
}
+ columns[i] = new ColumnDefinition(key);
}
-
+
String[] line;
while ((line = reader.readNext()) != null) {
- ComponentPreset preset = new ComponentPreset();
+ TypedPropertyMap preset = new TypedPropertyMap();
for (int i = 0; i < headers.length; i++) {
if (i > line.length) {
break;
}
String value = line[i];
+ if ( value == null ) {
+ continue;
+ }
+ value = value.trim();
+ if ( value.length() == 0 ) {
+ continue;
+ }
columns[i].setProperty(preset, value);
}
templates.add(preset);
}
-
+
return templates;
}
-
+
}
import java.util.Map;
import net.sf.openrocket.material.Material;
+import net.sf.openrocket.motor.Manufacturer;
+import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish;
import net.sf.openrocket.util.BugException;
*/
public class ComponentPreset {
- private final Map<TypedKey<?>, Object> properties = new HashMap<TypedKey<?>, Object>();
+ private final TypedPropertyMap properties = new TypedPropertyMap();
// TODO - Implement clone.
- // Implement "freezing" so the object cannot be modified.
public enum Type {
BODY_TUBE,
NOSE_CONE
}
+ public final static TypedKey<Manufacturer> MANUFACTURER = new TypedKey<Manufacturer>("Manufacturer", Manufacturer.class);
+ public final static TypedKey<String> PARTNO = new TypedKey<String>("PartNo",String.class);
+ public final static TypedKey<Type> TYPE = new TypedKey<Type>("Type",Type.class);
public final static TypedKey<Double> LENGTH = new TypedKey<Double>("Length", Double.class);
public final static TypedKey<Double> INNER_DIAMETER = new TypedKey<Double>("InnerDiameter", Double.class);
public final static TypedKey<Double> OUTER_DIAMETER = new TypedKey<Double>("OuterDiameter", Double.class);
public final static Map<String, TypedKey<?>> keyMap = new HashMap<String, TypedKey<?>>();
static {
+ keyMap.put(MANUFACTURER.getName(), MANUFACTURER);
+ keyMap.put(PARTNO.getName(), PARTNO);
+ keyMap.put(TYPE.getName(), TYPE);
keyMap.put(LENGTH.getName(), LENGTH);
keyMap.put(INNER_DIAMETER.getName(), INNER_DIAMETER);
keyMap.put(OUTER_DIAMETER.getName(), OUTER_DIAMETER);
keyMap.put(MASS.getName(), MASS);
}
- private String manufacturer;
- private String partNo;
- private String partDescription;
- private Type type;
-
-
- public String getManufacturer() {
- return manufacturer;
- }
-
- public void setManufacturer(String manufacturer) {
- this.manufacturer = manufacturer;
- }
-
- public String getPartNo() {
- return partNo;
- }
-
- public void setPartNo(String partNo) {
- this.partNo = partNo;
- }
-
- public String getPartDescription() {
- return partDescription;
- }
-
- public void setPartDescription(String partDescription) {
- this.partDescription = partDescription;
- }
-
- public Type getType() {
- return type;
+ public static ComponentPreset create( TypedPropertyMap props ) throws InvalidComponentPresetException {
+
+ ComponentPreset preset = new ComponentPreset();
+ // First do validation.
+ if ( !props.containsKey(TYPE)) {
+ throw new InvalidComponentPresetException("No Type specified " + props.toString() );
+ }
+
+ if (!props.containsKey(MANUFACTURER)) {
+ throw new InvalidComponentPresetException("No Manufacturer specified " + props.toString() );
+ }
+
+ if (!props.containsKey(PARTNO)) {
+ throw new InvalidComponentPresetException("No PartNo specified " + props.toString() );
+ }
+
+ preset.properties.putAll(props);
+
+ // Should check for various bits of each of the types.
+ Type t = props.get(TYPE);
+ switch ( t ) {
+ case BODY_TUBE: {
+
+ if ( !props.containsKey(LENGTH) ) {
+ throw new InvalidComponentPresetException( "No Length specified for body tube preset " + props.toString());
+ }
+
+ BodyTube bt = new BodyTube();
+
+ bt.setLength(props.get(LENGTH));
+
+ // Need to verify contains 2 of OD, thickness, ID. Compute the third.
+ boolean hasOd = props.containsKey(OUTER_DIAMETER);
+ boolean hasId = props.containsKey(INNER_DIAMETER);
+ boolean hasThickness = props.containsKey(THICKNESS);
+
+ if ( hasOd ) {
+ double outerRadius = props.get(OUTER_DIAMETER)/2.0;
+ double thickness = 0;
+ bt.setOuterRadius( outerRadius );
+ if ( hasId ) {
+ thickness = outerRadius - props.get(INNER_DIAMETER)/2.0;
+ } else if ( hasThickness ) {
+ thickness = props.get(THICKNESS);
+ } else {
+ throw new InvalidComponentPresetException("Body tube preset underspecified " + props.toString());
+ }
+ bt.setThickness( thickness );
+ } else {
+ if ( ! hasId && ! hasThickness ) {
+ throw new InvalidComponentPresetException("Body tube preset underspecified " + props.toString());
+ }
+ double innerRadius = props.get(INNER_DIAMETER)/2.0;
+ double thickness = props.get(THICKNESS);
+ bt.setOuterRadius(innerRadius + thickness);
+ bt.setThickness(thickness);
+ }
+
+ preset.properties.put(OUTER_DIAMETER, bt.getOuterRadius() *2.0);
+ preset.properties.put(INNER_DIAMETER, bt.getInnerRadius() *2.0);
+ preset.properties.put(THICKNESS, bt.getThickness());
+
+ // Need to translate Mass to Density.
+ if ( props.containsKey(MASS) ) {
+ String materialName = "TubeCustom";
+ if ( props.containsKey(MATERIAL) ) {
+ materialName = props.get(MATERIAL).getName();
+ }
+ Material m = Material.newMaterial(Material.Type.BULK, materialName, props.get(MASS)/bt.getComponentVolume(), false);
+ preset.properties.put(MATERIAL, m);
+ }
+
+ break;
+ }
+ case NOSE_CONE: {
+ break;
+ }
+ }
+
+ return preset;
+
}
-
- public void setType(Type type) {
- this.type = type;
+
+ // Private constructor to encourage use of factory.
+ private ComponentPreset() {
+
}
-
-
public boolean has(Object key) {
return properties.containsKey(key);
}
- @SuppressWarnings("unchecked")
public <T> T get(TypedKey<T> key) {
- Object value = properties.get(key);
+ T value = properties.get(key);
if (value == null) {
- throw new BugException("Preset of type " + type + " did not contain key " + key + " mfg=" + manufacturer + " partNo=" + partNo);
+ throw new BugException("Preset did not contain key " + key + " " + properties.toString());
}
return (T) value;
}
- @SuppressWarnings("unchecked")
- public <T> T put(TypedKey<T> key, T value) {
- return (T) properties.put(key, value);
- }
-
-
-
@Override
public String toString() {
- return partNo;
+ return get(MANUFACTURER).toString() + " " + get(PARTNO);
}
+
}