4 package net.sf.openrocket.file.rocksim.importt;
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;
15 import java.util.HashMap;
18 * The SAX nose cone handler for Rocksim NoseCones.
20 class NoseConeHandler extends BaseHandler<NoseCone> {
23 * The OpenRocket NoseCone.
25 private final NoseCone noseCone = new NoseCone();
28 * The wall thickness. Used for hollow nose cones.
30 private double thickness = 0d;
35 * @param c the parent component to the nosecone
36 * @param warnings the warning set
38 * @throws IllegalArgumentException thrown if <code>c</code> is null
40 public NoseConeHandler(RocketComponent c, WarningSet warnings) throws IllegalArgumentException {
42 throw new IllegalArgumentException("The parent component of a nose cone may not be null.");
44 if (isCompatible(c, NoseCone.class, warnings)) {
46 noseCone.setAftRadiusAutomatic(false);
51 public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
52 //Nose cones in Rocksim may have attached parts - namely Mass Objects - as children.
53 if ("AttachedParts".equals(element)) {
54 return new AttachedPartsHandler(noseCone);
56 return PlainTextHandler.INSTANCE;
60 public void closeElement(String element, HashMap<String, String> attributes,
61 String content, WarningSet warnings) throws SAXException {
62 super.closeElement(element, attributes, content, warnings);
65 if ("ShapeCode".equals(element)) {
66 noseCone.setType(RocksimNoseConeCode.fromCode(Integer.parseInt(content)).asOpenRocket());
68 if ("Len".equals(element)) {
69 noseCone.setLength(Math.max(0, Double.parseDouble(content) / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH));
71 if ("BaseDia".equals(element)) {
72 noseCone.setAftRadius(Math.max(0, Double.parseDouble(content) / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS));
74 if ("WallThickness".equals(element)) {
75 thickness = Math.max(0, Double.parseDouble(content) / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH);
77 if ("ShoulderOD".equals(element)) {
78 noseCone.setAftShoulderRadius(Math.max(0, Double.parseDouble(
79 content) / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS));
81 if ("ShoulderLen".equals(element)) {
82 noseCone.setAftShoulderLength(Math.max(0, Double.parseDouble(
83 content) / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH));
85 if ("ShapeParameter".equals(element)) {
86 //The Rocksim ShapeParameter only applies to certain shapes, although it is included
87 //in the design file for all nose cones. Applying it when it should not be causes oddities so
88 //a check is made for the allowable shapes.
89 if (Transition.Shape.POWER.equals(noseCone.getType()) ||
90 Transition.Shape.HAACK.equals(noseCone.getType()) ||
91 Transition.Shape.PARABOLIC.equals(noseCone.getType())) {
92 noseCone.setShapeParameter(Double.parseDouble(content));
95 if ("ConstructionType".equals(element)) {
96 int typeCode = Integer.parseInt(content);
99 noseCone.setFilled(true);
101 else if (typeCode == 1) {
103 noseCone.setFilled(false);
106 if ("FinishCode".equals(element)) {
107 noseCone.setFinish(RocksimFinishCode.fromCode(Integer.parseInt(content)).asOpenRocket());
109 if ("Material".equals(element)) {
110 setMaterialName(content);
113 catch (NumberFormatException nfe) {
114 warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
119 public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
120 throws SAXException {
121 super.endHandler(element, attributes, content, warnings);
123 if (noseCone.isFilled()) {
124 noseCone.setAftShoulderThickness(noseCone.getAftShoulderRadius());
127 noseCone.setThickness(thickness);
128 noseCone.setAftShoulderThickness(thickness);
133 * Get the nose cone component this handler is working upon.
135 * @return a nose cone component
138 public NoseCone getComponent() {
143 * Get the required type of material for this component.
147 public Material.Type getMaterialType() {
148 return Material.Type.BULK;