class AnnuityDefinitionBuilder {

  public static AnnuityCouponFixedDefinition couponFixedWithNotional(final Currency currency, final ZonedDateTime settlementDate, final ZonedDateTime maturityDate,
      final Period paymentPeriod, final Calendar calendar, final DayCount dayCount, final BusinessDayConvention businessDay, final boolean isEOM, final double notional,
      final double fixedRate, final boolean isPayer, final StubType stub, final int paymentLag, final boolean notionalStart, final boolean notionalEnd) {
    final AnnuityDefinition<CouponFixedDefinition> annuityNoNotional = couponFixed(currency, settlementDate, maturityDate, paymentPeriod, calendar, dayCount, businessDay,
        isEOM, notional, fixedRate, isPayer, stub, paymentLag);
    final double sign = (isPayer) ? -1.0 : 1.0;
    final int nbPay = annuityNoNotional.getNumberOfPayments();
    int nbNotional = 0;
    nbNotional = (notionalStart ? nbNotional + 1 : nbNotional);
    nbNotional = (notionalEnd ? nbNotional + 1 : nbNotional);
    final CouponFixedDefinition[] annuityWithNotional = new CouponFixedDefinition[nbPay + nbNotional];
    int loopnot = 0;
    if (notionalStart) {
      annuityWithNotional[0] = new CouponFixedDefinition(currency, settlementDate, settlementDate, settlementDate, 1.0, -notional * sign, 1);
      // Implementation note: Fixed amount written as a fixed coupon.
      loopnot++;
    }
    System.arraycopy(annuityNoNotional.getPayments(), 0, annuityWithNotional, loopnot, nbPay);
    if (notionalEnd) {
      final ZonedDateTime payDate = annuityNoNotional.getNthPayment(nbPay - 1).getPaymentDate();
      annuityWithNotional[nbPay + loopnot] = new CouponFixedDefinition(currency, payDate, payDate, payDate, 1.0, notional * sign, 1);
    }
    return new AnnuityCouponFixedDefinition(annuityWithNotional, calendar);
  }

}