// parses the properties file format private static PropertySet parse(ImmutableList <string> lines) { // cannot use ArrayListMultiMap as it does not retain the order of the keys // whereas ImmutableListMultimap does retain the order of the keys ImmutableListMultimap.Builder <string, string> parsed = ImmutableListMultimap.builder(); int lineNum = 0; foreach (string line in lines) { lineNum++; line = line.Trim(); if (line.Length == 0 || line.StartsWith("#", StringComparison.Ordinal) || line.StartsWith(";", StringComparison.Ordinal)) { continue; } int equalsPosition = line.IndexOf(" = ", StringComparison.Ordinal); equalsPosition = equalsPosition < 0 ? line.IndexOf('=') : equalsPosition + 1; string key = (equalsPosition < 0 ? line.Trim() : line.Substring(0, equalsPosition).Trim()); string value = (equalsPosition < 0 ? "" : line.Substring(equalsPosition + 1).Trim()); if (key.Length == 0) { throw new System.ArgumentException("Invalid properties file, empty key, line " + lineNum); } parsed.put(key, value); } return(PropertySet.of(parsed.build())); }
//------------------------------------------------------------------------- /// <summary> /// Overrides this property set with another. /// <para> /// The specified property set takes precedence. /// The order of any existing keys will be retained, with the value replaced. /// Any order of any additional keys will be retained, with those keys located after the base set of keys. /// /// </para> /// </summary> /// <param name="other"> the other property set </param> /// <returns> the combined property set </returns> public PropertySet overrideWith(PropertySet other) { ArgChecker.notNull(other, "other"); if (other.Empty) { return(this); } if (Empty) { return(other); } // cannot use ArrayListMultiMap as it does not retain the order of the keys // whereas ImmutableListMultimap does retain the order of the keys ImmutableListMultimap.Builder <string, string> map = ImmutableListMultimap.builder(); foreach (string key in this.keyValueMap.Keys) { if (other.contains(key)) { map.putAll(key, other.valueList(key)); } else { map.putAll(key, this.valueList(key)); } } foreach (string key in other.keyValueMap.Keys) { if (!this.contains(key)) { map.putAll(key, other.valueList(key)); } } return(new PropertySet(map.build())); }
public virtual void test_ofChained_chainToNowhere() { IniFile test = ResourceConfig.combinedIniFile("TestChain3.ini"); Multimap <string, string> keyValues1 = ImmutableListMultimap.of("a", "x", "b", "y"); assertEquals(test.asMap(), ImmutableMap.of("one", PropertySet.of(keyValues1))); }
public virtual void test_ofChained_autoChain() { IniFile test = ResourceConfig.combinedIniFile("TestChain4.ini"); Multimap <string, string> keyValues1 = ImmutableListMultimap.of("a", "z", "b", "y"); Multimap <string, string> keyValues2 = ImmutableListMultimap.of("m", "n"); assertEquals(test.asMap(), ImmutableMap.of("one", PropertySet.of(keyValues1), "two", PropertySet.of(keyValues2))); }
//------------------------------------------------------------------------- public virtual void toListMultimap() { IDictionary <string, int> map = ImmutableMap.of("a", 1, "aa", 2, "b", 10, "bb", 20, "c", 1); ListMultimap <string, int> expected = ImmutableListMultimap.of("a", 1, "a", 2, "b", 10, "b", 20, "c", 1); ListMultimap <string, int> result = MapStream.of(map).mapKeys(s => s.substring(0, 1)).toListMultimap(); assertThat(result).isEqualTo(expected); }
//------------------------------------------------------------------------- public virtual void test_combinedWith() { PropertySet @base = PropertySet.of(ImmutableListMultimap.of("a", "x", "a", "y", "c", "z")); PropertySet other = PropertySet.of(ImmutableListMultimap.of("a", "aa", "b", "bb", "d", "dd")); PropertySet expected = PropertySet.of(ImmutableListMultimap.of("a", "x", "a", "y", "c", "z", "b", "bb", "d", "dd")); assertEquals(@base.combinedWith(other), expected); }
//------------------------------------------------------------------------- public virtual void test_overrideWith() { PropertySet @base = PropertySet.of(ImmutableListMultimap.of("a", "x", "a", "y", "b", "y", "c", "z")); PropertySet other = PropertySet.of(ImmutableListMultimap.of("a", "aa", "c", "cc", "d", "dd", "e", "ee")); PropertySet expected = PropertySet.of(ImmutableListMultimap.of("a", "aa", "b", "y", "c", "cc", "d", "dd", "e", "ee")); assertEquals(@base.overrideWith(other), expected); }
//------------------------------------------------------------------------- /// <summary> /// Creates an instance, based on the specified element. /// <para> /// The map of references is used to link one part of the XML to another. /// For example, if one part of the XML has {@code <foo id="fooId">}, the references /// map will contain an entry mapping "fooId" to the parsed element {@code <foo>}. /// /// </para> /// </summary> /// <param name="fpmlRootEl"> the source of the FpML XML document </param> /// <param name="references"> the map of id/href to referenced element </param> /// <param name="ourPartySelector"> the selector used to find "our" party within the set of parties in the FpML document </param> /// <param name="tradeInfoParser"> the trade info parser </param> /// <param name="refData"> the reference data to use </param> public FpmlDocument(XmlElement fpmlRootEl, IDictionary <string, XmlElement> references, FpmlPartySelector ourPartySelector, FpmlTradeInfoParserPlugin tradeInfoParser, ReferenceData refData) { this.fpmlRoot = fpmlRootEl; this.references = ImmutableMap.copyOf(references); this.parties = parseParties(fpmlRootEl); this.ourPartyHrefIds = findOurParty(ourPartySelector); this.tradeInfoParser = tradeInfoParser; this.refData = refData; }
public virtual void test_toImmutableListMultimap_keyValue() { IList <string> list = Arrays.asList("a", "ab", "b", "bb", "c", "a"); //JAVA TO C# CONVERTER TODO TASK: Most Java stream collectors are not converted by Java to C# Converter: ImmutableListMultimap <int, string> test = list.collect(Guavate.toImmutableListMultimap(s => s.length(), s => "!" + s)); ImmutableListMultimap <object, object> expected = ImmutableListMultimap.builder().put(1, "!a").put(2, "!ab").put(1, "!b").put(2, "!bb").put(1, "!c").put(1, "!a").build(); assertEquals(test, expected); }
/// <summary> /// Obtains an instance from a map. /// <para> /// The returned instance will have one value for each key. /// /// </para> /// </summary> /// <param name="keyValues"> the key-values to create the instance with </param> /// <returns> the property set </returns> public static PropertySet of(IDictionary <string, string> keyValues) { ArgChecker.notNull(keyValues, "keyValues"); ImmutableListMultimap.Builder <string, string> builder = ImmutableListMultimap.builder(); foreach (KeyValuePair <string, string> entry in keyValues.SetOfKeyValuePairs()) { builder.put(entry); } return(new PropertySet(builder.build())); }
public virtual void test_load() { ImmutableListMultimap <LocalDate, LegalEntityCurveGroup> allCurves = LegalEntityRatesCurvesCsvLoader.loadAllDates(ResourceLocator.of(GROUPS), ResourceLocator.of(SETTINGS), ImmutableList.of(ResourceLocator.of(CURVES_1), ResourceLocator.of(CURVES_2))); foreach (LocalDate date in ALL_DATES) { ImmutableList <LegalEntityCurveGroup> oneDayCurves = LegalEntityRatesCurvesCsvLoader.load(date, ResourceLocator.of(GROUPS), ResourceLocator.of(SETTINGS), ImmutableList.of(ResourceLocator.of(CURVES_1), ResourceLocator.of(CURVES_2))); assertEquals(oneDayCurves, allCurves.get(date)); } }
// parse all the root-level party elements private static ImmutableListMultimap <string, string> parseParties(XmlElement root) { ListMultimap <string, string> parties = ArrayListMultimap.create(); foreach (XmlElement child in root.getChildren("party")) { parties.putAll(child.getAttribute(ID), findPartyIds(child)); } return(ImmutableListMultimap.copyOf(parties)); }
public virtual void test_loadAllDates() { LocalDate sampleDate = ALL_DATES[3]; // 2017-04-21 ImmutableList <LocalDate> expDates = ImmutableList.of(LocalDate.of(2017, 0x7, 21), LocalDate.of(2017, 10, 0x7), LocalDate.of(2018, 4, 13), LocalDate.of(2019, 4, 12), LocalDate.of(2020, 3, 20), LocalDate.of(2021, 3, 19), LocalDate.of(2022, 3, 19), LocalDate.of(2023, 3, 17), LocalDate.of(2024, 6, 17), LocalDate.of(2025, 3, 18), LocalDate.of(2026, 3, 20), LocalDate.of(2027, 3, 20), LocalDate.of(2031, 12, 19), LocalDate.of(2037, 3, 17), LocalDate.of(2047, 3, 17), LocalDate.of(2056, 3, 17)); ImmutableList <string> expTenors = ImmutableList.of("3M", "6M", "1Y", "2Y", "3Y", "4Y", "5Y", "6Y", "7Y", "8Y", "9Y", "10Y", "15Y", "20Y", "30Y", "40Y"); RepoGroup repoGroup = RepoGroup.of("JP-REPO"); DoubleArray expRepoXValues = DoubleArray.of(3, n => ACT_365F.relativeYearFraction(sampleDate, expDates.get(n))); DoubleArray expRepoYValues = DoubleArray.of(-0.0019521, -0.0016021, -0.0022521); ImmutableList <LabelDateParameterMetadata> expRepoMetadata = IntStream.range(0, 3).mapToObj(n => LabelDateParameterMetadata.of(expDates.get(n), expTenors.get(n))).collect(Guavate.toImmutableList()); LegalEntityGroup legalEntityGroup = LegalEntityGroup.of("JP-GOVT"); DoubleArray expIssuerXValues = DoubleArray.of(expDates.size(), n => ACT_365F.relativeYearFraction(sampleDate, expDates.get(n))); DoubleArray expIssuerYValues = DoubleArray.of(-0.0019511690511744527, -0.001497422302092893, -0.0021798583657932176, -0.002215700360912938, -0.0021722324679574866, -0.001922059591219172, -0.0015461646763548528, -0.0014835851245462084, -0.001118669580570464, -5.476767138782941E-4, -2.2155596172855965E-4, 2.0333291172821893E-5, 0.00284500423293463, 0.005876533417933958, 0.007957581583531789, 0.009134630405512047); ImmutableList <LabelDateParameterMetadata> expIssuerMetadata = IntStream.range(0, expDates.size()).mapToObj(n => LabelDateParameterMetadata.of(expDates.get(n), expTenors.get(n))).collect(Guavate.toImmutableList()); ImmutableListMultimap <LocalDate, LegalEntityCurveGroup> allCurves = LegalEntityRatesCurvesCsvLoader.loadAllDates(ResourceLocator.of(GROUPS), ResourceLocator.of(SETTINGS), ImmutableList.of(ResourceLocator.of(CURVES_1), ResourceLocator.of(CURVES_2))); //JAVA TO C# CONVERTER TODO TASK: There is no .NET equivalent to the java.util.Collection 'containsAll' method: assertTrue(allCurves.Keys.containsAll(ALL_DATES)); ImmutableList <LegalEntityCurveGroup> groups = allCurves.get(sampleDate); assertEquals(groups.size(), 2); // group 0 LegalEntityCurveGroup group0 = groups.get(0); assertEquals(group0.Name, CurveGroupName.of("Default1")); // repo assertEquals(group0.RepoCurves.size(), 1); Curve repoCurve = group0.RepoCurves.get(Pair.of(repoGroup, JPY)); InterpolatedNodalCurve expectedRepoCurve = InterpolatedNodalCurve.of(Curves.zeroRates(CurveName.of("JP-REPO-1"), ACT_365F, expRepoMetadata), expRepoXValues, expRepoYValues, CurveInterpolators.LINEAR, CurveExtrapolators.FLAT, CurveExtrapolators.FLAT); assertEquals(repoCurve, expectedRepoCurve); // issuer assertEquals(group0.IssuerCurves.size(), 2); Curve issuerCurve = group0.IssuerCurves.get(Pair.of(legalEntityGroup, JPY)); InterpolatedNodalCurve expectedIssuerCurve = InterpolatedNodalCurve.of(Curves.zeroRates(CurveName.of("JP-GOVT-1"), ACT_365F, expIssuerMetadata), expIssuerXValues, expIssuerYValues, CurveInterpolators.LINEAR, CurveExtrapolators.FLAT, CurveExtrapolators.FLAT); assertEquals(issuerCurve, expectedIssuerCurve); Curve usIssuerCurve = group0.IssuerCurves.get(Pair.of(LegalEntityGroup.of("US-GOVT"), USD)); expectedIssuerCurve = InterpolatedNodalCurve.of(Curves.zeroRates(CurveName.of("US-GOVT"), ACT_360, expIssuerMetadata), DoubleArray.of(expDates.size(), n => ACT_360.relativeYearFraction(sampleDate, expDates.get(n))), expIssuerYValues, CurveInterpolators.NATURAL_SPLINE, CurveExtrapolators.FLAT, CurveExtrapolators.FLAT); assertEquals(usIssuerCurve, expectedIssuerCurve); // group 1 LegalEntityCurveGroup group1 = groups.get(1); assertEquals(group1.Name, CurveGroupName.of("Default2")); // repo repoCurve = group1.RepoCurves.get(Pair.of(repoGroup, JPY)); expectedRepoCurve = InterpolatedNodalCurve.of(Curves.zeroRates(CurveName.of("JP-REPO-2"), ACT_365F, expRepoMetadata), expRepoXValues, expRepoYValues, CurveInterpolators.DOUBLE_QUADRATIC, CurveExtrapolators.LINEAR, CurveExtrapolators.LINEAR); assertEquals(repoCurve, expectedRepoCurve); // issuer assertEquals(group1.IssuerCurves.size(), 1); issuerCurve = group1.IssuerCurves.get(Pair.of(legalEntityGroup, JPY)); expectedIssuerCurve = InterpolatedNodalCurve.of(Curves.zeroRates(CurveName.of("JP-GOVT-2"), ACT_365F, expIssuerMetadata), expIssuerXValues, expIssuerYValues, CurveInterpolators.DOUBLE_QUADRATIC, CurveExtrapolators.LINEAR, CurveExtrapolators.LINEAR); assertEquals(issuerCurve, expectedIssuerCurve); }
//------------------------------------------------------------------------- /// <summary> /// Parses one or more CSV format position files, returning sensitivities. /// <para> /// The standard way to write sensitivities files is for each file to contain one sensitivity instance. /// The file format can handle multiple instances per file, where each instance has a separate identifier. /// Most files will not have the identifier columns, thus the identifier will be the empty string. /// </para> /// <para> /// The returned multimap is keyed by identifier. The value will contain one entry for each instance. /// If desired, the results can be reduced using <seealso cref="CurveSensitivities#mergedWith(CurveSensitivities)"/> /// to merge those with the same identifier. /// </para> /// <para> /// CSV files sometimes contain a Unicode Byte Order Mark. /// Callers are responsible for handling this, such as by using <seealso cref="UnicodeBom"/>. /// /// </para> /// </summary> /// <param name="charSources"> the CSV character sources </param> /// <returns> the loaded sensitivities, parsing errors are captured in the result </returns> public ValueWithFailures <ListMultimap <string, CurveSensitivities> > parse(ICollection <CharSource> charSources) { ListMultimap <string, CurveSensitivities> parsed = ArrayListMultimap.create(); IList <FailureItem> failures = new List <FailureItem>(); foreach (CharSource charSource in charSources) { parse(charSource, parsed, failures); } return(ValueWithFailures.of(ImmutableListMultimap.copyOf(parsed), failures)); }
//------------------------------------------------------------------------- /// <summary> /// Parses one or more CSV format curve files for all available dates. /// <para> /// A predicate is specified that is used to filter the dates that are returned. /// This could match a single date, a set of dates or all dates. /// </para> /// <para> /// If the files contain a duplicate entry an exception will be thrown. /// /// </para> /// </summary> /// <param name="datePredicate"> the predicate used to select the dates </param> /// <param name="groupsCharSource"> the curve groups CSV character source </param> /// <param name="settingsCharSource"> the curve settings CSV character source </param> /// <param name="curveValueCharSources"> the CSV character sources for curves </param> /// <returns> the loaded curves, mapped by date and identifier </returns> /// <exception cref="IllegalArgumentException"> if the files contain a duplicate entry </exception> public static ImmutableListMultimap <LocalDate, RatesCurveGroup> parse(System.Predicate <LocalDate> datePredicate, CharSource groupsCharSource, CharSource settingsCharSource, ICollection <CharSource> curveValueCharSources) { IList <RatesCurveGroupDefinition> curveGroups = RatesCurveGroupDefinitionCsvLoader.parseCurveGroupDefinitions(groupsCharSource); IDictionary <LocalDate, IDictionary <CurveName, Curve> > curves = parseCurves(datePredicate, settingsCharSource, curveValueCharSources); ImmutableListMultimap.Builder <LocalDate, RatesCurveGroup> builder = ImmutableListMultimap.builder(); foreach (RatesCurveGroupDefinition groupDefinition in curveGroups) { foreach (KeyValuePair <LocalDate, IDictionary <CurveName, Curve> > entry in curves.SetOfKeyValuePairs()) { RatesCurveGroup curveGroup = RatesCurveGroup.ofCurves(groupDefinition, entry.Value.values()); builder.put(entry.Key, curveGroup); } } return(builder.build()); }
//------------------------------------------------------------------------- // parses the INI file format private static ImmutableMap <string, ImmutableListMultimap <string, string> > parse(ImmutableList <string> lines) { // cannot use ArrayListMultiMap as it does not retain the order of the keys // whereas ImmutableListMultimap does retain the order of the keys IDictionary <string, ImmutableListMultimap.Builder <string, string> > ini = new LinkedHashMap <string, ImmutableListMultimap.Builder <string, string> >(); ImmutableListMultimap.Builder <string, string> currentSection = null; int lineNum = 0; foreach (string line in lines) { lineNum++; line = line.Trim(); if (line.Length == 0 || line.StartsWith("#", StringComparison.Ordinal) || line.StartsWith(";", StringComparison.Ordinal)) { continue; } if (line.StartsWith("[", StringComparison.Ordinal) && line.EndsWith("]", StringComparison.Ordinal)) { string sectionName = line.Substring(1, (line.Length - 1) - 1).Trim(); if (ini.ContainsKey(sectionName)) { throw new System.ArgumentException("Invalid INI file, duplicate section not allowed, line " + lineNum); } currentSection = ImmutableListMultimap.builder(); ini[sectionName] = currentSection; } else if (currentSection == null) { throw new System.ArgumentException("Invalid INI file, properties must be within a [section], line " + lineNum); } else { int equalsPosition = line.IndexOf(" = ", StringComparison.Ordinal); equalsPosition = equalsPosition < 0 ? line.IndexOf('=') : equalsPosition + 1; string key = (equalsPosition < 0 ? line.Trim() : line.Substring(0, equalsPosition).Trim()); string value = (equalsPosition < 0 ? "" : line.Substring(equalsPosition + 1).Trim()); if (key.Length == 0) { throw new System.ArgumentException("Invalid INI file, empty key, line " + lineNum); } currentSection.put(key, value); } } return(MapStream.of(ini).mapValues(b => b.build()).toMap()); }
public virtual void test_of_multimap() { Multimap <string, string> keyValues = ImmutableMultimap.of("a", "x", "a", "y", "b", "z"); PropertySet test = PropertySet.of(keyValues); assertEquals(test.Empty, false); assertEquals(test.contains("a"), true); assertThrowsIllegalArg(() => test.value("a")); assertEquals(test.valueList("a"), ImmutableList.of("x", "y")); assertEquals(test.contains("b"), true); assertEquals(test.value("b"), "z"); assertEquals(test.valueList("b"), ImmutableList.of("z")); assertEquals(test.contains("c"), false); assertEquals(test.keys(), ImmutableSet.of("a", "b")); assertEquals(test.asMultimap(), ImmutableListMultimap.of("a", "x", "a", "y", "b", "z")); assertEquals(test.valueList("unknown"), ImmutableSet.of()); assertThrowsIllegalArg(() => test.asMap()); assertThrowsIllegalArg(() => test.value("unknown")); assertEquals(test.ToString(), "{a=[x, y], b=[z]}"); }
/// <summary>Return a manifest of what finalized edit logs are available.</summary> /// <remarks> /// Return a manifest of what finalized edit logs are available. All available /// edit logs are returned starting from the transaction id passed. If /// 'fromTxId' falls in the middle of a log, that log is returned as well. /// </remarks> /// <param name="fromTxId">Starting transaction id to read the logs.</param> /// <returns>RemoteEditLogManifest object.</returns> public virtual RemoteEditLogManifest GetEditLogManifest(long fromTxId) { lock (this) { // Collect RemoteEditLogs available from each FileJournalManager IList <RemoteEditLog> allLogs = Lists.NewArrayList(); foreach (JournalSet.JournalAndStream j in journals) { if (j.GetManager() is FileJournalManager) { FileJournalManager fjm = (FileJournalManager)j.GetManager(); try { Sharpen.Collections.AddAll(allLogs, fjm.GetRemoteEditLogs(fromTxId, false)); } catch (Exception t) { Log.Warn("Cannot list edit logs in " + fjm, t); } } } // Group logs by their starting txid ImmutableListMultimap <long, RemoteEditLog> logsByStartTxId = Multimaps.Index(allLogs , RemoteEditLog.GetStartTxid); long curStartTxId = fromTxId; IList <RemoteEditLog> logs = Lists.NewArrayList(); while (true) { ImmutableList <RemoteEditLog> logGroup = ((ImmutableList <RemoteEditLog>)logsByStartTxId .Get(curStartTxId)); if (logGroup.IsEmpty()) { // we have a gap in logs - for example because we recovered some old // storage directory with ancient logs. Clear out any logs we've // accumulated so far, and then skip to the next segment of logs // after the gap. ICollection <long> startTxIds = Sets.NewTreeSet(logsByStartTxId.KeySet()); startTxIds = startTxIds.TailSet(curStartTxId); if (startTxIds.IsEmpty()) { break; } else { if (Log.IsDebugEnabled()) { Log.Debug("Found gap in logs at " + curStartTxId + ": " + "not returning previous logs in manifest." ); } logs.Clear(); curStartTxId = startTxIds.First(); continue; } } // Find the one that extends the farthest forward RemoteEditLog bestLog = Sharpen.Collections.Max(logGroup); logs.AddItem(bestLog); // And then start looking from after that point curStartTxId = bestLog.GetEndTxId() + 1; } RemoteEditLogManifest ret = new RemoteEditLogManifest(logs); if (Log.IsDebugEnabled()) { Log.Debug("Generated manifest for logs since " + fromTxId + ":" + ret); } return(ret); } }
public virtual void test_overrideWith_emptyOther() { PropertySet @base = PropertySet.of(ImmutableListMultimap.of("a", "x", "a", "y", "b", "y", "c", "z")); assertEquals(PropertySet.empty().overrideWith(@base), @base); }
public virtual void test_combinedWith_emptyBase() { PropertySet @base = PropertySet.of(ImmutableListMultimap.of("a", "x", "a", "y", "b", "y", "c", "z")); assertEquals(@base.combinedWith(PropertySet.empty()), @base); }
//------------------------------------------------------------------------- /// <summary> /// Restricted constructor. /// </summary> /// <param name="keyValues"> the key-value pairs </param> private PropertySet(ImmutableListMultimap <string, string> keyValues) { this.keyValueMap = keyValues; }
/// <summary> /// Obtains an instance from a map allowing for multiple values for each key. /// <para> /// The returned instance may have more than one value for each key. /// /// </para> /// </summary> /// <param name="keyValues"> the key-values to create the instance with </param> /// <returns> the property set </returns> public static PropertySet of(Multimap <string, string> keyValues) { ArgChecker.notNull(keyValues, "keyValues"); return(new PropertySet(ImmutableListMultimap.copyOf(keyValues))); }
/// <summary> /// Parses one or more CSV format curve files for all available dates. /// <para> /// A predicate is specified that is used to filter the dates that are returned. /// This could match a single date, a set of dates or all dates. /// </para> /// <para> /// If the files contain a duplicate entry an exception will be thrown. /// /// </para> /// </summary> /// <param name="datePredicate"> the predicate used to select the dates </param> /// <param name="groupsCharSource"> the curve groups CSV character source </param> /// <param name="settingsCharSource"> the curve settings CSV character source </param> /// <param name="curveValueCharSources"> the CSV character sources for curves </param> /// <returns> the loaded curves, mapped by date and identifier </returns> /// <exception cref="IllegalArgumentException"> if the files contain a duplicate entry </exception> public static ImmutableListMultimap <LocalDate, LegalEntityCurveGroup> parse(System.Predicate <LocalDate> datePredicate, CharSource groupsCharSource, CharSource settingsCharSource, ICollection <CharSource> curveValueCharSources) { IDictionary <CurveGroupName, IDictionary <Pair <RepoGroup, Currency>, CurveName> > repoGroups = new LinkedHashMap <CurveGroupName, IDictionary <Pair <RepoGroup, Currency>, CurveName> >(); IDictionary <CurveGroupName, IDictionary <Pair <LegalEntityGroup, Currency>, CurveName> > legalEntityGroups = new LinkedHashMap <CurveGroupName, IDictionary <Pair <LegalEntityGroup, Currency>, CurveName> >(); parseCurveMaps(groupsCharSource, repoGroups, legalEntityGroups); IDictionary <LocalDate, IDictionary <CurveName, Curve> > allCurves = parseCurves(datePredicate, settingsCharSource, curveValueCharSources); ImmutableListMultimap.Builder <LocalDate, LegalEntityCurveGroup> builder = ImmutableListMultimap.builder(); foreach (KeyValuePair <LocalDate, IDictionary <CurveName, Curve> > curveEntry in allCurves.SetOfKeyValuePairs()) { LocalDate date = curveEntry.Key; IDictionary <CurveName, Curve> curves = curveEntry.Value; foreach (KeyValuePair <CurveGroupName, IDictionary <Pair <RepoGroup, Currency>, CurveName> > repoEntry in repoGroups.SetOfKeyValuePairs()) { CurveGroupName groupName = repoEntry.Key; IDictionary <Pair <RepoGroup, Currency>, Curve> repoCurves = MapStream.of(repoEntry.Value).mapValues(name => queryCurve(name, curves, date, groupName, "Repo")).toMap(); IDictionary <Pair <LegalEntityGroup, Currency>, Curve> issuerCurves = MapStream.of(legalEntityGroups[groupName]).mapValues(name => queryCurve(name, curves, date, groupName, "Issuer")).toMap(); builder.put(date, LegalEntityCurveGroup.of(groupName, repoCurves, issuerCurves)); } } return(builder.build()); }