X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=core%2Fsrc%2Fnet%2Fsf%2Fopenrocket%2Fpreset%2FComponentPreset.java;fp=core%2Fsrc%2Fnet%2Fsf%2Fopenrocket%2Fpreset%2FComponentPreset.java;h=6e7bd7aaf4a4d60047609da7d6b56fca2f60318d;hb=9349577cdfdff682b2aabd6daa24fdc3a7449b58;hp=87343e9351b9734992abe645c9776e969d592763;hpb=30ba0a882f0c061176ba14dbf86d3d6fad096c02;p=debian%2Fopenrocket
diff --git a/core/src/net/sf/openrocket/preset/ComponentPreset.java b/core/src/net/sf/openrocket/preset/ComponentPreset.java
index 87343e93..6e7bd7aa 100644
--- a/core/src/net/sf/openrocket/preset/ComponentPreset.java
+++ b/core/src/net/sf/openrocket/preset/ComponentPreset.java
@@ -1,73 +1,377 @@
package net.sf.openrocket.preset;
+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;
+import java.util.List;
+import java.util.Map;
+
+import net.sf.openrocket.material.Material;
import net.sf.openrocket.motor.Manufacturer;
-import net.sf.openrocket.rocketcomponent.RocketComponent;
+import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish;
+import net.sf.openrocket.rocketcomponent.Transition.Shape;
+import net.sf.openrocket.unit.UnitGroup;
+import net.sf.openrocket.util.BugException;
+import net.sf.openrocket.util.TextUtil;
+
/**
* A model for a preset component.
*
* 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
*/
-public abstract class ComponentPreset {
+public class ComponentPreset implements Comparable {
- private final Manufacturer manufacturer;
- private final String partNo;
- private final String partDescription;
- private final RocketComponent prototype;
+ private final TypedPropertyMap properties = new TypedPropertyMap();
+ private String digest = "";
- public ComponentPreset(Manufacturer manufacturer, String partNo, String partDescription,
- RocketComponent prototype) {
- this.manufacturer = manufacturer;
- this.partNo = partNo;
- this.partDescription = partDescription;
- this.prototype = prototype.copy();
+ public enum Type {
+ BODY_TUBE(new TypedKey>[] {
+ ComponentPreset.MANUFACTURER,
+ ComponentPreset.PARTNO,
+ ComponentPreset.DESCRIPTION,
+ ComponentPreset.INNER_DIAMETER,
+ 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.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 }),
- if (prototype.getParent() != null) {
- throw new IllegalArgumentException("Prototype component cannot have a parent");
+ 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) {
+ this.displayedColumns = displayedColumns;
}
- if (prototype.getChildCount() > 0) {
- throw new IllegalArgumentException("Prototype component cannot have children");
+
+ 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 DESCRIPTION = new TypedKey("Description", String.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 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 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() {
+ }
/**
- * Return the component class that this preset defines.
+ * Convenience method to retrieve the Type of this ComponentPreset.
+ *
+ * @return
*/
- public Class extends RocketComponent> getComponentClass() {
- return prototype.getClass();
+ public Type getType() {
+ return properties.get(TYPE);
}
/**
- * Return the manufacturer of this preset component.
+ * Convenience method to retrieve the Manufacturer of this ComponentPreset.
+ * @return
*/
public Manufacturer getManufacturer() {
- return manufacturer;
+ return properties.get(MANUFACTURER);
}
/**
- * Return the part number. This is the part identifier (e.g. "BT-50").
+ * Convenience method to retrieve the PartNo of this ComponentPreset.
+ * @return
*/
public String getPartNo() {
- return partNo;
+ return properties.get(PARTNO);
+ }
+
+ public String getDigest() {
+ return digest;
+ }
+
+ public boolean has(Object key) {
+ return properties.containsKey(key);
}
/**
- * Return the part description. This is a longer description of the component.
+ * Package scope so the ComponentPresetFactory can call it.
+ * @param other
*/
- public String getPartDescription() {
- return partDescription;
+ void putAll(TypedPropertyMap other) {
+ if (other == null) {
+ return;
+ }
+ properties.putAll(other);
}
/**
- * Return a prototype component. This component may be modified freely.
+ * Package scope so the ComponentPresetFactory can call it.
+ * @param key
+ * @param value
*/
- public RocketComponent getPrototype() {
- return prototype.copy();
+ 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 value;
+ }
+
+ @Override
+ public int compareTo(ComponentPreset p2) {
+ int manuCompare = this.getManufacturer().getSimpleName().compareTo(p2.getManufacturer().getSimpleName());
+ if (manuCompare != 0)
+ return manuCompare;
+
+ int partNoCompare = this.getPartNo().compareTo(p2.getPartNo());
+ return partNoCompare;
+ }
+
+ @Override
+ public String toString() {
+ return get(PARTNO);
+ }
+
+ public String preferenceKey() {
+ return get(MANUFACTURER).toString() + "|" + get(PARTNO);
+ }
+
+ @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());
+
+ Collections.sort(keys, new Comparator>() {
+ @Override
+ public int compare(TypedKey> a, TypedKey> b) {
+ return a.getName().compareTo(b.getName());
+ }
+ });
+
+ for (TypedKey> key : keys) {
+
+ Object value = properties.get(key);
+
+ os.writeBytes(key.getName());
+
+ if (key.getType() == Double.class) {
+ Double d = (Double) value;
+ os.writeDouble(d);
+ } else if (key.getType() == String.class) {
+ String s = (String) value;
+ os.writeBytes(s);
+ } 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();
+ os.writeBytes(s);
+ } else if (key.getType() == Type.class) {
+ String s = ((Type) value).name();
+ os.writeBytes(s);
+ } else if (key.getType() == Boolean.class) {
+ Boolean b = (Boolean) value;
+ os.writeBoolean(b);
+ } else if (key.getType() == Material.class) {
+ double d = ((Material) value).getDensity();
+ os.writeDouble(d);
+ } 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) {
+ e.printStackTrace();
+ throw new BugException(e);
+ }
}
}