class DiscountingFixedCouponBondProductPricer {

  public double dirtyPriceFromYield(ResolvedFixedCouponBond bond, LocalDate settlementDate, double yield) {
    ImmutableList<FixedCouponBondPaymentPeriod> payments = bond.getPeriodicPayments();
    int nCoupon = payments.size() - couponIndex(payments, settlementDate);
    FixedCouponBondYieldConvention yieldConv = bond.getYieldConvention();
    if (nCoupon == 1) {
      if (yieldConv.equals(US_STREET) || yieldConv.equals(DE_BONDS)) {
        FixedCouponBondPaymentPeriod payment = payments.get(payments.size() - 1);
        return (1d + payment.getFixedRate() * payment.getYearFraction()) /
            (1d + factorToNextCoupon(bond, settlementDate) * yield /
                ((double) bond.getFrequency().eventsPerYear()));
      }
    }
    if ((yieldConv.equals(US_STREET)) || (yieldConv.equals(GB_BUMP_DMO)) || (yieldConv.equals(DE_BONDS))) {
      return dirtyPriceFromYieldStandard(bond, settlementDate, yield);
    }
    if (yieldConv.equals(JP_SIMPLE)) {
      LocalDate maturityDate = bond.getUnadjustedEndDate();
      if (settlementDate.isAfter(maturityDate)) {
        return 0d;
      }
      double maturity = bond.getDayCount().relativeYearFraction(settlementDate, maturityDate);
      double cleanPrice = (1d + bond.getFixedRate() * maturity) / (1d + yield * maturity);
      return dirtyPriceFromCleanPrice(bond, settlementDate, cleanPrice);
    }
    throw new UnsupportedOperationException("The convention " + yieldConv.name() + " is not supported.");
  }

  public  DiscountingFixedCouponBondProductPricer(
      DiscountingFixedCouponBondPaymentPeriodPricer periodPricer,
      DiscountingPaymentPricer nominalPricer);

}