/// <summary> /// Constructs and returns a <see cref="MarketDescriptionCacheItem"/> from the provided DTO /// </summary> /// <param name="dto">The <see cref="MarketDescriptionDTO"/> containing market description data.</param> /// <param name="factory">The <see cref="IMappingValidatorFactory"/> instance used to build market mapping validators .</param> /// <param name="culture">A <see cref="CultureInfo"/> specifying the language of the provided DTO.</param> /// <param name="source">The source cache where <see cref="MarketDescriptionCacheItem"/> is built</param> /// <returns>The constructed <see cref="MarketDescriptionCacheItem"/>.</returns> /// <exception cref="InvalidOperationException">The cache item could not be build from the provided DTO</exception> public static MarketDescriptionCacheItem Build(MarketDescriptionDTO dto, IMappingValidatorFactory factory, CultureInfo culture, string source) { Guard.Argument(dto, nameof(dto)).NotNull(); Guard.Argument(factory, nameof(factory)).NotNull(); Guard.Argument(culture, nameof(culture)).NotNull(); var names = new Dictionary <CultureInfo, string> { { culture, dto.Name } }; var descriptions = string.IsNullOrEmpty(dto.Description) ? new Dictionary <CultureInfo, string>() : new Dictionary <CultureInfo, string> { { culture, dto.Description } }; var outcomes = dto.Outcomes == null ? null : new ReadOnlyCollection <MarketOutcomeCacheItem>(dto.Outcomes.Select(o => new MarketOutcomeCacheItem(o, culture)).ToList()); var mappings = dto.Mappings == null ? null : new ReadOnlyCollection <MarketMappingCacheItem>(dto.Mappings.Select(m => MarketMappingCacheItem.Build(m, factory, culture)).ToList()); var specifiers = dto.Specifiers == null ? null : new ReadOnlyCollection <MarketSpecifierCacheItem>(dto.Specifiers.Select(s => new MarketSpecifierCacheItem(s)).ToList()); var attributes = dto.Attributes == null ? null : new ReadOnlyCollection <MarketAttributeCacheItem>(dto.Attributes.Select(a => new MarketAttributeCacheItem(a)).ToList()); var groups = dto.Groups == null ? null : new ReadOnlyCollection <string>(dto.Groups.ToList()); return(new MarketDescriptionCacheItem(dto.Id, names, descriptions, dto.Variant, dto.OutcomeType, outcomes, mappings, specifiers, attributes, groups, culture, source)); }
public void MarketDescriptionDTOMappingTest() { var msg = RMF.GetDescMarket(); var dto = new MarketDescriptionDTO(msg); Assert.AreEqual(msg.id, dto.Id); Assert.AreEqual(msg.name, dto.Name); Assert.AreEqual(msg.description, dto.Description); //Assert.AreEqual(msg.variant, dto.Variant); //TODO: check if variant is missing in dto? Assert.AreEqual(msg.mappings.Length, dto.Mappings.Count()); Assert.AreEqual(msg.outcomes.Length, dto.Outcomes.Count()); Assert.AreEqual(msg.specifiers.Length, dto.Specifiers.Count()); for (var i = 0; i < msg.mappings.Length; i++) { ValidateMapping(msg.mappings[i], dto.Mappings.ToArray()[i]); } for (var i = 0; i < msg.outcomes.Length; i++) { ValidateOutcome(msg.outcomes[i], dto.Outcomes.ToArray()[i]); } for (var i = 0; i < msg.specifiers.Length; i++) { ValidateSpecifier(msg.specifiers[i], dto.Specifiers.ToArray()[i]); } }
internal void Merge(MarketDescriptionDTO dto, CultureInfo culture) { Contract.Requires(dto != null); Contract.Requires(culture != null); lock (_lock) { _names[culture] = dto.Name; if (!string.IsNullOrEmpty(dto.Description)) { _descriptions[culture] = dto.Description; } Variant = dto.Variant; if (dto.Outcomes != null) { foreach (var outcomeDto in dto.Outcomes) { var existingOutcome = Outcomes?.FirstOrDefault(o => o.Id == outcomeDto.Id); if (existingOutcome != null) { existingOutcome.Merge(outcomeDto, culture); } else { ExecutionLog.Warn( $"Could not merge outcome[Id={outcomeDto.Id}] for lang={culture.TwoLetterISOLanguageName} on marketDescription[Id={Id}] because the specified outcome does not exist on stored market description."); ComparePrint(dto, culture); } } } if (dto.Mappings != null) { foreach (var mappingDto in dto.Mappings) { var existingMapping = Mappings?.FirstOrDefault(m => MarketMappingsMatch(m, mappingDto)); if (existingMapping != null) { existingMapping.Merge(mappingDto, culture); } else { ExecutionLog.Warn( $"Could not merge mapping[MarketId={mappingDto.MarketTypeId}:{mappingDto.MarketSubTypeId}] for lang={culture.TwoLetterISOLanguageName} on marketDescription[Id={dto.Id}]because the specified mapping does not exist on stored market description."); ComparePrint(dto, culture); } } } OutcomeType = dto.OutcomeType; Groups = dto.Groups == null ? null : new ReadOnlyCollection <string>(dto.Groups.ToList()); FetchedLanguages.Add(culture); LastDataReceived = DateTime.Now; } }
private void ComparePrint(MarketDescriptionDTO dto, CultureInfo culture) { var names = _names.Aggregate(string.Empty, (current, name) => current + $", {name.Key.TwoLetterISOLanguageName}-{name.Value}").Substring(2); var desc = _descriptions.Aggregate(string.Empty, (current, d) => current + $", {d.Key.TwoLetterISOLanguageName}-{d.Value}"); var specs = Specifiers == null ? null : string.Join(", ", Specifiers.Select(s => s.Name)); var outcomes = Outcomes == null ? null : string.Join(",", Outcomes.Select(s => s.Id)); var maps = Mappings == null ? null : string.Join(",", Mappings.Select(s => s.MarketTypeId)); ExecutionLog.Debug($"Original Id={Id}, Names=[{names}], Descriptions=[{desc}], Variant=[{Variant}], Specifiers=[{specs}], Outocomes=[{outcomes}], Mappings=[{maps}]."); var specsNew = dto.Specifiers == null ? null : string.Join(", ", dto.Specifiers.Select(s => s.Name)); var outcomesNew = dto.Outcomes == null ? null : string.Join(",", dto.Outcomes.Select(s => s.Id)); var mapsNew = dto.Mappings == null ? null : string.Join(",", dto.Mappings.Select(s => s.MarketTypeId)); ExecutionLog.Debug($"New Id={dto.Id}, Name=[{culture.TwoLetterISOLanguageName}-{dto.Name}], Descriptions=[{dto.Description}], Variant=[{dto.Variant}], Specifiers=[{specsNew}], Outocomes=[{outcomesNew}], Mappings=[{mapsNew}]."); }
public void Merge(MarketDescriptionDTO dto, CultureInfo culture) { Guard.Argument(dto, nameof(dto)).NotNull(); Guard.Argument(culture, nameof(culture)).NotNull(); _names[culture] = dto.Name; if (!string.IsNullOrEmpty(dto.Description)) { _descriptions[culture] = dto.Description; } Variant = dto.Variant; if (dto.Outcomes != null) { foreach (var outcomeDto in dto.Outcomes) { var existingOutcome = Outcomes?.FirstOrDefault(o => o.Id == outcomeDto.Id); if (existingOutcome != null) { existingOutcome.Merge(outcomeDto, culture); } else { Log.Warn($"Could not merge outcome[Id={outcomeDto.Id}] on marketDescription[Id={dto.Id}] because the specified outcome does not exist on stored market description"); } } } if (dto.Mappings != null) { foreach (var mappingDto in dto.Mappings) { var existingMapping = Mappings?.FirstOrDefault(m => m.MarketTypeId == mappingDto.MarketTypeId && m.MarketSubTypeId == mappingDto.MarketSubTypeId); if (existingMapping != null) { existingMapping.Merge(mappingDto); } else { Log.Warn($"Could not merge mapping[MarketId={mappingDto.MarketTypeId}:{mappingDto.MarketSubTypeId}] on marketDescription[Id={dto.Id}] because the specified mapping" + " does not exist on stored market description"); } } } _supportedLanguages.Add(culture); }
/// <summary> /// Merges the provided descriptions with those found in cache /// </summary> /// <param name="culture">A <see cref="CultureInfo" /> specifying the language of the <code>descriptions</code></param> /// <param name="description">A <see cref="MarketDescriptionDTO" /> containing market description in specified language</param> private void Merge(CultureInfo culture, MarketDescriptionDTO description) { Contract.Requires(culture != null); Contract.Requires(description != null); if (_isDisposed) { return; } try { _semaphoreCacheMerge.Wait(); var cachedItem = _cache.GetCacheItem(GetCacheKey(description.Id, description.Variant)); if (cachedItem == null) { cachedItem = new CacheItem(GetCacheKey(description.Id, description.Variant), MarketDescriptionCacheItem.Build(description, _mappingValidatorFactory, culture, CacheName)); _cache.Add(cachedItem, _cacheItemPolicy); } else { ((MarketDescriptionCacheItem)cachedItem.Value).Merge(description, culture); } } catch (Exception e) { if (!(e is InvalidOperationException)) { throw; } ExecutionLog.Warn("Mapping validation for MarketDescriptionCacheItem failed.", e); } finally { if (!_isDisposed) { _semaphoreCacheMerge.Release(); } } }
/// <summary> /// Merges the provided descriptions with those found in cache /// </summary> /// <param name="culture">A <see cref="CultureInfo"/> specifying the language of the <code>descriptions</code></param> /// <param name="description">A <see cref="MarketDescriptionDTO"/> containing market description in specified language</param> private async Task MergeAsync(CultureInfo culture, MarketDescriptionDTO description) { Guard.Argument(culture, nameof(culture)).NotNull(); Guard.Argument(description, nameof(description)).NotNull(); if (_isDisposed) { return; } try { await _semaphoreCacheMerge.WaitAsync().ConfigureAwait(false); var cacheId = GetCacheKey(description.Id, description.Variant); var cachedItem = _cache.GetCacheItem(cacheId); if (cachedItem == null) { cachedItem = new CacheItem(cacheId, MarketDescriptionCacheItem.Build(description, _mappingValidatorFactory, culture, CacheName)); _cache.Add(cachedItem, new CacheItemPolicy { SlidingExpiration = OperationManager.VariantMarketDescriptionCacheTimeout }); } else { ((MarketDescriptionCacheItem)cachedItem.Value).Merge(description, culture); } } catch (Exception e) { if (!(e is InvalidOperationException)) { throw; } ExecutionLog.LogWarning(e, "Mapping validation for MarketDescriptionCacheItem failed."); } finally { _semaphoreCacheMerge.ReleaseSafe(); } }