X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=core%2Fsrc%2Fnet%2Fsf%2Fopenrocket%2Fpreset%2FComponentPreset.java;h=6e7bd7aaf4a4d60047609da7d6b56fca2f60318d;hb=3baf151be2d95eecbec6cf7aefe7c68edfc121d8;hp=c1d562856e726d6cefa85423601fa41bba80cebb;hpb=bad1051fc1ad12b01d1fbd1c679dcc883d8a14a5;p=debian%2Fopenrocket diff --git a/core/src/net/sf/openrocket/preset/ComponentPreset.java b/core/src/net/sf/openrocket/preset/ComponentPreset.java index c1d56285..6e7bd7aa 100644 --- a/core/src/net/sf/openrocket/preset/ComponentPreset.java +++ b/core/src/net/sf/openrocket/preset/ComponentPreset.java @@ -4,6 +4,7 @@ import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.security.MessageDigest; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; @@ -12,9 +13,7 @@ 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.rocketcomponent.NoseCone; import net.sf.openrocket.rocketcomponent.Transition.Shape; import net.sf.openrocket.unit.UnitGroup; import net.sf.openrocket.util.BugException; @@ -26,221 +25,200 @@ import net.sf.openrocket.util.TextUtil; *

* A preset component contains a component class type, manufacturer information, * part information, and a method that returns a prototype of the preset component. - * + * * @author Sampo Niskanen */ -// FIXME - Implement clone. public class ComponentPreset implements Comparable { - + private final TypedPropertyMap properties = new TypedPropertyMap(); - - private boolean favorite = false; + private String digest = ""; - + public enum Type { - BODY_TUBE( new TypedKey[] { + BODY_TUBE(new TypedKey[] { ComponentPreset.MANUFACTURER, ComponentPreset.PARTNO, - ComponentPreset.OUTER_DIAMETER, + ComponentPreset.DESCRIPTION, ComponentPreset.INNER_DIAMETER, - ComponentPreset.LENGTH} ), - - NOSE_CONE( new TypedKey[] { + ComponentPreset.OUTER_DIAMETER, + ComponentPreset.LENGTH }), + + NOSE_CONE(new TypedKey[] { + ComponentPreset.MANUFACTURER, + ComponentPreset.PARTNO, + ComponentPreset.DESCRIPTION, + ComponentPreset.SHAPE, + ComponentPreset.AFT_OUTER_DIAMETER, + ComponentPreset.AFT_SHOULDER_DIAMETER, + ComponentPreset.AFT_SHOULDER_LENGTH, + ComponentPreset.LENGTH }), + + TRANSITION(new TypedKey[] { ComponentPreset.MANUFACTURER, ComponentPreset.PARTNO, + ComponentPreset.DESCRIPTION, ComponentPreset.SHAPE, + ComponentPreset.FORE_OUTER_DIAMETER, + ComponentPreset.FORE_SHOULDER_DIAMETER, + ComponentPreset.FORE_SHOULDER_LENGTH, + ComponentPreset.AFT_OUTER_DIAMETER, + ComponentPreset.AFT_SHOULDER_DIAMETER, + ComponentPreset.AFT_SHOULDER_LENGTH, + ComponentPreset.LENGTH }), + + TUBE_COUPLER(new TypedKey[] { + ComponentPreset.MANUFACTURER, + ComponentPreset.PARTNO, + ComponentPreset.DESCRIPTION, ComponentPreset.OUTER_DIAMETER, - ComponentPreset.LENGTH} ) ; - - Type[] compatibleTypes; + ComponentPreset.INNER_DIAMETER, + ComponentPreset.LENGTH }), + + BULK_HEAD(new TypedKey[] { + ComponentPreset.MANUFACTURER, + ComponentPreset.PARTNO, + ComponentPreset.DESCRIPTION, + ComponentPreset.OUTER_DIAMETER, + ComponentPreset.LENGTH }), + + CENTERING_RING(new TypedKey[] { + ComponentPreset.MANUFACTURER, + ComponentPreset.PARTNO, + ComponentPreset.DESCRIPTION, + ComponentPreset.INNER_DIAMETER, + ComponentPreset.OUTER_DIAMETER, + ComponentPreset.LENGTH }), + + ENGINE_BLOCK(new TypedKey[] { + ComponentPreset.MANUFACTURER, + ComponentPreset.PARTNO, + ComponentPreset.DESCRIPTION, + ComponentPreset.INNER_DIAMETER, + ComponentPreset.OUTER_DIAMETER, + ComponentPreset.LENGTH }), + + LAUNCH_LUG(new TypedKey[] { + ComponentPreset.MANUFACTURER, + ComponentPreset.PARTNO, + ComponentPreset.DESCRIPTION, + ComponentPreset.INNER_DIAMETER, + ComponentPreset.OUTER_DIAMETER, + ComponentPreset.LENGTH }), + + STREAMER(new TypedKey[] { + ComponentPreset.MANUFACTURER, + ComponentPreset.PARTNO, + ComponentPreset.DESCRIPTION, + ComponentPreset.LENGTH, + ComponentPreset.WIDTH, + ComponentPreset.THICKNESS, + ComponentPreset.MATERIAL }), + + PARACHUTE(new TypedKey[] { + ComponentPreset.MANUFACTURER, + ComponentPreset.PARTNO, + ComponentPreset.DESCRIPTION, + ComponentPreset.DIAMETER, + ComponentPreset.SIDES, + ComponentPreset.LINE_COUNT, + ComponentPreset.LINE_LENGTH, + ComponentPreset.LINE_MATERIAL, + ComponentPreset.MATERIAL }); + TypedKey[] displayedColumns; - - Type( TypedKey[] displayedColumns) { - compatibleTypes = new Type[1]; - compatibleTypes[0] = this; - this.displayedColumns = displayedColumns; - } - - Type( Type[] t, TypedKey[] displayedColumns ) { - - compatibleTypes = new Type[t.length+1]; - compatibleTypes[0] = this; - for( int i=0; i[] displayedColumns) { this.displayedColumns = displayedColumns; } - - public Type[] getCompatibleTypes() { - return compatibleTypes; + + public List getCompatibleTypes() { + return compatibleTypeMap.get(Type.this); } - + public TypedKey[] getDisplayedColumns() { return displayedColumns; } - + + private static Map> compatibleTypeMap = new HashMap>(); + + static { + compatibleTypeMap.put(BODY_TUBE, Arrays.asList(BODY_TUBE, TUBE_COUPLER, LAUNCH_LUG)); + compatibleTypeMap.put(TUBE_COUPLER, Arrays.asList(BODY_TUBE, TUBE_COUPLER, LAUNCH_LUG)); + compatibleTypeMap.put(LAUNCH_LUG, Arrays.asList(BODY_TUBE, TUBE_COUPLER, LAUNCH_LUG)); + compatibleTypeMap.put(CENTERING_RING, Arrays.asList(CENTERING_RING, ENGINE_BLOCK)); + compatibleTypeMap.put(NOSE_CONE, Arrays.asList(NOSE_CONE, TRANSITION)); + } + } - + public final static TypedKey MANUFACTURER = new TypedKey("Manufacturer", Manufacturer.class); - public final static TypedKey PARTNO = new TypedKey("PartNo",String.class); + public final static TypedKey PARTNO = new TypedKey("PartNo", String.class); public final static TypedKey DESCRIPTION = new TypedKey("Description", String.class); - public final static TypedKey TYPE = new TypedKey("Type",Type.class); + public final static TypedKey TYPE = new TypedKey("Type", Type.class); public final static TypedKey LENGTH = new TypedKey("Length", Double.class, UnitGroup.UNITS_LENGTH); + public final static TypedKey WIDTH = new TypedKey("Width", Double.class, UnitGroup.UNITS_LENGTH); public final static TypedKey INNER_DIAMETER = new TypedKey("InnerDiameter", Double.class, UnitGroup.UNITS_LENGTH); public final static TypedKey OUTER_DIAMETER = new TypedKey("OuterDiameter", Double.class, UnitGroup.UNITS_LENGTH); - public final static TypedKey SHOULDER_LENGTH = new TypedKey("ShoulderLength", Double.class, UnitGroup.UNITS_LENGTH); - public final static TypedKey SHOULDER_DIAMETER = new TypedKey("ShoulderDiameter", Double.class, UnitGroup.UNITS_LENGTH); + public final static TypedKey FORE_SHOULDER_LENGTH = new TypedKey("ForeShoulderLength", Double.class, UnitGroup.UNITS_LENGTH); + public final static TypedKey FORE_SHOULDER_DIAMETER = new TypedKey("ForeShoulderDiameter", Double.class, UnitGroup.UNITS_LENGTH); + public final static TypedKey FORE_OUTER_DIAMETER = new TypedKey("ForeOuterDiameter", Double.class, UnitGroup.UNITS_LENGTH); + public final static TypedKey AFT_SHOULDER_LENGTH = new TypedKey("AftShoulderLength", Double.class, UnitGroup.UNITS_LENGTH); + public final static TypedKey AFT_SHOULDER_DIAMETER = new TypedKey("AftShoulderDiameter", Double.class, UnitGroup.UNITS_LENGTH); + public final static TypedKey AFT_OUTER_DIAMETER = new TypedKey("AftOuterDiameter", Double.class, UnitGroup.UNITS_LENGTH); public final static TypedKey SHAPE = new TypedKey("Shape", Shape.class); public final static TypedKey MATERIAL = new TypedKey("Material", Material.class); public final static TypedKey FINISH = new TypedKey("Finish", Finish.class); public final static TypedKey THICKNESS = new TypedKey("Thickness", Double.class, UnitGroup.UNITS_LENGTH); public final static TypedKey FILLED = new TypedKey("Filled", Boolean.class); public final static TypedKey MASS = new TypedKey("Mass", Double.class, UnitGroup.UNITS_MASS); - - public final static Map> keyMap = new HashMap>(); - static { - keyMap.put(MANUFACTURER.getName(), MANUFACTURER); - keyMap.put(PARTNO.getName(), PARTNO); - keyMap.put(TYPE.getName(), TYPE); - keyMap.put(DESCRIPTION.getName(), DESCRIPTION); - keyMap.put(LENGTH.getName(), LENGTH); - keyMap.put(INNER_DIAMETER.getName(), INNER_DIAMETER); - keyMap.put(OUTER_DIAMETER.getName(), OUTER_DIAMETER); - keyMap.put(SHOULDER_LENGTH.getName(), SHOULDER_LENGTH); - keyMap.put(SHOULDER_DIAMETER.getName(), SHOULDER_DIAMETER); - keyMap.put(SHAPE.getName(), SHAPE); - keyMap.put(MATERIAL.getName(), MATERIAL); - keyMap.put(FINISH.getName(), FINISH); - keyMap.put(THICKNESS.getName(), THICKNESS); - keyMap.put(FILLED.getName(), FILLED); - keyMap.put(MASS.getName(), MASS); - } - - 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: { - if ( !props.containsKey(LENGTH) ) { - throw new InvalidComponentPresetException( "No Length specified for nose cone preset " + props.toString()); - } - if ( !props.containsKey(SHAPE) ) { - throw new InvalidComponentPresetException( "No Shape specified for nose cone preset " + props.toString()); - } - if ( !props.containsKey(OUTER_DIAMETER) ) { - throw new InvalidComponentPresetException( "No Outer Diameter specified for nose cone preset " + props.toString()); - } - - if ( props.containsKey(MASS) ) { - // compute a density for this component - double mass = props.get(MASS); - NoseCone nc = new NoseCone(); - nc.loadPreset(preset); - double density = mass / nc.getComponentVolume(); - - String materialName = "NoseConeCustom"; - if ( props.containsKey(MATERIAL) ) { - materialName = props.get(MATERIAL).getName(); - } - - Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false); - preset.properties.put(MATERIAL, m); - - } - break; - } - } - - preset.computeDigest(); - - return preset; - - } - - // Private constructor to encourage use of factory. - private ComponentPreset() { + public final static TypedKey DIAMETER = new TypedKey("Diameter", Double.class, UnitGroup.UNITS_LENGTH); + public final static TypedKey SIDES = new TypedKey("Sides", Integer.class); + public final static TypedKey LINE_COUNT = new TypedKey("LineCount", Integer.class); + public final static TypedKey LINE_LENGTH = new TypedKey("LineLength", Double.class, UnitGroup.UNITS_LENGTH); + public final static TypedKey LINE_MATERIAL = new TypedKey("LineMaterial", Material.class); + public final static TypedKey IMAGE = new TypedKey("Image", byte[].class); + + public final static List> ORDERED_KEY_LIST = Collections.unmodifiableList(Arrays.> asList( + MANUFACTURER, + PARTNO, + DESCRIPTION, + OUTER_DIAMETER, + FORE_OUTER_DIAMETER, + AFT_OUTER_DIAMETER, + INNER_DIAMETER, + LENGTH, + WIDTH, + AFT_SHOULDER_DIAMETER, + AFT_SHOULDER_LENGTH, + FORE_SHOULDER_DIAMETER, + FORE_SHOULDER_LENGTH, + SHAPE, + THICKNESS, + FILLED, + DIAMETER, + SIDES, + LINE_COUNT, + LINE_LENGTH, + LINE_MATERIAL, + MASS, + FINISH, + MATERIAL + )); + + + // package scope constructor to encourage use of factory. + ComponentPreset() { } - + /** * Convenience method to retrieve the Type of this ComponentPreset. - * + * * @return */ public Type getType() { return properties.get(TYPE); } - + /** * Convenience method to retrieve the Manufacturer of this ComponentPreset. * @return @@ -248,7 +226,7 @@ public class ComponentPreset implements Comparable { public Manufacturer getManufacturer() { return properties.get(MANUFACTURER); } - + /** * Convenience method to retrieve the PartNo of this ComponentPreset. * @return @@ -256,106 +234,144 @@ public class ComponentPreset implements Comparable { public String getPartNo() { return properties.get(PARTNO); } - + public String getDigest() { return digest; } - + public boolean has(Object key) { return properties.containsKey(key); } - + + /** + * Package scope so the ComponentPresetFactory can call it. + * @param other + */ + void putAll(TypedPropertyMap other) { + if (other == null) { + return; + } + properties.putAll(other); + } + + /** + * Package scope so the ComponentPresetFactory can call it. + * @param key + * @param value + */ + void put(TypedKey key, T value) { + properties.put(key, value); + } + public T get(TypedKey key) { T value = properties.get(key); if (value == null) { throw new BugException("Preset did not contain key " + key + " " + properties.toString()); } - return (T) value; - } - - public boolean isFavorite() { - return favorite; - } - - public void setFavorite(boolean favorite) { - this.favorite = favorite; + return value; } - + @Override public int compareTo(ComponentPreset p2) { int manuCompare = this.getManufacturer().getSimpleName().compareTo(p2.getManufacturer().getSimpleName()); - if ( manuCompare != 0 ) + if (manuCompare != 0) return manuCompare; - + int partNoCompare = this.getPartNo().compareTo(p2.getPartNo()); return partNoCompare; } - + @Override public String toString() { - return get(MANUFACTURER).toString() + " " + get(PARTNO); + return get(PARTNO); } - + public String preferenceKey() { return get(MANUFACTURER).toString() + "|" + get(PARTNO); } - - private void computeDigest() { - + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + ComponentPreset that = (ComponentPreset) o; + + if (digest != null ? !digest.equals(that.digest) : that.digest != null) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return digest != null ? digest.hashCode() : 0; + } + + /** + * Package scope so the factory can call it. + */ + void computeDigest() { + try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); DataOutputStream os = new DataOutputStream(bos); - - List> keys = new ArrayList>( properties.keySet()); - + + List> keys = new ArrayList>(properties.keySet()); + Collections.sort(keys, new Comparator>() { @Override - public int compare( TypedKey a, TypedKey b ) { + public int compare(TypedKey a, TypedKey b) { return a.getName().compareTo(b.getName()); } }); - - for ( TypedKey key : keys ) { - + + for (TypedKey key : keys) { + Object value = properties.get(key); - + os.writeBytes(key.getName()); - - if ( key.getType() == Double.class ) { + + if (key.getType() == Double.class) { Double d = (Double) value; os.writeDouble(d); - } else if (key.getType() == String.class ) { + } else if (key.getType() == String.class) { String s = (String) value; os.writeBytes(s); - } else if (key.getType() == Manufacturer.class ) { - String s = ((Manufacturer)value).getSimpleName(); + } else if (key.getType() == Manufacturer.class) { + String s = ((Manufacturer) value).getSimpleName(); os.writeBytes(s); - } else if ( key.getType() == Finish.class ) { - String s = ((Finish)value).name(); + } else if (key.getType() == Finish.class) { + String s = ((Finish) value).name(); os.writeBytes(s); - } else if ( key.getType() == Type.class ) { - String s = ((Type)value).name(); + } else if (key.getType() == Type.class) { + String s = ((Type) value).name(); os.writeBytes(s); - } else if ( key.getType() == Boolean.class ) { + } else if (key.getType() == Boolean.class) { Boolean b = (Boolean) value; os.writeBoolean(b); - } else if ( key.getType() == Material.class ) { - double d = ((Material)value).getDensity(); + } else if (key.getType() == Material.class) { + double d = ((Material) value).getDensity(); os.writeDouble(d); - } else if ( key.getType() == Shape.class ) { - // FIXME - this is ugly to use the ordinal but what else? - int i = ((Shape)value).ordinal(); + } else if (key.getType() == Shape.class) { + // this is ugly to use the ordinal but what else? + int i = ((Shape) value).ordinal(); os.writeInt(i); } - + } - + MessageDigest md5 = MessageDigest.getInstance("MD5"); - digest = TextUtil.hexString(md5.digest( bos.toByteArray() )); - } - catch ( Exception e ) { + digest = TextUtil.hexString(md5.digest(bos.toByteArray())); + } catch (Exception e) { + e.printStackTrace(); throw new BugException(e); } } - + }