committed Doug's Rocksim loader
[debian/openrocket] / src / net / sf / openrocket / file / rocksim / NoseConeHandler.java
1 /*
2  * NoseConeHandler.java
3  */
4 package net.sf.openrocket.file.rocksim;
5
6 import net.sf.openrocket.aerodynamics.WarningSet;
7 import net.sf.openrocket.file.simplesax.ElementHandler;
8 import net.sf.openrocket.file.simplesax.PlainTextHandler;
9 import net.sf.openrocket.material.Material;
10 import net.sf.openrocket.rocketcomponent.NoseCone;
11 import net.sf.openrocket.rocketcomponent.RocketComponent;
12 import net.sf.openrocket.rocketcomponent.Transition;
13 import org.xml.sax.SAXException;
14
15 import java.util.HashMap;
16
17 /**
18  * The SAX nose cone handler for Rocksim NoseCones.
19  */
20 class NoseConeHandler extends BaseHandler<NoseCone> {
21
22     /**
23      * The OpenRocket NoseCone.
24      */
25     private final NoseCone noseCone = new NoseCone();
26
27     /**
28      * The wall thickness.  Used for hollow nose cones.  
29      */
30     private double thickness = 0d;
31     
32     /**
33      * Constructor.
34      *
35      * @param c the parent component to the nosecone
36      * @throws IllegalArgumentException thrown if <code>c</code> is null
37      */
38     public NoseConeHandler(RocketComponent c) throws IllegalArgumentException {
39         if (c == null) {
40             throw new IllegalArgumentException("The parent component of a nose cone may not be null.");
41         }
42         c.addChild(noseCone);
43         noseCone.setAftRadiusAutomatic(false);
44     }
45
46     @Override
47     public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
48         //Nose cones in Rocksim may have attached parts - namely Mass Objects - as children.
49         if ("AttachedParts".equals(element)) {
50             return new AttachedPartsHandler(noseCone);
51         }
52         return PlainTextHandler.INSTANCE;
53     }
54
55     @Override
56     public void closeElement(String element, HashMap<String, String> attributes,
57                              String content, WarningSet warnings) throws SAXException {
58         super.closeElement(element, attributes, content, warnings);
59
60         try {
61             if ("ShapeCode".equals(element)) {
62                 noseCone.setType(RocksimNoseConeCode.fromCode(Integer.parseInt(content)).asOpenRocket());
63             }
64             if ("Len".equals(element)) {
65                 noseCone.setLength(Math.max(0, Double.parseDouble(content) / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH));
66             }
67             if ("BaseDia".equals(element)) {
68                 noseCone.setAftRadius(Math.max(0, Double.parseDouble(content) / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS));
69             }
70             if ("WallThickness".equals(element)) {
71                 thickness = Math.max(0, Double.parseDouble(content) / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH);
72             }
73             if ("ShoulderOD".equals(element)) {
74                 noseCone.setAftShoulderRadius(Math.max(0, Double.parseDouble(
75                         content) / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS));
76             }
77             if ("ShoulderLen".equals(element)) {
78                 noseCone.setAftShoulderLength(Math.max(0, Double.parseDouble(
79                         content) / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH));
80             }
81             if ("ShapeParameter".equals(element)) {
82                 //The Rocksim ShapeParameter only applies to certain shapes, although it is included
83                 //in the design file for all nose cones.  Applying it when it should not be causes oddities so 
84                 //a check is made for the allowable shapes.
85                 if (Transition.Shape.POWER.equals(noseCone.getType()) ||
86                     Transition.Shape.HAACK.equals(noseCone.getType()) ||
87                     Transition.Shape.PARABOLIC.equals(noseCone.getType())) {
88                     noseCone.setShapeParameter(Double.parseDouble(content));
89                 }
90             }
91             if ("ConstructionType".equals(element)) {
92                 int typeCode = Integer.parseInt(content);
93                 if (typeCode == 0) {
94                     //SOLID
95                     noseCone.setFilled(true);
96                 }
97                 else if (typeCode == 1) {
98                     //HOLLOW
99                     noseCone.setFilled(false);
100                 }
101             }
102             if ("FinishCode".equals(element)) {
103                 noseCone.setFinish(RocksimFinishCode.fromCode(Integer.parseInt(content)).asOpenRocket());
104             }
105             if ("Material".equals(element)) {
106                 setMaterialName(content);
107             }
108         }
109         catch (NumberFormatException nfe) {
110             warnings.add("Could not convert " + element + " value of " + content + ".  It is expected to be a number.");
111         }
112     }
113
114     @Override
115     public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
116             throws SAXException {
117         super.endHandler(element, attributes, content, warnings);
118         
119         if (noseCone.isFilled()) {
120             noseCone.setAftShoulderThickness(noseCone.getAftShoulderRadius());                    
121         }
122         else {
123             noseCone.setThickness(thickness);
124             noseCone.setAftShoulderThickness(thickness);
125         }
126     }
127     
128     /**
129      * Get the nose cone component this handler is working upon.
130      *
131      * @return a nose cone component
132      */
133     @Override
134     public NoseCone getComponent() {
135         return noseCone;
136     }
137
138     /**
139      * Get the required type of material for this component.
140      *
141      * @return BULK
142      */
143     public Material.Type getMaterialType() {
144         return Material.Type.BULK;
145     }
146
147 }