/*
* NoseConeHandler.java
*/
package net.sf.openrocket.file.rocksim.importt;
import java.util.HashMap;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.rocksim.RocksimCommonConstants;
import net.sf.openrocket.file.rocksim.RocksimFinishCode;
import net.sf.openrocket.file.rocksim.RocksimNoseConeCode;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;
import net.sf.openrocket.material.Material;
import net.sf.openrocket.rocketcomponent.NoseCone;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.Transition;
import org.xml.sax.SAXException;
/**
* The SAX nose cone handler for Rocksim NoseCones.
*/
class NoseConeHandler extends BaseHandler<NoseCone> {
/**
* The OpenRocket NoseCone.
*/
private final NoseCone noseCone = new NoseCone();
/**
* The wall thickness. Used for hollow nose cones.
*/
private double thickness = 0d;
/**
* Constructor.
*
* @param c the parent component to the nosecone
* @param warnings the warning set
*
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public NoseConeHandler(DocumentLoadingContext context, RocketComponent c, WarningSet warnings) throws IllegalArgumentException {
super(context);
if (c == null) {
throw new IllegalArgumentException("The parent component of a nose cone may not be null.");
}
if (isCompatible(c, NoseCone.class, warnings)) {
c.addChild(noseCone);
noseCone.setAftRadiusAutomatic(false);
}
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
//Nose cones in Rocksim may have attached parts - namely Mass Objects - as children.
if (RocksimCommonConstants.ATTACHED_PARTS.equals(element)) {
return new AttachedPartsHandler(context, noseCone);
}
return PlainTextHandler.INSTANCE;
}
@Override
public void closeElement(String element, HashMap<String, String> attributes,
String content, WarningSet warnings) throws SAXException {
super.closeElement(element, attributes, content, warnings);
try {
if (RocksimCommonConstants.SHAPE_CODE.equals(element)) {
noseCone.setType(RocksimNoseConeCode.fromCode(Integer.parseInt(content)).asOpenRocket());
}
if (RocksimCommonConstants.LEN.equals(element)) {
noseCone.setLength(Math.max(0, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
}
if (RocksimCommonConstants.BASE_DIA.equals(element)) {
noseCone.setAftRadius(Math.max(0, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
}
if (RocksimCommonConstants.WALL_THICKNESS.equals(element)) {
thickness = Math.max(0, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
}
if (RocksimCommonConstants.SHOULDER_OD.equals(element)) {
noseCone.setAftShoulderRadius(Math.max(0, Double.parseDouble(
content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
}
if (RocksimCommonConstants.SHOULDER_LEN.equals(element)) {
noseCone.setAftShoulderLength(Math.max(0, Double.parseDouble(
content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
}
if (RocksimCommonConstants.SHAPE_PARAMETER.equals(element)) {
//The Rocksim ShapeParameter only applies to certain shapes, although it is included
//in the design file for all nose cones. Applying it when it should not be causes oddities so
//a check is made for the allowable shapes.
if (Transition.Shape.POWER.equals(noseCone.getType()) ||
Transition.Shape.HAACK.equals(noseCone.getType()) ||
Transition.Shape.PARABOLIC.equals(noseCone.getType())) {
noseCone.setShapeParameter(Double.parseDouble(content));
}
}
if (RocksimCommonConstants.CONSTRUCTION_TYPE.equals(element)) {
int typeCode = Integer.parseInt(content);
if (typeCode == 0) {
//SOLID
noseCone.setFilled(true);
}
else if (typeCode == 1) {
//HOLLOW
noseCone.setFilled(false);
}
}
if (RocksimCommonConstants.FINISH_CODE.equals(element)) {
noseCone.setFinish(RocksimFinishCode.fromCode(Integer.parseInt(content)).asOpenRocket());
}
if (RocksimCommonConstants.MATERIAL.equals(element)) {
setMaterialName(content);
}
} catch (NumberFormatException nfe) {
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
}
}
@Override
public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
throws SAXException {
super.endHandler(element, attributes, content, warnings);
if (noseCone.isFilled()) {
noseCone.setAftShoulderThickness(noseCone.getAftShoulderRadius());
}
else {
noseCone.setThickness(thickness);
noseCone.setAftShoulderThickness(thickness);
}
}
/**
* Get the nose cone component this handler is working upon.
*
* @return a nose cone component
*/
@Override
public NoseCone getComponent() {
return noseCone;
}
/**
* Get the required type of material for this component.
*
* @return BULK
*/
public Material.Type getMaterialType() {
return Material.Type.BULK;
}
}