Added persistence of ComponentPresets in the ORK file. Bumped ORK file version number to 1.5 when saving designs containing ComponentPresets. Added a digest string to ComponentPreset which is used during reading and writing ORK files to verify the correct ComponentPreset is used.
This commit is contained in:
parent
68eaf21ef0
commit
edcd0008b1
@ -38,3 +38,5 @@ The following file format versions exist:
|
||||
deploymentvelocity attributes to <flightdata> element. The motor
|
||||
digesting algorithm was changed. Adds <separationevent> and
|
||||
<separationdelay> elements to stage components (except sustainer).
|
||||
|
||||
1.5: Introduced with OpenRocket 12.xx. Added ComponentPresets.
|
@ -26,4 +26,6 @@ public interface ComponentPresetDao {
|
||||
|
||||
public void setFavorite( ComponentPreset preset, boolean favorite );
|
||||
|
||||
public List<ComponentPreset> find( String manufacturer, String partNo );
|
||||
|
||||
}
|
@ -129,6 +129,17 @@ public class ComponentPresetDatabase extends Database<ComponentPreset> implement
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ComponentPreset> find(String manufacturer, String partNo) {
|
||||
List<ComponentPreset> presets = new ArrayList<ComponentPreset>();
|
||||
for( ComponentPreset preset : list ) {
|
||||
if ( preset.getManufacturer().getSimpleName().equals(manufacturer) && preset.getPartNo().equals(partNo) ) {
|
||||
presets.add(preset);
|
||||
}
|
||||
}
|
||||
return presets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFavorite( ComponentPreset preset, boolean favorite ) {
|
||||
preset.setFavorite(favorite);
|
||||
|
@ -184,6 +184,9 @@ public class OpenRocketSaver extends RocketSaver {
|
||||
*/
|
||||
private int calculateNecessaryFileVersion(OpenRocketDocument document, StorageOptions opts) {
|
||||
/*
|
||||
* File version 1.5 is requires for:
|
||||
* - saving designs using ComponentPrests
|
||||
*
|
||||
* File version 1.4 is required for:
|
||||
* - saving simulation data
|
||||
* - saving motor data
|
||||
@ -195,6 +198,22 @@ public class OpenRocketSaver extends RocketSaver {
|
||||
* Otherwise use version 1.0.
|
||||
*/
|
||||
|
||||
// Search the rocket for any ComponentPrests
|
||||
{
|
||||
Rocket r = document.getRocket();
|
||||
Iterator<RocketComponent> componentIterator = r.iterator();
|
||||
boolean usesComponentPreset = false;
|
||||
while ( !usesComponentPreset && componentIterator.hasNext() ) {
|
||||
RocketComponent c = componentIterator.next();
|
||||
if ( c.getPresetComponent() != null ) {
|
||||
usesComponentPreset = true;
|
||||
}
|
||||
}
|
||||
if ( usesComponentPreset ) {
|
||||
return FILE_VERSION_DIVISOR + 5;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if design has simulations defined (version 1.4)
|
||||
if (document.getSimulationCount() > 0) {
|
||||
return FILE_VERSION_DIVISOR + 4;
|
||||
|
@ -28,6 +28,7 @@ import net.sf.openrocket.file.simplesax.SimpleSAX;
|
||||
import net.sf.openrocket.logging.LogHelper;
|
||||
import net.sf.openrocket.material.Material;
|
||||
import net.sf.openrocket.motor.Motor;
|
||||
import net.sf.openrocket.preset.ComponentPreset;
|
||||
import net.sf.openrocket.rocketcomponent.BodyComponent;
|
||||
import net.sf.openrocket.rocketcomponent.BodyTube;
|
||||
import net.sf.openrocket.rocketcomponent.Bulkhead;
|
||||
@ -101,7 +102,7 @@ public class OpenRocketLoader extends AbstractRocketLoader {
|
||||
|
||||
@Override
|
||||
public OpenRocketDocument loadFromStream(InputStream source, MotorFinder motorFinder) throws RocketLoadException,
|
||||
IOException {
|
||||
IOException {
|
||||
log.info("Loading .ork file");
|
||||
DocumentLoadingContext context = new DocumentLoadingContext();
|
||||
context.setMotorFinder(motorFinder);
|
||||
@ -164,7 +165,7 @@ public class OpenRocketLoader extends AbstractRocketLoader {
|
||||
class DocumentConfig {
|
||||
|
||||
/* Remember to update OpenRocketSaver as well! */
|
||||
public static final String[] SUPPORTED_VERSIONS = { "1.0", "1.1", "1.2", "1.3", "1.4" };
|
||||
public static final String[] SUPPORTED_VERSIONS = { "1.0", "1.1", "1.2", "1.3", "1.4", "1.5" };
|
||||
|
||||
/**
|
||||
* Divisor used in converting an integer version to the point-represented version.
|
||||
@ -236,6 +237,8 @@ class DocumentConfig {
|
||||
Reflection.findMethod(RocketComponent.class, "setOverrideSubcomponents", boolean.class)));
|
||||
setters.put("RocketComponent:comment", new StringSetter(
|
||||
Reflection.findMethod(RocketComponent.class, "setComment", String.class)));
|
||||
setters.put("RocketComponent:preset", new ComponentPresetSetter(
|
||||
Reflection.findMethod(RocketComponent.class, "loadPreset", ComponentPreset.class)));
|
||||
|
||||
// ExternalComponent
|
||||
setters.put("ExternalComponent:finish", new EnumSetter<Finish>(
|
||||
@ -1934,8 +1937,72 @@ class ColorSetter implements Setter {
|
||||
}
|
||||
}
|
||||
|
||||
////ComponentPresetSetter - sets a ComponentPreset value
|
||||
class ComponentPresetSetter implements Setter {
|
||||
private final Reflection.Method setMethod;
|
||||
|
||||
public ComponentPresetSetter(Reflection.Method set) {
|
||||
this.setMethod = set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(RocketComponent c, String name, HashMap<String, String> attributes,
|
||||
WarningSet warnings) {
|
||||
// FIXME - probably need more data in the warning messages - like what component preset...
|
||||
String manufacturerName = attributes.get("manufacturer");
|
||||
if ( manufacturerName == null ) {
|
||||
warnings.add(Warning.fromString("Invalid ComponentPreset, no manufacturer specified. Ignored"));
|
||||
return;
|
||||
}
|
||||
|
||||
String productNo = attributes.get("partno");
|
||||
if ( productNo == null ) {
|
||||
warnings.add(Warning.fromString("Invalid ComponentPreset, no partno specified. Ignored"));
|
||||
return;
|
||||
}
|
||||
|
||||
String digest = attributes.get("digest");
|
||||
if ( digest == null ) {
|
||||
warnings.add(Warning.fromString("Invalid ComponentPreset, no digest specified."));
|
||||
}
|
||||
|
||||
String type = attributes.get("type");
|
||||
if ( type == null ) {
|
||||
warnings.add(Warning.fromString("Invalid ComponentPreset, no type specified."));
|
||||
}
|
||||
|
||||
List<ComponentPreset> presets = Application.getComponentPresetDao().find( manufacturerName, productNo );
|
||||
|
||||
ComponentPreset matchingPreset = null;
|
||||
|
||||
for( ComponentPreset preset: presets ) {
|
||||
if ( digest != null && preset.getDigest().equals(digest) ) {
|
||||
// Found one with matching digest. Take it.
|
||||
matchingPreset = preset;
|
||||
break;
|
||||
}
|
||||
if ( type != null && preset.getType().name().equals(type) && matchingPreset != null) {
|
||||
// Found the first one with matching type.
|
||||
matchingPreset = preset;
|
||||
}
|
||||
}
|
||||
|
||||
// Was any found?
|
||||
if ( matchingPreset == null ) {
|
||||
warnings.add(Warning.fromString("No matching ComponentPreset found"));
|
||||
return;
|
||||
}
|
||||
|
||||
if ( digest != null && !matchingPreset.getDigest().equals(digest) ) {
|
||||
warnings.add(Warning.fromString("ComponentPreset has wrong digest"));
|
||||
}
|
||||
|
||||
setMethod.invoke(c, matchingPreset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////MaterialSetter - sets a Material value
|
||||
class MaterialSetter implements Setter {
|
||||
private final Reflection.Method setMethod;
|
||||
private final Material.Type type;
|
||||
|
@ -9,6 +9,7 @@ import net.sf.openrocket.file.RocketSaver;
|
||||
import net.sf.openrocket.material.Material;
|
||||
import net.sf.openrocket.motor.Motor;
|
||||
import net.sf.openrocket.motor.ThrustCurveMotor;
|
||||
import net.sf.openrocket.preset.ComponentPreset;
|
||||
import net.sf.openrocket.rocketcomponent.ComponentAssembly;
|
||||
import net.sf.openrocket.rocketcomponent.MotorMount;
|
||||
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||
@ -27,6 +28,13 @@ public class RocketComponentSaver {
|
||||
protected void addParams(net.sf.openrocket.rocketcomponent.RocketComponent c, List<String> elements) {
|
||||
elements.add("<name>" + RocketSaver.escapeXML(c.getName()) + "</name>");
|
||||
|
||||
ComponentPreset preset = c.getPresetComponent();
|
||||
if ( preset != null ) {
|
||||
elements.add("<preset type=\"" + preset.getType() +
|
||||
"\" manufacturer=\"" + preset.getManufacturer().getSimpleName() +
|
||||
"\" partno=\"" + preset.getPartNo() + "\" digest=\"" + preset.getDigest() +"\"/>");
|
||||
}
|
||||
|
||||
|
||||
// Save color and line style if significant
|
||||
if (!(c instanceof Rocket || c instanceof ComponentAssembly)) {
|
||||
|
@ -1,6 +1,13 @@
|
||||
package net.sf.openrocket.preset;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.ArrayList;
|
||||
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;
|
||||
@ -9,6 +16,7 @@ import net.sf.openrocket.rocketcomponent.BodyTube;
|
||||
import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish;
|
||||
import net.sf.openrocket.unit.UnitGroup;
|
||||
import net.sf.openrocket.util.BugException;
|
||||
import net.sf.openrocket.util.TextUtil;
|
||||
|
||||
|
||||
/**
|
||||
@ -25,6 +33,7 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
|
||||
private final TypedPropertyMap properties = new TypedPropertyMap();
|
||||
|
||||
private boolean favorite = false;
|
||||
private String digest = "";
|
||||
|
||||
public enum Type {
|
||||
BODY_TUBE,
|
||||
@ -158,23 +167,45 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
|
||||
}
|
||||
}
|
||||
|
||||
preset.computeDigest();
|
||||
|
||||
return preset;
|
||||
|
||||
}
|
||||
|
||||
// Private constructor to encourage use of factory.
|
||||
private 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
|
||||
*/
|
||||
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);
|
||||
}
|
||||
@ -214,4 +245,58 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
|
||||
return get(MANUFACTURER).toString() + "|" + get(PARTNO);
|
||||
}
|
||||
|
||||
private void computeDigest() {
|
||||
|
||||
try {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
DataOutputStream os = new DataOutputStream(bos);
|
||||
|
||||
List<TypedKey<?>> keys = new ArrayList<TypedKey<?>>( properties.keySet());
|
||||
|
||||
Collections.sort(keys, new Comparator<TypedKey<?>>() {
|
||||
@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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MessageDigest md5 = MessageDigest.getInstance("MD5");
|
||||
digest = TextUtil.hexString(md5.digest( bos.toByteArray() ));
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
throw new BugException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user