307 lines
13 KiB
C#
307 lines
13 KiB
C#
using C4IT.FASD.Base;
|
|
using C4IT.FASD.Cockpit.Communication;
|
|
using FasdDesktopUi.Basics.CustomEvents;
|
|
using FasdDesktopUi.Basics.Services.RelationService;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using static C4IT.Logging.cLogManager;
|
|
|
|
namespace FasdDesktopUi.Basics.Services.SupportCase
|
|
{
|
|
public class SupportCase : ISupportCase
|
|
{
|
|
private readonly Dictionary<enumFasdInformationClass, IList<cF4sdApiSearchResultRelation>> _caseRelations = new Dictionary<enumFasdInformationClass, IList<cF4sdApiSearchResultRelation>>();
|
|
private readonly Dictionary<string, Dictionary<cF4sdApiSearchResultRelation, cF4SDHealthCardRawData.cHealthCardTable>> _supportCaseDataCache = new Dictionary<string, Dictionary<cF4sdApiSearchResultRelation, cF4SDHealthCardRawData.cHealthCardTable>>();
|
|
private readonly Dictionary<cF4sdApiSearchResultRelation, cF4SDHealthCardRawData> _rawDataCache = new Dictionary<cF4sdApiSearchResultRelation, cF4SDHealthCardRawData>(); // todo remove, currently only used for SupportCaseDataProviderArtifact
|
|
|
|
internal readonly Guid Id;
|
|
private readonly IRelationService _relationService;
|
|
public cSupportCaseDataProvider SupportCaseDataProviderArtifact { get; }
|
|
|
|
internal SupportCase(Guid id, IRelationService relationService, cSupportCaseDataProvider supportCaseDataProvider)
|
|
{
|
|
Id = id;
|
|
_relationService = relationService;
|
|
SupportCaseDataProviderArtifact = supportCaseDataProvider;
|
|
|
|
AddCaseRelations(_relationService?.GetLoadedRelations());
|
|
}
|
|
|
|
~SupportCase()
|
|
{
|
|
if (_relationService != null)
|
|
_relationService.RelationsFound -= HandleRelationsFound;
|
|
}
|
|
|
|
public void Initialize()
|
|
{
|
|
if (_relationService != null)
|
|
_relationService.RelationsFound += HandleRelationsFound;
|
|
}
|
|
|
|
public ILookup<enumFasdInformationClass, cF4sdApiSearchResultRelation> GetCaseRelations()
|
|
{
|
|
try
|
|
{
|
|
IEnumerable<(enumFasdInformationClass InformationClass, cF4sdApiSearchResultRelation Relation)> flatList
|
|
= _caseRelations.SelectMany(i => i.Value.Select(v => (i.Key, v)));
|
|
|
|
return flatList.ToLookup(v => v.InformationClass, v => v.Relation);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogException(ex);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public void AddCaseRelations(ILookup<enumFasdInformationClass, cF4sdApiSearchResultRelation> relations)
|
|
{
|
|
try
|
|
{
|
|
if (relations is null)
|
|
return;
|
|
|
|
foreach (var relationType in relations)
|
|
{
|
|
if (_caseRelations.TryGetValue(relationType.Key, out var caseRelation))
|
|
caseRelation = caseRelation.Union(relationType).ToList();
|
|
else
|
|
_caseRelations.Add(relationType.Key, relationType.ToList());
|
|
|
|
if (SupportCaseDataProviderArtifact?.CaseRelations?.TryGetValue(relationType.Key, out var caseRelations) ?? false)
|
|
caseRelations = caseRelations.Union(relationType).ToList();
|
|
else
|
|
SupportCaseDataProviderArtifact?.CaseRelations?.Add(relationType.Key, relationType.ToList());
|
|
}
|
|
|
|
CaseRelationsAdded?.Invoke(this, new RelationEventArgs() { Relations = relations });
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogException(ex);
|
|
}
|
|
}
|
|
|
|
public async Task LoadSupportCaseDataAsync(cF4sdApiSearchResultRelation relation, IEnumerable<string> tablesToLoad)
|
|
{
|
|
try
|
|
{
|
|
cF4SDHealthCardRawData rawData = null;
|
|
|
|
// todo this is only a temporary fix. Currently the tablesToLoad contain also detail tables
|
|
// and tables won't be loaded e.g. the QuickActionHistory
|
|
bool isDataComplete = IsRawDataCacheComplete() && IsSupportCaseDataCacheComplete();
|
|
|
|
if (isDataComplete)
|
|
{
|
|
await SupportCaseDataProviderArtifact.HealthCardDataHelper.LoadingHelper.SetHealthCardRawData(_rawDataCache[relation], relation.Identities);
|
|
return;
|
|
}
|
|
|
|
var rawDataRequest = new cF4sdHealthCardRawDataRequest()
|
|
{
|
|
Identities = relation.Identities,
|
|
Tables = tablesToLoad.ToList(),
|
|
MaxAge = cF4SDCockpitXmlConfig.Instance?.HealthCardConfig?.SearchResultAge ?? 14
|
|
};
|
|
|
|
while (!isDataComplete)
|
|
{
|
|
if (rawData is null)
|
|
{
|
|
rawData = await cFasdCockpitCommunicationBase.Instance.GetHealthCardData(rawDataRequest);
|
|
_rawDataCache[relation] = rawData;
|
|
await SupportCaseDataProviderArtifact.HealthCardDataHelper.LoadingHelper.SetHealthCardRawData(rawData, rawDataRequest.Identities);
|
|
}
|
|
else
|
|
{
|
|
rawData = await cFasdCockpitCommunicationBase.Instance.GetHealthCardData(rawData.Id);
|
|
_rawDataCache[relation] = _rawDataCache[relation].Combine(rawData);
|
|
await SupportCaseDataProviderArtifact.HealthCardDataHelper.LoadingHelper.UpdateHealthcardRawData(rawData);
|
|
}
|
|
|
|
UpdateSupportCaseDataCache(relation, rawData?.Tables?.Values);
|
|
|
|
isDataComplete = rawData?.Tables?
|
|
.Where(table => table.Key.StartsWith("Computation_") == false)
|
|
.All(table => !table.Value.IsIncomplete && !table.Value.Columns.Values.Any(c => c.IsIncomplete)) ?? false;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogException(ex);
|
|
}
|
|
|
|
bool IsRawDataCacheComplete()
|
|
{
|
|
return tablesToLoad.All(t =>
|
|
_rawDataCache.TryGetValue(relation, out var cachedRawData)
|
|
&& (cachedRawData?.Tables?.TryGetValue(t, out var cachedTable) ?? false)
|
|
&& cachedTable != null && !cachedTable.IsIncomplete && !cachedTable.Columns.Values.Any(c => c.IsIncomplete)
|
|
);
|
|
}
|
|
|
|
bool IsSupportCaseDataCacheComplete()
|
|
{
|
|
return tablesToLoad.Any(t =>
|
|
_supportCaseDataCache.TryGetValue(t, out var cachedTables)
|
|
&& cachedTables.TryGetValue(relation, out var table)
|
|
&& !table.IsIncomplete && !table.Columns.Values.Any(c => c.IsIncomplete)
|
|
);
|
|
}
|
|
}
|
|
|
|
public void UpdateSupportCaseDataCache(cF4sdApiSearchResultRelation relation, IEnumerable<cF4SDHealthCardRawData.cHealthCardTable> tables)
|
|
{
|
|
try
|
|
{
|
|
if (tables is null)
|
|
return;
|
|
|
|
List<cF4SDHealthCardRawData.cHealthCardTable> dataTables = tables?.ToList();
|
|
|
|
foreach (var table in dataTables)
|
|
{
|
|
if (string.IsNullOrEmpty(table.Name))
|
|
continue;
|
|
|
|
if (!_supportCaseDataCache.ContainsKey(table.Name))
|
|
_supportCaseDataCache.Add(table.Name, new Dictionary<cF4sdApiSearchResultRelation, cF4SDHealthCardRawData.cHealthCardTable>());
|
|
|
|
if (!_supportCaseDataCache[table.Name].ContainsKey(relation))
|
|
_supportCaseDataCache[table.Name][relation] = table;
|
|
else if (_supportCaseDataCache[table.Name][relation].IsIncomplete)
|
|
MergeTable(_supportCaseDataCache[table.Name][relation], table);
|
|
}
|
|
|
|
SupportCaseDataCacheHasChanged?.Invoke(this, new SupportCaseDataEventArgs() { Relation = relation, DataTables = dataTables });
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogException(ex);
|
|
}
|
|
|
|
void MergeTable(cF4SDHealthCardRawData.cHealthCardTable existingTable, cF4SDHealthCardRawData.cHealthCardTable newTable)
|
|
{
|
|
try
|
|
{
|
|
existingTable.IsIncomplete = newTable.IsIncomplete;
|
|
|
|
foreach (var newColumn in newTable.Columns)
|
|
{
|
|
existingTable.Columns[newColumn.Key] = newColumn.Value;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogException(ex);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void InvalidateCaseDataCacheFor(cF4sdApiSearchResultRelation relation)
|
|
{
|
|
try
|
|
{
|
|
_rawDataCache.Remove(relation);
|
|
|
|
foreach (var tableCache in _supportCaseDataCache.Values)
|
|
{
|
|
tableCache.Remove(relation);
|
|
}
|
|
|
|
// todo: invoke SupportCaseDataChache with empty tables
|
|
// SupportCaseDataCacheHasChanged?.Invoke(this, new SupportCaseDataEventArgs() { Relation = relation });
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogException(ex);
|
|
}
|
|
}
|
|
|
|
public void InvalidateLatestCaseDataCacheFor(cF4sdApiSearchResultRelation relation, out ICollection<cF4SDHealthCardRawData.cHealthCardTable> invalidatedTables)
|
|
{
|
|
invalidatedTables = new HashSet<cF4SDHealthCardRawData.cHealthCardTable>();
|
|
try
|
|
{
|
|
foreach (var tableCache in _supportCaseDataCache.Values)
|
|
{
|
|
if (!tableCache.TryGetValue(relation, out cF4SDHealthCardRawData.cHealthCardTable table))
|
|
continue;
|
|
|
|
table.IsIncomplete = true;
|
|
|
|
foreach (var column in table.Columns.Values)
|
|
{
|
|
if (column.Values != null && column.Values.Count > 0)
|
|
column.Values[0] = null;
|
|
column.IsIncomplete = true;
|
|
}
|
|
|
|
invalidatedTables.Add(table);
|
|
}
|
|
|
|
if (!_rawDataCache.TryGetValue(relation, out var cachedRawData) || cachedRawData?.Tables is null)
|
|
return;
|
|
|
|
foreach (var table in cachedRawData.Tables.Values)
|
|
{
|
|
table.IsIncomplete = true;
|
|
|
|
foreach (var column in table.Columns.Values)
|
|
{
|
|
if (column.Values != null && column.Values.Count > 0)
|
|
column.Values[0] = null;
|
|
column.IsIncomplete = true;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogException(ex);
|
|
}
|
|
}
|
|
|
|
public IEnumerable<object> GetSupportCaseHealthcardData(cF4sdApiSearchResultRelation relation, cValueAddress valueAddress)
|
|
{
|
|
try
|
|
{
|
|
if (!_supportCaseDataCache.TryGetValue(valueAddress.ValueTable, out var tables))
|
|
return null;
|
|
|
|
if (!tables.TryGetValue(relation, out var table))
|
|
return null;
|
|
|
|
if (!table.Columns.TryGetValue(valueAddress.ValueColumn, out var column))
|
|
return null;
|
|
|
|
return column.Values;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogException(ex);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private void HandleRelationsFound(object sender, StagedSearchResultRelationsEventArgs e)
|
|
{
|
|
AddCaseRelations(e.StagedResultRelations.Relations);
|
|
|
|
if (e.StagedResultRelations.IsComplete)
|
|
_relationService.RelationsFound -= HandleRelationsFound;
|
|
}
|
|
|
|
private void AddCaseRelations(IEnumerable<cF4sdApiSearchResultRelation> relations)
|
|
=> AddCaseRelations(relations?.ToLookup(r => cF4sdIdentityEntry.GetFromSearchResult(r.Type), r => r));
|
|
|
|
public event EventHandler<RelationEventArgs> CaseRelationsAdded;
|
|
public event EventHandler<SupportCaseDataEventArgs> SupportCaseDataCacheHasChanged;
|
|
}
|
|
}
|