private static List<CurveDefinition> parseSingle(
CharSource resource,
Map<CurveName, LoadedCurveSettings> settingsMap) {
CsvFile csv = CsvFile.of(resource, true);
Map<CurveName, List<CurveNode>> allNodes = new HashMap<>();
for (CsvRow row : csv.rows()) {
String curveNameStr = row.getField(CURVE_NAME);
String label = row.getField(CURVE_LABEL);
String symbologyQuoteStr = row.getField(CURVE_SYMBOLOGY_QUOTE);
String tickerQuoteStr = row.getField(CURVE_TICKER_QUOTE);
String fieldQuoteStr = row.getField(CURVE_FIELD_QUOTE);
String typeStr = row.getField(CURVE_TYPE);
String conventionStr = row.getField(CURVE_CONVENTION);
String timeStr = row.getField(CURVE_TIME);
String dateStr = row.findField(CURVE_DATE).orElse("");
String minGapStr = row.findField(CURVE_MIN_GAP).orElse("");
String clashActionStr = row.findField(CURVE_CLASH_ACTION).orElse("");
String spreadStr = row.findField(CURVE_SPREAD).orElse("");
CurveName curveName = CurveName.of(curveNameStr);
StandardId quoteStandardId = StandardId.of(symbologyQuoteStr, tickerQuoteStr);
FieldName quoteField = fieldQuoteStr.isEmpty() ? FieldName.MARKET_VALUE : FieldName.of(fieldQuoteStr);
QuoteId quoteId = QuoteId.of(quoteStandardId, quoteField);
double spread = spreadStr.isEmpty() ? 0d : Double.parseDouble(spreadStr);
CurveNodeDate date = parseDate(dateStr);
CurveNodeDateOrder order = parseDateOrder(minGapStr, clashActionStr);
List<CurveNode> curveNodes = allNodes.computeIfAbsent(curveName, k -> new ArrayList<>());
curveNodes.add(createCurveNode(typeStr, conventionStr, timeStr, label, quoteId, spread, date, order));
}
return buildCurveDefinition(settingsMap, allNodes);
}