class CouponFixedFxResetDiscountingMethod {

  public MultipleCurrencyMulticurveSensitivity presentValueCurveSensitivity(final CouponFixedFxReset coupon, 
      final MulticurveProviderInterface multicurve) {
    Validate.notNull(coupon, "Coupon");
    Validate.notNull(multicurve, "multicurve");
    Currency ccyPayment = coupon.getCurrency();
    Currency ccyReference = coupon.getReferenceCurrency();
    double tp = coupon.getPaymentTime();
    double t0 = coupon.getFxDeliveryTime();
    double todayFxRate = multicurve.getFxRate(ccyReference, ccyPayment);
    double amount = coupon.paymentAmount(todayFxRate);
    double dfCcyPaymentAtPayment = multicurve.getDiscountFactor(ccyPayment, tp);
    double dfCcyReferenceAtDelivery = multicurve.getDiscountFactor(ccyReference, t0);
    double dfCcyPaymentAtDelivery = multicurve.getDiscountFactor(ccyPayment, t0);
    // Backward sweep.
    double pvBar = 1.0;
    double dfCcyPaymentAtDeliveryBar = -amount * 
        dfCcyPaymentAtPayment * dfCcyReferenceAtDelivery / (dfCcyPaymentAtDelivery * dfCcyPaymentAtDelivery) * pvBar;
    double dfCcyReferenceAtDeliveryBar = amount * dfCcyPaymentAtPayment  / dfCcyPaymentAtDelivery * pvBar;
    double dfCcyPaymentAtPaymentBar = amount * dfCcyReferenceAtDelivery / dfCcyPaymentAtDelivery * pvBar;
    MultipleCurrencyMulticurveSensitivity result = new MultipleCurrencyMulticurveSensitivity();
    final Map<String, List<DoublesPair>> mapDscCcyPayment = new HashMap<>();
    final List<DoublesPair> listDscCcyPayment = new ArrayList<>();
    listDscCcyPayment.add(DoublesPair.of(t0, -t0 * dfCcyPaymentAtDelivery * dfCcyPaymentAtDeliveryBar));
    listDscCcyPayment.add(DoublesPair.of(tp, -tp * dfCcyPaymentAtPayment * dfCcyPaymentAtPaymentBar));
    mapDscCcyPayment.put(multicurve.getName(ccyPayment), listDscCcyPayment);
    result = result.plus(ccyPayment, MulticurveSensitivity.ofYieldDiscounting(mapDscCcyPayment));
    final Map<String, List<DoublesPair>> mapDscCcyReference = new HashMap<>();
    final List<DoublesPair> listDscCcyReference = new ArrayList<>();
    listDscCcyReference.add(DoublesPair.of(t0, -t0 * dfCcyReferenceAtDelivery * dfCcyReferenceAtDeliveryBar));
    mapDscCcyReference.put(multicurve.getName(ccyReference), listDscCcyReference);
    result = result.plus(ccyPayment, MulticurveSensitivity.ofYieldDiscounting(mapDscCcyReference));
    return result;
  }

  private  CouponFixedFxResetDiscountingMethod();

}