/**
   * Validate the CDXRefData instance
   *
   * @return TRUE if successful
   */
  public boolean validate() {
    if (null == _strCurveID
        || _strCurveID.isEmpty()
        || null == _strSPN
        || _strSPN.isEmpty()
        || null == _strIndexLabel
        || _strIndexLabel.isEmpty()
        || null == _strIndexName
        || _strIndexName.isEmpty()
        || null == _strCurveName
        || _strCurveName.isEmpty()
        || null == _dtIssue
        || null == _dtMaturity
        || _dtIssue.getJulian() >= _dtMaturity.getJulian()
        || !org.drip.quant.common.NumberUtil.IsValid(_dblCoupon)
        || null == _strCurrency
        || _strCurrency.isEmpty()
        || null == _strDayCount
        || _strDayCount.isEmpty()
        || !org.drip.quant.common.NumberUtil.IsValid(_dblRecovery)
        || null == _strRedID
        || _strRedID.isEmpty()
        || null == _strIndexClass
        || _strIndexClass.isEmpty()
        || null == _strIndexGroupName
        || _strIndexGroupName.isEmpty()) return false;

    return true;
  }
  @Override
  public org.drip.analytics.date.JulianDate getMaturityDate() {
    org.drip.analytics.date.JulianDate dtFloatReferenceMaturity = _floatReference.getMaturityDate();

    org.drip.analytics.date.JulianDate dtFloatDerivedMaturity = _floatDerived.getMaturityDate();

    if (null == dtFloatReferenceMaturity || null == dtFloatDerivedMaturity) return null;

    return dtFloatReferenceMaturity.getJulian() > dtFloatDerivedMaturity.getJulian()
        ? dtFloatReferenceMaturity
        : dtFloatDerivedMaturity;
  }
  @Override
  public org.drip.analytics.date.JulianDate getEffectiveDate() {
    org.drip.analytics.date.JulianDate dtFloatReferenceEffective =
        _floatReference.getEffectiveDate();

    org.drip.analytics.date.JulianDate dtFloatDerivedEffective = _floatDerived.getEffectiveDate();

    if (null == dtFloatReferenceEffective || null == dtFloatDerivedEffective) return null;

    return dtFloatReferenceEffective.getJulian() < dtFloatDerivedEffective.getJulian()
        ? dtFloatReferenceEffective
        : dtFloatDerivedEffective;
  }
  @Override
  public org.drip.analytics.date.JulianDate getFirstCouponDate() {
    org.drip.analytics.date.JulianDate dtFloatReferenceFirstCoupon =
        _floatReference.getFirstCouponDate();

    org.drip.analytics.date.JulianDate dtFloatDerivedFirstCoupon =
        _floatDerived.getFirstCouponDate();

    if (null == dtFloatReferenceFirstCoupon || null == dtFloatDerivedFirstCoupon) return null;

    return dtFloatReferenceFirstCoupon.getJulian() < dtFloatDerivedFirstCoupon.getJulian()
        ? dtFloatReferenceFirstCoupon
        : dtFloatDerivedFirstCoupon;
  }
  /**
   * Return the maturity date of the basket product
   *
   * @return Maturity date of the basket product
   */
  public org.drip.analytics.date.JulianDate getMaturityDate() {
    org.drip.product.definition.Component[] aComp = getComponents();

    int iNumComp = aComp.length;

    org.drip.analytics.date.JulianDate dtMaturity = aComp[0].getMaturityDate();

    for (int i = 1; i < iNumComp; ++i) {
      org.drip.analytics.date.JulianDate dtCompMaturity = aComp[i].getMaturityDate();

      if (dtCompMaturity.getJulian() < dtMaturity.getJulian()) dtMaturity = dtCompMaturity;
    }

    return dtMaturity;
  }
  private static final void CreditCurveAPISample() throws Exception {
    JulianDate dtStart = JulianDate.Today();

    JulianDate dt10Y = dtStart.addYears(10);

    /*
     * Create Credit Curve from flat Hazard Rate
     */

    CreditCurve ccFlatHazard =
        CreditCurveBuilder.FromFlatHazard(dtStart.getJulian(), "CC", "USD", 0.02, 0.4);

    System.out.println(
        "CCFromFlatHazard["
            + dt10Y.toString()
            + "]; Survival="
            + ccFlatHazard.getSurvival("10Y")
            + "; Hazard="
            + ccFlatHazard.calcHazard("10Y"));

    double[] adblDate = new double[5];
    double[] adblSurvival = new double[5];

    for (int i = 0; i < 5; ++i) {
      adblDate[i] = dtStart.addYears(2 * i + 2).getJulian();

      adblSurvival[i] = 1. - 0.1 * (i + 1);
    }

    /*
     * Create Credit Curve from an array of dates and their corresponding survival probabilities
     */

    CreditCurve ccFromSurvival =
        CreditCurveBuilder.FromSurvival(
            dtStart.getJulian(), "CC", "USD", adblDate, adblSurvival, 0.4);

    System.out.println(
        "CCFromSurvival["
            + dt10Y.toString()
            + "]; Survival="
            + ccFromSurvival.getSurvival("10Y")
            + "; Hazard="
            + ccFromSurvival.calcHazard("10Y"));
  }
  /**
   * Constructs a Cash Component
   *
   * @param dtEffective Effective Date
   * @param dtMaturity Maturity Date
   * @param strIR IR Curve
   * @param strDC Day Count
   * @param strCalendar Calendar
   * @throws java.lang.Exception Thrown if the inputs are invalid
   */
  public CashComponent(
      final org.drip.analytics.date.JulianDate dtEffective,
      final org.drip.analytics.date.JulianDate dtMaturity,
      final java.lang.String strIR,
      final java.lang.String strDC,
      final java.lang.String strCalendar)
      throws java.lang.Exception {
    if (null == dtEffective
        || null == dtMaturity
        || null == (_strIR = strIR)
        || strIR.isEmpty()
        || (_dblMaturity = dtMaturity.getJulian()) <= (_dblEffective = dtEffective.getJulian()))
      throw new java.lang.Exception("CashComponent ctr: Invalid Inputs!");

    _strDC = strDC;
    _strCalendar = strCalendar;

    _notlSchedule = org.drip.product.params.FactorSchedule.CreateBulletSchedule();
  }
  /**
   * Get the first coupon date
   *
   * @return First Coupon Date
   */
  public org.drip.analytics.date.JulianDate getFirstCouponDate() {
    org.drip.product.definition.Component[] aComp = getComponents();

    int iNumComp = aComp.length;

    org.drip.analytics.date.JulianDate dtFirstCoupon = aComp[0].getFirstCouponDate();

    for (int i = 1; i < iNumComp; ++i) {
      if (dtFirstCoupon.getJulian() > aComp[i].getFirstCouponDate().getJulian())
        dtFirstCoupon = aComp[i].getFirstCouponDate();
    }

    return dtFirstCoupon;
  }
  /**
   * Return the stringified set of parameters in a java call that can be statically used to
   * re-construct the index.
   *
   * @return Set of Stringified parameters as a java call.
   */
  public java.lang.String setConstructionString() {
    java.lang.StringBuffer sb = new java.lang.StringBuffer();

    java.lang.String strCDXCode =
        _strIndexClass
            + "."
            + _strIndexGroupName
            + "."
            + _iIndexLifeSpan
            + "Y."
            + _iIndexSeries
            + "."
            + _iIndexVersion;

    sb.append(
        "\t\tUpdateCDXRefDataMap ("
            + org.drip.quant.common.StringUtil.MakeStringArg(strCDXCode)
            + ",\n\t\t\torg.drip.product.creator.CDXRefDataBuilder.CreateCDXRefDataBuilder (");

    sb.append(org.drip.quant.common.StringUtil.MakeStringArg(_strCurveID) + ", ");

    sb.append(org.drip.quant.common.StringUtil.MakeStringArg(_strSPN) + ",\n\t\t\t\t");

    sb.append(org.drip.quant.common.StringUtil.MakeStringArg(_strIndexLabel) + ", ");

    sb.append(org.drip.quant.common.StringUtil.MakeStringArg(_strIndexName) + ",\n\t\t\t\t\t");

    sb.append(org.drip.quant.common.StringUtil.MakeStringArg(_strCurveName) + ", ");

    sb.append(_dtIssue.getJulian() + ", ");

    sb.append(_dtMaturity.getJulian() + ", ");

    sb.append(_dblCoupon + ", ");

    sb.append(org.drip.quant.common.StringUtil.MakeStringArg(_strCurrency) + ",\n\t\t\t\t\t\t");

    sb.append(org.drip.quant.common.StringUtil.MakeStringArg(_strDayCount) + ", ");

    sb.append(_bFullFirstStub + ", ");

    sb.append(_dblRecovery + ", ");

    sb.append(_iFrequency + ", ");

    sb.append(org.drip.quant.common.StringUtil.MakeStringArg(_strRedID) + ", ");

    sb.append(org.drip.quant.common.StringUtil.MakeStringArg(_strIndexClass) + ", ");

    sb.append(_iIndexSeries + ", ");

    sb.append(org.drip.quant.common.StringUtil.MakeStringArg(_strIndexGroupName) + ", ");

    sb.append(org.drip.quant.common.StringUtil.MakeStringArg(_strIndexShortName) + ", ");

    sb.append(org.drip.quant.common.StringUtil.MakeStringArg(_strIndexShortGroupName) + ", ");

    sb.append(_iIndexVersion + ", ");

    sb.append(_iIndexLifeSpan + ",\n\t\t\t\t\t\t\t");

    sb.append(org.drip.quant.common.StringUtil.MakeStringArg(_strCurvyCurveID) + ", ");

    sb.append(_dblIndexFactor + ", ");

    sb.append(_iOriginalComponentCount + ", ");

    sb.append(_iDefaultedComponentCount + ", ");

    sb.append(org.drip.quant.common.StringUtil.MakeStringArg(_strLocation) + ", ");

    sb.append(_bPayAccrued + ", ");

    sb.append(_bKnockOutOnDefault + ", ");

    sb.append(_bQuoteAsCDS + ", ");

    sb.append(org.drip.quant.common.StringUtil.MakeStringArg(_strBBGTicker) + ", ");

    sb.append(org.drip.quant.common.StringUtil.MakeStringArg(_strShortName) + "));\n\n");

    return sb.toString();
  }
  private static final void CDSAPISample() throws Exception {
    JulianDate dtStart = JulianDate.Today();

    /*
     * Flat Discount Curve
     */

    DiscountCurve dc = DiscountCurveBuilder.CreateFromFlatRate(dtStart, "USD", 0.05);

    /*
     * Flat Credit Curve
     */

    CreditCurve cc = CreditCurveBuilder.FromFlatHazard(dtStart.getJulian(), "CC", "USD", 0.02, 0.4);

    /*
     * Component Market Parameters built from the Discount and the Credit Curves
     */

    ComponentMarketParams cmp = ComponentMarketParamsBuilder.MakeCreditCMP(dc, cc);

    /*
     * Create an SNAC CDS
     */

    CreditDefaultSwap cds = CDSBuilder.CreateSNAC(dtStart, "5Y", 0.1, "CC");

    /*
     * Valuation Parameters
     */

    ValuationParams valParams =
        ValuationParams.CreateValParams(dtStart, 0, "", Convention.DR_ACTUAL);

    /*
     * Standard Credit Pricer Parameters (check javadoc for details)
     */

    PricerParams pricerParams = PricerParams.MakeStdPricerParams();

    System.out.println(
        "Acc Start       Acc End     Pay Date    Index   Spread   Cpn DCF    Pay01    Surv01");

    System.out.println(
        "---------      ---------    ---------   ------  ------   -------- --------- --------");

    /*
     * CDS Coupon Cash Flow
     */

    for (CashflowPeriodCurveFactors p : cds.getCouponFlow(valParams, pricerParams, cmp))
      System.out.println(
          JulianDate.fromJulian(p.getAccrualStartDate())
              + FIELD_SEPARATOR
              + JulianDate.fromJulian(p.getAccrualEndDate())
              + FIELD_SEPARATOR
              + JulianDate.fromJulian(p.getPayDate())
              + FIELD_SEPARATOR
              + FormatUtil.FormatDouble(p.getIndexRate(), 1, 4, 1.)
              + FIELD_SEPARATOR
              + FormatUtil.FormatDouble(p.getSpread(), 1, 4, 1.)
              + FIELD_SEPARATOR
              + FormatUtil.FormatDouble(p.getCouponDCF(), 1, 4, 1.)
              + FIELD_SEPARATOR
              + FormatUtil.FormatDouble(dc.df(p.getPayDate()), 1, 4, 1.)
              + FIELD_SEPARATOR
              + FormatUtil.FormatDouble(cc.getSurvival(p.getPayDate()), 1, 4, 1.));

    System.out.println(
        "Loss Start     Loss End      Pay Date      Cpn    Notl     Rec    EffDF    StartSurv  EndSurv");

    System.out.println(
        "----------     --------      --------      ---    ----     ---    -----    ---------  -------");

    /*
     * CDS Loss Cash Flow
     */

    for (LossPeriodCurveFactors dp : cds.getLossFlow(valParams, pricerParams, cmp))
      System.out.println(
          JulianDate.fromJulian(dp.getStartDate())
              + FIELD_SEPARATOR
              + JulianDate.fromJulian(dp.getEndDate())
              + FIELD_SEPARATOR
              + JulianDate.fromJulian(dp.getPayDate())
              + FIELD_SEPARATOR
              + FormatUtil.FormatDouble(dp.getCouponDCF(), 1, 4, 1.)
              + FIELD_SEPARATOR
              + FormatUtil.FormatDouble(dp.effectiveNotional(), 1, 0, 1.)
              + FIELD_SEPARATOR
              + FormatUtil.FormatDouble(dp.effectiveRecovery(), 1, 2, 1.)
              + FIELD_SEPARATOR
              + FormatUtil.FormatDouble(dp.effectiveDF(), 1, 4, 1.)
              + FIELD_SEPARATOR
              + FormatUtil.FormatDouble(dp.startSurvival(), 1, 4, 1.)
              + FIELD_SEPARATOR
              + FormatUtil.FormatDouble(dp.endSurvival(), 1, 4, 1.));
  }