//-------------------------------------------------------------------------
        // constructs an interpolated nodal curve
        internal InterpolatedNodalCurve createCurve(LocalDate date, IList <LoadedCurveNode> curveNodes)
        {
            // copy and sort
            IList <LoadedCurveNode> nodes = new List <LoadedCurveNode>(curveNodes);

            nodes.sort(System.Collections.IComparer.naturalOrder());

            // build each node
            double[] xValues = new double[nodes.Count];
            double[] yValues = new double[nodes.Count];
            IList <ParameterMetadata> pointsMetadata = new List <ParameterMetadata>(nodes.Count);

            for (int i = 0; i < nodes.Count; i++)
            {
                LoadedCurveNode point        = nodes[i];
                double          yearFraction = dayCount.yearFraction(date, point.Date);
                xValues[i] = yearFraction;
                yValues[i] = point.Value;
                ParameterMetadata pointMetadata = LabelDateParameterMetadata.of(point.Date, point.Label);
                pointsMetadata.Add(pointMetadata);
            }

            // create metadata
            CurveMetadata curveMetadata = DefaultCurveMetadata.builder().curveName(curveName).xValueType(xValueType).yValueType(yValueType).dayCount(dayCount).parameterMetadata(pointsMetadata).build();

            return(InterpolatedNodalCurve.builder().metadata(curveMetadata).xValues(DoubleArray.copyOf(xValues)).yValues(DoubleArray.copyOf(yValues)).interpolator(interpolator).extrapolatorLeft(extrapolatorLeft).extrapolatorRight(extrapolatorRight).build());
        }
        private static Multimap <LocalDate, Curve> parseSingle(System.Predicate <LocalDate> datePredicate, CharSource curvesResource, IDictionary <CurveName, LoadedCurveSettings> settingsMap)
        {
            CsvFile csv = CsvFile.of(curvesResource, true);
            IDictionary <LoadedCurveKey, IList <LoadedCurveNode> > allNodes = new Dictionary <LoadedCurveKey, IList <LoadedCurveNode> >();

            foreach (CsvRow row in csv.rows())
            {
                string dateStr       = row.getField(CURVE_DATE);
                string curveNameStr  = row.getField(CURVE_NAME);
                string pointDateStr  = row.getField(CURVE_POINT_DATE);
                string pointValueStr = row.getField(CURVE_POINT_VALUE);
                string pointLabel    = row.getField(CURVE_POINT_LABEL);

                LocalDate date = LoaderUtils.parseDate(dateStr);
                if (datePredicate(date))
                {
                    LocalDate pointDate  = LoaderUtils.parseDate(pointDateStr);
                    double    pointValue = Convert.ToDouble(pointValueStr);

                    LoadedCurveKey          key        = LoadedCurveKey.of(date, CurveName.of(curveNameStr));
                    IList <LoadedCurveNode> curveNodes = allNodes.computeIfAbsent(key, k => new List <LoadedCurveNode>());
                    curveNodes.Add(LoadedCurveNode.of(pointDate, pointValue, pointLabel));
                }
            }
            return(buildCurves(settingsMap, allNodes));
        }
        //-------------------------------------------------------------------------
        public virtual void coverage()
        {
            coverPrivateConstructor(typeof(RatesCurvesCsvLoader));
            LoadedCurveKey.meta();
            coverImmutableBean(LoadedCurveKey.of(CURVE_DATE, CurveName.of("Test")));
            LoadedCurveNode.meta();
            coverImmutableBean(LoadedCurveNode.of(CURVE_DATE, 1d, "Test"));
            LoadedCurveSettings.meta();
            LoadedCurveSettings settings1 = LoadedCurveSettings.of(CurveName.of("Test"), ValueType.YEAR_FRACTION, ValueType.ZERO_RATE, DayCounts.ACT_365F, CurveInterpolators.LINEAR, CurveExtrapolators.FLAT, CurveExtrapolators.FLAT);
            LoadedCurveSettings settings2 = LoadedCurveSettings.of(CurveName.of("Test2"), ValueType.YEAR_FRACTION, ValueType.DISCOUNT_FACTOR, DayCounts.ACT_ACT_ISDA, CurveInterpolators.LOG_LINEAR, CurveExtrapolators.LINEAR, CurveExtrapolators.LINEAR);

            coverImmutableBean(settings1);
            coverBeanEquals(settings1, settings2);
        }