/**
   * Convert the value from a source unit to a target unit Note: if the value is an age, the method
   * adjusts the value to return the right age
   *
   * @param activeInstrumentRunService
   * @param targetInstrumentRunValue
   * @param sourceInstrumentRunValue
   */
  @SuppressWarnings("unchecked")
  public void convert(
      ActiveInstrumentRunService activeInstrumentRunService,
      InstrumentRunValue targetInstrumentRunValue,
      InstrumentRunValue sourceInstrumentRunValue) {

    InstrumentParameter sourceParameter =
        activeInstrumentRunService
            .getInstrumentType()
            .getInstrumentParameter(sourceInstrumentRunValue.getInstrumentParameter());
    InstrumentParameter targetParameter =
        activeInstrumentRunService
            .getInstrumentType()
            .getInstrumentParameter(targetInstrumentRunValue.getInstrumentParameter());

    log.debug(
        "Converting parameters from source {} to target {}", sourceParameter, targetParameter);

    Unit sourceUnit = Unit.valueOf(sourceParameter.getMeasurementUnit());
    Unit targetUnit = Unit.valueOf(targetParameter.getMeasurementUnit());

    log.debug(
        "Converting units from source {} to target {}",
        sourceUnit.toString(),
        targetUnit.toString());

    double sourceValue;
    // Extract the source value and convert it to a double
    try {
      sourceValue =
          Double.parseDouble(
              sourceInstrumentRunValue.getData(sourceParameter.getDataType()).getValueAsString());
    } catch (NumberFormatException e) {
      Data sourceData = sourceInstrumentRunValue.getData(sourceParameter.getDataType());
      log.error(
          "Error converting between measurement units. Original value {} of type {} cannot be converted to a double, which is required to convert between measurement units.",
          sourceData.getValueAsString(),
          sourceData.getType());
      throw e;
    }

    double newValue = sourceUnit.getConverterTo(targetUnit).convert(sourceValue);

    switch (activeInstrumentRunService
        .getInstrumentType()
        .getInstrumentParameter(targetInstrumentRunValue.getInstrumentParameter())
        .getDataType()) {
      case DECIMAL:
        targetInstrumentRunValue.setData(DataBuilder.buildDecimal(newValue));
        break;

      case INTEGER:
        if (targetUnit.toString().equalsIgnoreCase("year")) newValue = Math.floor(newValue);
        targetInstrumentRunValue.setData(DataBuilder.buildInteger(Math.round(newValue)));
        break;
    }
  }
  /**
   * @param bufferWidth
   * @param bufferUnits
   * @param geometryUnits
   * @return the converted distance <code>bufferWidth</code> from <code>targetUnits</code> to <code>
   *     sourceUnits</code>
   */
  private double getBufferWidth(double bufferWidth, Unit sourceUnits, Unit targetUnits) {
    assert sourceUnits != null;
    assert targetUnits != null;

    double convertedWidth;
    if (GeoToolsUtils.PIXEL_UNITS.equals(targetUnits)) {

      IViewportModel viewportModel = this.sourceLayer.getMap().getViewportModel();
      Coordinate origin = viewportModel.pixelToWorld(0, 0);
      int fixedBufferWidth = (int) Math.round(bufferWidth);
      Coordinate originPlusWidth = viewportModel.pixelToWorld(fixedBufferWidth, fixedBufferWidth);
      convertedWidth = Math.abs(originPlusWidth.x - origin.x);
    } else {
      UnitConverter converter = targetUnits.getConverterTo(sourceUnits);
      convertedWidth = converter.convert(bufferWidth);
    }
    return convertedWidth;
  }