package net.sf.openrocket.preset;
-import net.sf.openrocket.material.Material;
-import net.sf.openrocket.motor.Manufacturer;
-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;
-
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.security.MessageDigest;
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.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.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
-// FIXME - Implement clone.
public class ComponentPreset implements Comparable<ComponentPreset> {
-
+
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.DESCRIPTION,
ComponentPreset.INNER_DIAMETER,
ComponentPreset.OUTER_DIAMETER,
- ComponentPreset.LENGTH} ),
-
- NOSE_CONE( new TypedKey<?>[] {
+ 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.AFT_SHOULDER_LENGTH,
+ ComponentPreset.LENGTH }),
+
+ TRANSITION(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
ComponentPreset.DESCRIPTION,
ComponentPreset.AFT_OUTER_DIAMETER,
ComponentPreset.AFT_SHOULDER_DIAMETER,
ComponentPreset.AFT_SHOULDER_LENGTH,
- ComponentPreset.LENGTH} ),
-
- TUBE_COUPLER( new TypedKey<?>[] {
+ ComponentPreset.LENGTH }),
+
+ TUBE_COUPLER(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
- ComponentPreset.DESCRIPTION,
+ ComponentPreset.DESCRIPTION,
ComponentPreset.OUTER_DIAMETER,
ComponentPreset.INNER_DIAMETER,
- ComponentPreset.LENGTH} ),
-
- BULK_HEAD( new TypedKey<?>[] {
+ ComponentPreset.LENGTH }),
+
+ BULK_HEAD(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
ComponentPreset.DESCRIPTION,
ComponentPreset.OUTER_DIAMETER,
- ComponentPreset.LENGTH} ),
-
- CENTERING_RING( new TypedKey<?>[] {
+ 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.LENGTH }),
+
+ ENGINE_BLOCK(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
ComponentPreset.DESCRIPTION,
ComponentPreset.INNER_DIAMETER,
ComponentPreset.OUTER_DIAMETER,
- ComponentPreset.LENGTH} ),
-
- LAUNCH_LUG( new TypedKey<?>[] {
+ ComponentPreset.LENGTH }),
+
+ LAUNCH_LUG(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
ComponentPreset.DESCRIPTION,
ComponentPreset.INNER_DIAMETER,
ComponentPreset.OUTER_DIAMETER,
- ComponentPreset.LENGTH} ),
-
- STREAMER( new TypedKey<?>[] {
+ ComponentPreset.LENGTH }),
+
+ STREAMER(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
- ComponentPreset.DESCRIPTION,
+ ComponentPreset.DESCRIPTION,
ComponentPreset.LENGTH,
ComponentPreset.WIDTH,
ComponentPreset.THICKNESS,
- ComponentPreset.MATERIAL} ),
-
- PARACHUTE( new TypedKey<?>[] {
+ ComponentPreset.MATERIAL }),
+
+ PARACHUTE(new TypedKey<?>[] {
ComponentPreset.MANUFACTURER,
ComponentPreset.PARTNO,
- ComponentPreset.DESCRIPTION,
+ ComponentPreset.DESCRIPTION,
ComponentPreset.DIAMETER,
ComponentPreset.SIDES,
ComponentPreset.LINE_COUNT,
ComponentPreset.LINE_LENGTH,
ComponentPreset.LINE_MATERIAL,
- ComponentPreset.MATERIAL} );
-
+ ComponentPreset.MATERIAL });
+
TypedKey<?>[] displayedColumns;
-
- Type( TypedKey<?>[] displayedColumns) {
+
+ Type(TypedKey<?>[] displayedColumns) {
this.displayedColumns = displayedColumns;
}
-
+
public List<Type> getCompatibleTypes() {
return compatibleTypeMap.get(Type.this);
}
-
+
public TypedKey<?>[] getDisplayedColumns() {
return displayedColumns;
}
-
- private static Map<Type,List<Type>> compatibleTypeMap = new HashMap<Type,List<Type>>();
-
+
+ private static Map<Type, List<Type>> compatibleTypeMap = new HashMap<Type, List<Type>>();
+
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));
+ 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> MANUFACTURER = new TypedKey<Manufacturer>("Manufacturer", Manufacturer.class);
- public final static TypedKey<String> PARTNO = new TypedKey<String>("PartNo",String.class);
+ public final static TypedKey<String> PARTNO = new TypedKey<String>("PartNo", String.class);
public final static TypedKey<String> DESCRIPTION = new TypedKey<String>("Description", String.class);
- public final static TypedKey<Type> TYPE = new TypedKey<Type>("Type",Type.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, UnitGroup.UNITS_LENGTH);
public final static TypedKey<Double> WIDTH = new TypedKey<Double>("Width", Double.class, UnitGroup.UNITS_LENGTH);
public final static TypedKey<Double> INNER_DIAMETER = new TypedKey<Double>("InnerDiameter", Double.class, UnitGroup.UNITS_LENGTH);
public final static TypedKey<Double> OUTER_DIAMETER = new TypedKey<Double>("OuterDiameter", Double.class, UnitGroup.UNITS_LENGTH);
- public final static TypedKey<Double> FORE_SHOULDER_LENGTH = new TypedKey<Double>("ForeShoulderLength",Double.class, UnitGroup.UNITS_LENGTH);
- public final static TypedKey<Double> FORE_SHOULDER_DIAMETER = new TypedKey<Double>("ForeShoulderDiameter",Double.class, UnitGroup.UNITS_LENGTH);
+ public final static TypedKey<Double> FORE_SHOULDER_LENGTH = new TypedKey<Double>("ForeShoulderLength", Double.class, UnitGroup.UNITS_LENGTH);
+ public final static TypedKey<Double> FORE_SHOULDER_DIAMETER = new TypedKey<Double>("ForeShoulderDiameter", Double.class, UnitGroup.UNITS_LENGTH);
public final static TypedKey<Double> FORE_OUTER_DIAMETER = new TypedKey<Double>("ForeOuterDiameter", Double.class, UnitGroup.UNITS_LENGTH);
- public final static TypedKey<Double> AFT_SHOULDER_LENGTH = new TypedKey<Double>("AftShoulderLength",Double.class, UnitGroup.UNITS_LENGTH);
- public final static TypedKey<Double> AFT_SHOULDER_DIAMETER = new TypedKey<Double>("AftShoulderDiameter",Double.class, UnitGroup.UNITS_LENGTH);
+ public final static TypedKey<Double> AFT_SHOULDER_LENGTH = new TypedKey<Double>("AftShoulderLength", Double.class, UnitGroup.UNITS_LENGTH);
+ public final static TypedKey<Double> AFT_SHOULDER_DIAMETER = new TypedKey<Double>("AftShoulderDiameter", Double.class, UnitGroup.UNITS_LENGTH);
public final static TypedKey<Double> AFT_OUTER_DIAMETER = new TypedKey<Double>("AftOuterDiameter", Double.class, UnitGroup.UNITS_LENGTH);
public final static TypedKey<Shape> SHAPE = new TypedKey<Shape>("Shape", Shape.class);
public final static TypedKey<Material> MATERIAL = new TypedKey<Material>("Material", Material.class);
public final static TypedKey<Integer> LINE_COUNT = new TypedKey<Integer>("LineCount", Integer.class);
public final static TypedKey<Double> LINE_LENGTH = new TypedKey<Double>("LineLength", Double.class, UnitGroup.UNITS_LENGTH);
public final static TypedKey<Material> LINE_MATERIAL = new TypedKey<Material>("LineMaterial", Material.class);
- public final static TypedKey<byte[]> IMAGE = new TypedKey<byte[]>("Image", byte[].class);
-
- public final static List<TypedKey<?>> orderedKeyList = Arrays.<TypedKey<?>>asList(
+ public final static TypedKey<byte[]> IMAGE = new TypedKey<byte[]>("Image", byte[].class);
+
+ public final static List<TypedKey<?>> ORDERED_KEY_LIST = Collections.unmodifiableList(Arrays.<TypedKey<?>> asList(
MANUFACTURER,
PARTNO,
DESCRIPTION,
MASS,
FINISH,
MATERIAL
- );
-
-
+ ));
+
+
// package scope constructor to encourage use of factory.
ComponentPreset() {
}
-
+
/**
* Convenience method to retrieve the Type of this ComponentPreset.
*
public Type getType() {
return properties.get(TYPE);
}
-
+
/**
* Convenience method to retrieve the Manufacturer of this ComponentPreset.
* @return
public Manufacturer getManufacturer() {
return properties.get(MANUFACTURER);
}
-
+
/**
* Convenience method to retrieve the PartNo of this ComponentPreset.
* @return
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
}
properties.putAll(other);
}
-
+
/**
* Package scope so the ComponentPresetFactory can call it.
* @param key
* @param value
*/
- <T> void put( TypedKey<T> key, T value ) {
+ <T> void put(TypedKey<T> key, T value) {
properties.put(key, value);
}
-
+
public <T> T get(TypedKey<T> 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;
+ return value;
}
-
- public void setFavorite(boolean favorite) {
- this.favorite = favorite;
- }
-
+
@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);
}
-
- @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;
- }
-
- /**
+
+ @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<TypedKey<?>> keys = new ArrayList<TypedKey<?>>( properties.keySet());
-
+
+ List<TypedKey<?>> keys = new ArrayList<TypedKey<?>>(properties.keySet());
+
Collections.sort(keys, new Comparator<TypedKey<?>>() {
@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 ) {
+ } else if (key.getType() == Shape.class) {
// this is ugly to use the ordinal but what else?
- int i = ((Shape)value).ordinal();
+ 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();
+ digest = TextUtil.hexString(md5.digest(bos.toByteArray()));
+ } catch (Exception e) {
+ e.printStackTrace();
throw new BugException(e);
}
}
-
+
}