Revamp construction of ComponentPresets. Validation and data munging done in the ComponentPreset.create() factory method.
This commit is contained in:
parent
2c793422b5
commit
addca0b4b8
@ -7,6 +7,9 @@ import java.util.List;
|
||||
|
||||
import net.sf.openrocket.file.preset.PresetCSVReader;
|
||||
import net.sf.openrocket.preset.ComponentPreset;
|
||||
import net.sf.openrocket.preset.InvalidComponentPresetException;
|
||||
import net.sf.openrocket.preset.TypedPropertyMap;
|
||||
import net.sf.openrocket.util.BugException;
|
||||
|
||||
public class ComponentPresetDao {
|
||||
|
||||
@ -20,9 +23,14 @@ public class ComponentPresetDao {
|
||||
InputStream is = ComponentPresetDao.class.getResourceAsStream("/datafiles/bodytubepresets.csv");
|
||||
|
||||
PresetCSVReader parser = new PresetCSVReader(is);
|
||||
List<ComponentPreset> list = parser.parse();
|
||||
for( ComponentPreset preset : list ) {
|
||||
templates.add(preset);
|
||||
List<TypedPropertyMap> list = parser.parse();
|
||||
for( TypedPropertyMap o : list ) {
|
||||
try {
|
||||
ComponentPreset preset = ComponentPreset.create(o);
|
||||
this.insert(preset);
|
||||
} catch ( InvalidComponentPresetException ex ) {
|
||||
throw new BugException( ex );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,4 +38,8 @@ public class ComponentPresetDao {
|
||||
return templates;
|
||||
}
|
||||
|
||||
public void insert( ComponentPreset preset ) {
|
||||
templates.add(preset);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,46 +1,15 @@
|
||||
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 class ColumnDefinition<T> {
|
||||
TypedKey<T> key;
|
||||
public ColumnDefinition( TypedKey<T> key ) {
|
||||
this.key = key;
|
||||
}
|
||||
public static class PartNumber implements ColumnDefinition {
|
||||
@Override
|
||||
public void setProperty( ComponentPreset preset, String value ) {
|
||||
preset.setPartNo(value);
|
||||
}
|
||||
public void setProperty( TypedPropertyMap preset, String value ) {
|
||||
T o = (T) key.parseFromString(value);
|
||||
preset.put(key, o);
|
||||
}
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -8,63 +8,63 @@ import java.util.List;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ import java.util.HashMap;
|
||||
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;
|
||||
|
||||
@ -18,17 +20,19 @@ 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);
|
||||
@ -40,6 +44,9 @@ public class ComponentPreset {
|
||||
|
||||
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);
|
||||
@ -50,69 +57,110 @@ public class ComponentPreset {
|
||||
keyMap.put(MASS.getName(), MASS);
|
||||
}
|
||||
|
||||
private String manufacturer;
|
||||
private String partNo;
|
||||
private String partDescription;
|
||||
private Type type;
|
||||
|
||||
|
||||
public String getManufacturer() {
|
||||
return manufacturer;
|
||||
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 setManufacturer(String manufacturer) {
|
||||
this.manufacturer = manufacturer;
|
||||
|
||||
// Private constructor to encourage use of factory.
|
||||
private ComponentPreset() {
|
||||
|
||||
}
|
||||
|
||||
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 void setType(Type type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,25 @@
|
||||
package net.sf.openrocket.preset;
|
||||
|
||||
public class InvalidComponentPresetException extends Exception {
|
||||
|
||||
public InvalidComponentPresetException() {
|
||||
super();
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public InvalidComponentPresetException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public InvalidComponentPresetException(String message) {
|
||||
super(message);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public InvalidComponentPresetException(Throwable cause) {
|
||||
super(cause);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user