class ZSpreadCalculator {

  public Map<String, List<DoublesPair>> calculateZSpreadSensitivityToCurve(final Annuity<? extends Payment> annuity, final YieldCurveBundle curves, final double zSpread) {
    ArgumentChecker.notNull(annuity, "annuity");
    ArgumentChecker.notNull(curves, "curves");

    final double dPricedZ = calculatePriceSensitivityToZSpread(annuity, curves, zSpread);
    ArgumentChecker.isTrue(Double.doubleToLongBits(dPricedZ) != 0, "Price Sensitivity To ZSpread is zero");

    final Map<String, List<DoublesPair>> temp = annuity.accept(PV_SENSITIVITY_CALCULATOR, curves);
    final Map<String, List<DoublesPair>> result = new HashMap<>();
    for (final Map.Entry<String, List<DoublesPair>> entry : temp.entrySet()) {
      final List<DoublesPair> unadjusted = entry.getValue();
      final ArrayList<DoublesPair> adjusted = new ArrayList<>(unadjusted.size());
      for (final DoublesPair pair : unadjusted) {
        final DoublesPair newPair = DoublesPair.of(pair.first, -pair.second * Math.exp(-zSpread * pair.first) / dPricedZ);
        adjusted.add(newPair);
      }
      result.put(entry.getKey(), adjusted);
    }
    return result;
  }

  private  ZSpreadCalculator();

}