De-localize Material and FlightDataType objects when persisting in ork files. Added...
[debian/openrocket] / core / src / net / sf / openrocket / preset / ComponentPresetFactory.java
index 6531a31e1f3b20c6f2be31ddc6c579c96163254a..7c4b2b9a0fac3f807b58e145458d31dce82cf94f 100644 (file)
@@ -1,20 +1,8 @@
 package net.sf.openrocket.preset;
 
-import static net.sf.openrocket.preset.ComponentPreset.FORE_OUTER_DIAMETER;
-import static net.sf.openrocket.preset.ComponentPreset.INNER_DIAMETER;
-import static net.sf.openrocket.preset.ComponentPreset.LENGTH;
-import static net.sf.openrocket.preset.ComponentPreset.MANUFACTURER;
-import static net.sf.openrocket.preset.ComponentPreset.MASS;
-import static net.sf.openrocket.preset.ComponentPreset.MATERIAL;
-import static net.sf.openrocket.preset.ComponentPreset.OUTER_DIAMETER;
-import static net.sf.openrocket.preset.ComponentPreset.PARTNO;
-import static net.sf.openrocket.preset.ComponentPreset.SHAPE;
-import static net.sf.openrocket.preset.ComponentPreset.THICKNESS;
-import static net.sf.openrocket.preset.ComponentPreset.TYPE;
+import static net.sf.openrocket.preset.ComponentPreset.*;
 import net.sf.openrocket.material.Material;
 import net.sf.openrocket.preset.ComponentPreset.Type;
-import net.sf.openrocket.rocketcomponent.BodyTube;
-import net.sf.openrocket.rocketcomponent.Bulkhead;
 import net.sf.openrocket.rocketcomponent.NoseCone;
 import net.sf.openrocket.rocketcomponent.Transition;
 
@@ -22,108 +10,106 @@ public abstract class ComponentPresetFactory {
 
        public static ComponentPreset create( TypedPropertyMap props ) throws InvalidComponentPresetException {
 
+               InvalidComponentPresetException exceptions = new InvalidComponentPresetException("Invalid preset specification.");
+               
                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() );
+                       exceptions.addInvalidParameter(MANUFACTURER, "No Manufacturer specified"); 
                }
-
                if (!props.containsKey(PARTNO)) {
-                       throw new InvalidComponentPresetException("No PartNo specified " + props.toString() );
+                       exceptions.addInvalidParameter(PARTNO,"No PartNo specified");
+               }
+               if ( !props.containsKey(TYPE)) {
+                       exceptions.addInvalidParameter(TYPE, "No Type specified" );
+                       // We can't do anything else without TYPE so throw immediately.
+                       throw exceptions;
                }
 
+
                preset.putAll(props);
 
                // Should check for various bits of each of the types.
                Type t = props.get(TYPE);
                switch ( t ) {
                case BODY_TUBE: {
-                       makeBodyTube(preset);
+                       makeBodyTube(exceptions,preset);
                        break;
                }
                case NOSE_CONE: {
-                       makeNoseCone(preset);
+                       makeNoseCone(exceptions,preset);
                        break;
                }
                case TRANSITION: {
-                       makeTransition(preset);
+                       makeTransition(exceptions,preset);
                        break;
                }
                case BULK_HEAD: {
-                       makeBulkHead(preset);
+                       makeBulkHead(exceptions,preset);
                        break;
                }
                case TUBE_COUPLER: {
-                       makeTubeCoupler(preset);
+                       // For now TUBE_COUPLER is the same as BODY_TUBE
+                       makeBodyTube(exceptions,preset);
+                       break;
+               }
+               case CENTERING_RING: {
+                       makeCenteringRing(exceptions,preset);
+                       break;
+               }
+               case ENGINE_BLOCK: {
+                       makeEngineBlock(exceptions,preset);
+                       break;
+               }
+               case LAUNCH_LUG: {
+                       // Same processing as BODY_TUBE
+                       makeBodyTube(exceptions,preset);
+                       break;
+               }
+               case STREAMER: {
+                       makeStreamer(exceptions,preset);
+                       break;
+               }
+               case PARACHUTE: {
+                       makeParachute(exceptions,preset);
                        break;
                }
                }
 
