@Override
  public void set(
      RocketComponent c, String s, HashMap<String, String> attributes, WarningSet warnings) {

    if (!(c instanceof FinSet)) {
      throw new IllegalStateException("FinTabPositionSetter called for component " + c);
    }

    String relative = attributes.get("relativeto");
    FinSet.TabRelativePosition position =
        (TabRelativePosition) DocumentConfig.findEnum(relative, FinSet.TabRelativePosition.class);

    if (position != null) {

      ((FinSet) c).setTabRelativePosition(position);

    } else {
      if (relative == null) {
        warnings.add("Required attribute 'relativeto' not found for fin tab position.");
      } else {
        warnings.add("Illegal attribute value '" + relative + "' encountered.");
      }
    }

    super.set(c, s, attributes, warnings);
  }
  @Override
  public void endHandler(
      String element, HashMap<String, String> attributes, String content, WarningSet warnings)
      throws SAXException {

    FlightConfigurationId fcid = new FlightConfigurationId(attributes.remove("configid"));
    if (!fcid.isValid()) {
      warnings.add(Warning.FILE_INVALID_PARAMETER);
      return;
    }

    rocket.createFlightConfiguration(fcid);

    if (name != null && name.trim().length() > 0) {
      rocket.getFlightConfiguration(fcid).setName(name);
    }

    if ("true".equals(attributes.remove("default"))) {
      // also associate this configuration with the default.
      FlightConfiguration fc = rocket.getFlightConfiguration(fcid);
      rocket.setSelectedConfiguration(fc);
    }

    super.closeElement(element, attributes, content, warnings);
  }
 @Override
 public ElementHandler openElement(
     String element, HashMap<String, String> attributes, WarningSet warnings) {
   if (RocksimCommonConstants.FIN_SET.equals(element)) {
     return new FinSetHandler(context, component);
   }
   if (RocksimCommonConstants.CUSTOM_FIN_SET.equals(element)) {
     return new FinSetHandler(context, component);
   }
   if (RocksimCommonConstants.LAUNCH_LUG.equals(element)) {
     return new LaunchLugHandler(context, component, warnings);
   }
   if (RocksimCommonConstants.PARACHUTE.equals(element)) {
     return new ParachuteHandler(context, component, warnings);
   }
   if (RocksimCommonConstants.STREAMER.equals(element)) {
     return new StreamerHandler(context, component, warnings);
   }
   if (RocksimCommonConstants.MASS_OBJECT.equals(element)) {
     return new MassObjectHandler(context, component, warnings);
   }
   if (RocksimCommonConstants.RING.equals(element)) {
     return new RingHandler(context, component, warnings);
   }
   if (RocksimCommonConstants.BODY_TUBE.equals(element)) {
     return new InnerBodyTubeHandler(context, component, warnings);
   }
   if (RocksimCommonConstants.TRANSITION.equals(element)) {
     return new TransitionHandler(context, component, warnings);
   }
   if (RocksimCommonConstants.TUBE_FIN_SET.equals(element)) {
     warnings.add("Tube fins are not currently supported. Ignoring.");
   }
   if (RocksimCommonConstants.RING_TAIL.equals(element)) {
     warnings.add("Ring tails are not currently supported. Ignoring.");
   }
   if (RocksimCommonConstants.EXTERNAL_POD.equals(element)) {
     warnings.add("Pods are not currently supported. Ignoring.");
   }
   return null;
 }
  @Override
  public ElementHandler openElement(
      String element, HashMap<String, String> attributes, WarningSet warnings) {

    if (inNameElement || !element.equals("name")) {
      warnings.add(Warning.FILE_INVALID_PARAMETER);
      return null;
    }
    inNameElement = true;

    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 ("ShapeCode".equals(element)) {
        transition.setType(RocksimNoseConeCode.fromCode(Integer.parseInt(content)).asOpenRocket());
      }
      if ("Len".equals(element)) {
        transition.setLength(
            Math.max(
                0,
                Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
      }
      if ("FrontDia".equals(element)) {
        transition.setForeRadius(
            Math.max(
                0,
                Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
      }
      if ("RearDia".equals(element)) {
        transition.setAftRadius(
            Math.max(
                0,
                Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
      }
      if ("WallThickness".equals(element)) {
        thickness =
            Math.max(
                0d,
                Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
      }
      if ("FrontShoulderDia".equals(element)) {
        transition.setForeShoulderRadius(
            Math.max(
                0d,
                Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
      }
      if ("RearShoulderDia".equals(element)) {
        transition.setAftShoulderRadius(
            Math.max(
                0d,
                Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
      }
      if ("FrontShoulderLen".equals(element)) {
        transition.setForeShoulderLength(
            Math.max(
                0d,
                Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
      }
      if ("RearShoulderLen".equals(element)) {
        transition.setAftShoulderLength(
            Math.max(
                0d,
                Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
      }
      if ("ShapeParameter".equals(element)) {
        if (Transition.Shape.POWER.equals(transition.getType())
            || Transition.Shape.HAACK.equals(transition.getType())
            || Transition.Shape.PARABOLIC.equals(transition.getType())) {
          transition.setShapeParameter(Double.parseDouble(content));
        }
      }
      if ("ConstructionType".equals(element)) {
        int typeCode = Integer.parseInt(content);
        if (typeCode == 0) {
          // SOLID
          transition.setFilled(true);
        } else if (typeCode == 1) {
          // HOLLOW
          transition.setFilled(false);
        }
      }
      if ("FinishCode".equals(element)) {
        transition.setFinish(RocksimFinishCode.fromCode(Integer.parseInt(content)).asOpenRocket());
      }
      if ("Material".equals(element)) {
        setMaterialName(content);
      }
    } catch (NumberFormatException nfe) {
      warnings.add(
          "Could not convert "
              + element
              + " value of "
              + content
              + ".  It is expected to be a number.");
    }
  }