+               if ( exceptions.hasProblems() ) {
+                       throw exceptions;
+               }
+               
                preset.computeDigest();
 
                return preset;
 
        }
 
-       private static void makeBodyTube( ComponentPreset preset ) throws InvalidComponentPresetException {
+       private static void makeBodyTube( InvalidComponentPresetException exceptions, ComponentPreset preset ) throws InvalidComponentPresetException {
                
-               checkRequiredFields( preset, LENGTH );
-
-               BodyTube bt = new BodyTube();
-
-               bt.setLength(preset.get(LENGTH));
-
-               // Need to verify contains 2 of OD, thickness, ID.  Compute the third.
-               boolean hasOd = preset.has(OUTER_DIAMETER);
-               boolean hasId = preset.has(INNER_DIAMETER);
-               boolean hasThickness = preset.has(THICKNESS);
-
-               if ( hasOd ) {
-                       double outerRadius = preset.get(OUTER_DIAMETER)/2.0;
-                       double thickness = 0;
-                       bt.setOuterRadius( outerRadius );
-                       if ( hasId ) {
-                               thickness = outerRadius - preset.get(INNER_DIAMETER)/2.0;
-                       } else if ( hasThickness ) {
-                               thickness = preset.get(THICKNESS);
-                       } else {
-                               throw new InvalidComponentPresetException("Body tube preset underspecified " + preset.toString());
-                       }
-                       bt.setThickness( thickness );
-               } else {
-                       if ( ! hasId && ! hasThickness ) {
-                               throw new InvalidComponentPresetException("Body tube preset underspecified " + preset.toString());
-                       }
-                       double innerRadius = preset.get(INNER_DIAMETER)/2.0;
-                       double thickness = preset.get(THICKNESS);
-                       bt.setOuterRadius(innerRadius + thickness);
-                       bt.setThickness(thickness);
-               }
-
-               preset.put(OUTER_DIAMETER, bt.getOuterRadius() *2.0);
-               preset.put(INNER_DIAMETER, bt.getInnerRadius() *2.0);
-               preset.put(THICKNESS, bt.getThickness());
+               checkRequiredFields( exceptions, preset, LENGTH );
 
+               checkDiametersAndThickness(exceptions, preset);
+               
+               double volume = computeVolumeOfTube( preset );
+               
                // Need to translate Mass to Density.
                if ( preset.has(MASS) ) {
                        String materialName = "TubeCustom";
                        if ( preset.has(MATERIAL) ) {
                                materialName = preset.get(MATERIAL).getName();
                        }
-                       Material m = Material.newMaterial(Material.Type.BULK, materialName, preset.get(MASS)/bt.getComponentVolume(), false);
+                       Material m = Material.newUserMaterial(Material.Type.BULK, materialName, preset.get(MASS)/volume);
                        preset.put(MATERIAL, m);
                }
 
 
        }
 
-       private static void makeNoseCone( ComponentPreset preset ) throws InvalidComponentPresetException {
+       private static void makeNoseCone( InvalidComponentPresetException exceptions, ComponentPreset preset ) {
 
-               checkRequiredFields( preset, LENGTH, SHAPE, OUTER_DIAMETER );
+               checkRequiredFields( exceptions, preset, LENGTH, SHAPE, AFT_OUTER_DIAMETER );
 
                if ( preset.has(MASS) ) {
                        // compute a density for this component
@@ -137,15 +123,15 @@ public abstract class ComponentPresetFactory {
                                materialName = preset.get(MATERIAL).getName();
                        }
 
-                       Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false);
+                       Material m = Material.newUserMaterial(Material.Type.BULK, materialName,density);
                        preset.put(MATERIAL, m);
 
                }
 
        }
 
-       private static void makeTransition( ComponentPreset preset ) throws InvalidComponentPresetException {
-               checkRequiredFields(preset, LENGTH, OUTER_DIAMETER, FORE_OUTER_DIAMETER);
+       private static void makeTransition( InvalidComponentPresetException exceptions, ComponentPreset preset ) {
+               checkRequiredFields(exceptions, preset, LENGTH, AFT_OUTER_DIAMETER, FORE_OUTER_DIAMETER);
 
                if ( preset.has(MASS) ) {
                        // compute a density for this component
@@ -159,98 +145,135 @@ public abstract class ComponentPresetFactory {
                                materialName = preset.get(MATERIAL).getName();
                        }
 
-                       Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false);
+                       Material m = Material.newUserMaterial(Material.Type.BULK, materialName,density);
                        preset.put(MATERIAL, m);
 
                }
 
        }
 
-       private static void makeBulkHead( ComponentPreset preset ) throws InvalidComponentPresetException {
-               checkRequiredFields(preset, LENGTH, OUTER_DIAMETER );
+       private static void makeBulkHead( InvalidComponentPresetException exceptions, ComponentPreset preset ) {
+               checkRequiredFields(exceptions, preset, LENGTH, OUTER_DIAMETER );
 
                if ( preset.has(MASS) ) {
                        // compute a density for this component
                        double mass = preset.get(MASS);
-                       Bulkhead tr = new Bulkhead();
-                       tr.loadPreset(preset);
-                       // FIXME - Bulkhead.getComponentVolume does not exist!
-                       // double density = mass / tr.getComponentVolume();
 
-                       double volume = Math.pow(preset.get(OUTER_DIAMETER),2) * Math.PI / 4.0;
+                       double volume = computeVolumeOfTube(preset);
                        double density = mass / volume;
 
-                       String materialName = "TransitionCustom";
+                       String materialName = "BulkHeadCustom";
                        if ( preset.has(MATERIAL) ) {
                                materialName = preset.get(MATERIAL).getName();
                        }
 
-                       Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false);
+                       Material m = Material.newUserMaterial(Material.Type.BULK, materialName,density);
                        preset.put(MATERIAL, m);
 
                }
 
        }
 
-       private static void makeTubeCoupler( ComponentPreset preset ) throws InvalidComponentPresetException {
-               
-               checkRequiredFields( preset, LENGTH );
+       private static void makeCenteringRing( InvalidComponentPresetException exceptions, ComponentPreset preset ) throws InvalidComponentPresetException {
+               checkRequiredFields( exceptions, preset, LENGTH );
 
-               // FIXME - TubeCoupler does not have getComponentVolume.  So we use a BodyTube for this.
-               BodyTube bt = new BodyTube();
+               checkDiametersAndThickness( exceptions, preset );
 
-               bt.setLength(preset.get(LENGTH));
+               double volume = computeVolumeOfTube( preset );
 
-               // Need to verify contains 2 of OD, thickness, ID.  Compute the third.
-               boolean hasOd = preset.has(OUTER_DIAMETER);
-               boolean hasId = preset.has(INNER_DIAMETER);
-               boolean hasThickness = preset.has(THICKNESS);
-
-               if ( hasOd ) {
-                       double outerRadius = preset.get(OUTER_DIAMETER)/2.0;
-                       double thickness = 0;
-                       bt.setOuterRadius( outerRadius );
-                       if ( hasId ) {
-                               thickness = outerRadius - preset.get(INNER_DIAMETER)/2.0;
-                       } else if ( hasThickness ) {
-                               thickness = preset.get(THICKNESS);
-                       } else {
-                               throw new InvalidComponentPresetException("Body tube preset underspecified " + preset.toString());
-                       }
-                       bt.setThickness( thickness );
-               } else {
-                       if ( ! hasId && ! hasThickness ) {
-                               throw new InvalidComponentPresetException("Body tube preset underspecified " + preset.toString());
+               // Need to translate Mass to Density.
+               if ( preset.has(MASS) ) {
+                       String materialName = "CenteringRingCustom";
+                       if ( preset.has(MATERIAL) ) {
+                               materialName = preset.get(MATERIAL).getName();
                        }
-                       double innerRadius = preset.get(INNER_DIAMETER)/2.0;
-                       double thickness = preset.get(THICKNESS);
-                       bt.setOuterRadius(innerRadius + thickness);
-                       bt.setThickness(thickness);
+                       Material m = Material.newUserMaterial(Material.Type.BULK, materialName, preset.get(MASS)/volume);
+                       preset.put(MATERIAL, m);
                }
 
-               preset.put(OUTER_DIAMETER, bt.getOuterRadius() *2.0);
-               preset.put(INNER_DIAMETER, bt.getInnerRadius() *2.0);
-               preset.put(THICKNESS, bt.getThickness());
+       }
+       
+       private static void makeEngineBlock( InvalidComponentPresetException exceptions, ComponentPreset preset ) throws InvalidComponentPresetException {
+               checkRequiredFields( exceptions, preset, LENGTH );
+
+               checkDiametersAndThickness( exceptions, preset );
+
+               double volume = computeVolumeOfTube( preset );
 
                // Need to translate Mass to Density.
                if ( preset.has(MASS) ) {
-                       String materialName = "TubeCustom";
+                       String materialName = "EngineBlockCustom";
                        if ( preset.has(MATERIAL) ) {
                                materialName = preset.get(MATERIAL).getName();
                        }
-                       Material m = Material.newMaterial(Material.Type.BULK, materialName, preset.get(MASS)/bt.getComponentVolume(), false);
+                       Material m = Material.newUserMaterial(Material.Type.BULK, materialName, preset.get(MASS)/volume);
                        preset.put(MATERIAL, m);
                }
 
+       }
+       
+       private static void makeStreamer( InvalidComponentPresetException exceptions, ComponentPreset preset ) {
+               checkRequiredFields( exceptions, preset, LENGTH, WIDTH );
+       }
 
+       private static void makeParachute( InvalidComponentPresetException exceptions, ComponentPreset preset ) {
+               checkRequiredFields( exceptions, preset, DIAMETER, LINE_COUNT, LINE_LENGTH );
        }
        
-       private static void checkRequiredFields( ComponentPreset preset, TypedKey<?> ... keys ) throws InvalidComponentPresetException {
+
+       private static void checkRequiredFields( InvalidComponentPresetException exceptions, ComponentPreset preset, TypedKey<?> ... keys ) {
                for( TypedKey<?> key: keys ) {
                        if (! preset.has(key) ) {
-                               throw new InvalidComponentPresetException( "No " + key.getName() + " specified for " + preset.getType().name() + " preset " + preset.toString());
+                               exceptions.addInvalidParameter(key, "No " + key.getName() + " specified");
                        }
                }
        }
 
+       private static void checkDiametersAndThickness( InvalidComponentPresetException exceptions, ComponentPreset preset ) throws InvalidComponentPresetException {
+               // Need to verify contains 2 of OD, thickness, ID.  Compute the third.
+               boolean hasOd = preset.has(OUTER_DIAMETER);
+               boolean hasId = preset.has(INNER_DIAMETER);
+               boolean hasThickness = preset.has(THICKNESS);
+
+               double outerRadius;
+               double innerRadius;
+               double thickness;
+               
+               if ( hasOd ) {
+                       outerRadius = preset.get(OUTER_DIAMETER)/2.0;
+                       thickness = 0;
+                       if ( hasId ) {
+                               innerRadius = preset.get(INNER_DIAMETER)/2.0;
+                               thickness = outerRadius - innerRadius;
+                       } else if ( hasThickness ) {
+                               thickness = preset.get(THICKNESS);
+                               innerRadius = outerRadius - thickness;
+                       } else {
+                               exceptions.addMessage("Preset dimensions underspecified");
+                               throw exceptions;
+                       }
+               } else {
+                       if ( ! hasId || ! hasThickness ) {
+                               exceptions.addMessage("Preset dimensions underspecified");
+                               throw exceptions;
+                       }
+                       innerRadius = preset.get(INNER_DIAMETER)/2.0;
+                       thickness = preset.get(THICKNESS);
+                       outerRadius = innerRadius + thickness;
+               }
+
+               preset.put(OUTER_DIAMETER, outerRadius *2.0);
+               preset.put(INNER_DIAMETER, innerRadius *2.0);
+               preset.put(THICKNESS, thickness );
+
+       }
+       
+       private static double computeVolumeOfTube(ComponentPreset preset) {
+               double or = preset.get(OUTER_DIAMETER)/2.0;
+               double ir = preset.has(INNER_DIAMETER) ? preset.get(INNER_DIAMETER)/2.0 : 0.0;
+               double l = preset.get(LENGTH);
+               return Math.PI * (or*or - ir*ir) * l;
+       }
+
+       
 }