Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 21 additions & 10 deletions PxWeb.UnitTests/DataSource/CnmmDataSourceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public void ResolveShouldResolveItemCollection()
var memorymock = new Mock<IPxCache>();
var configMock = new Mock<IPxApiConfigurationService>();
var pcAxisFactory = new Mock<IItemSelectionResolverFactory>();
var cnmmConfigMock = new Mock<IOptions<CnmmConfigurationOptions>>();
cnmmConfigMock.Setup(x => x.Value).Returns(new CnmmConfigurationOptions());

var testFactory = new TestFactory();
var dict = testFactory.GetMenuLookupFolders();
Expand All @@ -21,7 +23,7 @@ public void ResolveShouldResolveItemCollection()

pcAxisFactory.Setup(x => x.GetMenuLookupFolders(language)).Returns(dict);

var resolver = new ItemSelectionResolverCnmm(memorymock.Object, pcAxisFactory.Object, configMock.Object);
var resolver = new ItemSelectionResolverCnmm(memorymock.Object, pcAxisFactory.Object, configMock.Object, cnmmConfigMock.Object);

bool selectionExists;

Expand All @@ -40,6 +42,8 @@ public void ResolveEmtySelectionItemShouldReturnStart()
var memorymock = new Mock<IPxCache>();
var configMock = new Mock<IPxApiConfigurationService>();
var pcAxisFactory = new Mock<IItemSelectionResolverFactory>();
var cnmmConfigMock = new Mock<IOptions<CnmmConfigurationOptions>>();
cnmmConfigMock.Setup(x => x.Value).Returns(new CnmmConfigurationOptions());

var testFactory = new TestFactory();
var dict = testFactory.GetMenuLookupFolders();
Expand All @@ -49,7 +53,7 @@ public void ResolveEmtySelectionItemShouldReturnStart()

pcAxisFactory.Setup(x => x.GetMenuLookupFolders(language)).Returns(dict);

var resolver = new ItemSelectionResolverCnmm(memorymock.Object, pcAxisFactory.Object, configMock.Object);
var resolver = new ItemSelectionResolverCnmm(memorymock.Object, pcAxisFactory.Object, configMock.Object, cnmmConfigMock.Object);

bool selectionExists;

Expand All @@ -71,6 +75,7 @@ public void ShouldReturnMenu()
var configServiceMock = new Mock<ICnmmConfigurationService>();
var codelistMapperMock = new Mock<ICodelistMapper>();
var pxApiConfig = new Mock<IOptions<PxApiConfigurationOptions>>();
var cnmmConfigMock = new Mock<IOptions<CnmmConfigurationOptions>>();

var pcAxisFactory = new Mock<IItemSelectionResolverFactory>();

Expand All @@ -82,11 +87,11 @@ public void ShouldReturnMenu()

pcAxisFactory.Setup(x => x.GetMenuLookupFolders(language)).Returns(dict);

var resolver = new ItemSelectionResolverCnmm(memorymock.Object, pcAxisFactory.Object, configMock.Object);
var resolver = new ItemSelectionResolverCnmm(memorymock.Object, pcAxisFactory.Object, configMock.Object, cnmmConfigMock.Object);
var tablePathResolver = new TablePathResolverCnmm(configServiceMock.Object, resolver);
pxApiConfig.Setup(x => x.Value).Returns(config);

var datasource = new CnmmDataSource(configServiceMock.Object, resolver, tablePathResolver, codelistMapperMock.Object, pxApiConfig.Object);
var datasource = new CnmmDataSource(configServiceMock.Object, resolver, tablePathResolver, codelistMapperMock.Object, pxApiConfig.Object, cnmmConfigMock.Object);

bool selectionExists;

Expand All @@ -106,6 +111,7 @@ public void TableExistsCNMMShouldReturnTrue()
var configServiceMock = new Mock<ICnmmConfigurationService>();
var codelistMapperMock = new Mock<ICodelistMapper>();
var pxApiConfig = new Mock<IOptions<PxApiConfigurationOptions>>();
var cnmmConfigMock = new Mock<IOptions<CnmmConfigurationOptions>>();

var pcAxisFactory = new Mock<IItemSelectionResolverFactory>();

Expand All @@ -117,12 +123,12 @@ public void TableExistsCNMMShouldReturnTrue()

pcAxisFactory.Setup(x => x.GetMenuLookupTables(language)).Returns(dict);

var resolver = new ItemSelectionResolverCnmm(memorymock.Object, pcAxisFactory.Object, configMock.Object);
var resolver = new ItemSelectionResolverCnmm(memorymock.Object, pcAxisFactory.Object, configMock.Object, cnmmConfigMock.Object);
var tablePathResolver = new TablePathResolverCnmm(configServiceMock.Object, resolver);

pxApiConfig.Setup(x => x.Value).Returns(config);

var datasource = new CnmmDataSource(configServiceMock.Object, resolver, tablePathResolver, codelistMapperMock.Object, pxApiConfig.Object);
var datasource = new CnmmDataSource(configServiceMock.Object, resolver, tablePathResolver, codelistMapperMock.Object, pxApiConfig.Object, cnmmConfigMock.Object);

var result = datasource.TableExists("Befolkning", language);

Expand All @@ -140,6 +146,7 @@ public void TableExistsCNMMShouldReturnFalse()
var configServiceMock = new Mock<ICnmmConfigurationService>();
var codelistMapperMock = new Mock<ICodelistMapper>();
var pxApiConfig = new Mock<IOptions<PxApiConfigurationOptions>>();
var cnmmConfigMock = new Mock<IOptions<CnmmConfigurationOptions>>();

var pcAxisFactory = new Mock<IItemSelectionResolverFactory>();

Expand All @@ -151,11 +158,11 @@ public void TableExistsCNMMShouldReturnFalse()

pcAxisFactory.Setup(x => x.GetMenuLookupTables(language)).Returns(dict);

var resolver = new ItemSelectionResolverCnmm(memorymock.Object, pcAxisFactory.Object, configMock.Object);
var resolver = new ItemSelectionResolverCnmm(memorymock.Object, pcAxisFactory.Object, configMock.Object, cnmmConfigMock.Object);
var tablePathResolver = new TablePathResolverCnmm(configServiceMock.Object, resolver);
pxApiConfig.Setup(x => x.Value).Returns(config);

var datasource = new CnmmDataSource(configServiceMock.Object, resolver, tablePathResolver, codelistMapperMock.Object, pxApiConfig.Object);
var datasource = new CnmmDataSource(configServiceMock.Object, resolver, tablePathResolver, codelistMapperMock.Object, pxApiConfig.Object, cnmmConfigMock.Object);

var result = datasource.TableExists("select * from Befolkning", language);

Expand All @@ -173,15 +180,19 @@ public void GetTableLanguages_ShouldReturn_emptyMappingWhenNoDataSourceSpecified
var codelistMapperMock = new Mock<ICodelistMapper>();
var pxApiConfig = new Mock<IOptions<PxApiConfigurationOptions>>();
var pcAxisFactory = new Mock<IItemSelectionResolverFactory>();
var cnmmConfigMock = new Mock<IOptions<CnmmConfigurationOptions>>();
cnmmConfigMock.Setup(x => x.Value).Returns(new CnmmConfigurationOptions());


var testFactory = new TestFactory();
var dict = testFactory.GetMenuLookupTables();
var config = testFactory.GetPxApiConfiguration();
configMock.Setup(x => x.GetConfiguration()).Returns(config);
pcAxisFactory.Setup(x => x.GetMenuLookupTables(language)).Returns(dict);
var resolver = new ItemSelectionResolverCnmm(memorymock.Object, pcAxisFactory.Object, configMock.Object);
var resolver = new ItemSelectionResolverCnmm(memorymock.Object, pcAxisFactory.Object, configMock.Object, cnmmConfigMock.Object);
var tablePathResolver = new TablePathResolverCnmm(configServiceMock.Object, resolver);
pxApiConfig.Setup(x => x.Value).Returns(config);
var datasource = new CnmmDataSource(configServiceMock.Object, resolver, tablePathResolver, codelistMapperMock.Object, pxApiConfig.Object);
var datasource = new CnmmDataSource(configServiceMock.Object, resolver, tablePathResolver, codelistMapperMock.Object, pxApiConfig.Object, cnmmConfigMock.Object);

//Act
var mapping = datasource.GetTableLanguages();
Expand Down
11 changes: 7 additions & 4 deletions PxWeb.UnitTests/DataSource/PXDataSourceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

using System;

using Microsoft.Extensions.Options;

namespace PxWeb.UnitTests.DataSource
{
[TestClass]
Expand Down Expand Up @@ -79,7 +81,7 @@ public void ShouldReturnMenu()
.Setup(m => m.RootPath)
.Returns(wwwrootPath);

var resolver = new ItemSelectionResolverCnmm(memorymock.Object, pcAxisFactory, configMock.Object);
var resolver = new ItemSelectionResolverPxFile(memorymock.Object, pcAxisFactory, configMock.Object);
var tablePathResolver = new TablePathResolverPxFile(memorymock.Object, hostingEnvironmentMock.Object, configMock.Object, loggerMock.Object);
var datasource = new PxFileDataSource(configServiceMock.Object, resolver, tablePathResolver, hostingEnvironmentMock.Object, codelistMapperMock.Object);
bool selectionExists;
Expand Down Expand Up @@ -200,7 +202,7 @@ public void TableExistPXFileShouldNotReturnTrue()
.Setup(m => m.RootPath)
.Returns(wwwrootPath);

var resolver = new ItemSelectionResolverCnmm(memorymock.Object, pcAxisFactory, configMock.Object);
var resolver = new ItemSelectionResolverPxFile(memorymock.Object, pcAxisFactory, configMock.Object);
var tablePathResolver = new TablePathResolverPxFile(memorymock.Object, hostingEnvironmentMock.Object, configMock.Object, loggerMock.Object);
var datasource = new PxFileDataSource(configServiceMock.Object, resolver, tablePathResolver, hostingEnvironmentMock.Object, codelistMapperMock.Object);

Expand Down Expand Up @@ -320,7 +322,7 @@ public void ShouldReturnMappingOfTableLanguages()
.Setup(m => m.RootPath)
.Returns(wwwrootPath);

var resolver = new ItemSelectionResolverCnmm(memorymock.Object, pcAxisFactory, configMock.Object);
var resolver = new ItemSelectionResolverPxFile(memorymock.Object, pcAxisFactory, configMock.Object);
var tablePathResolver = new TablePathResolverPxFile(memorymock.Object, hostingEnvironmentMock.Object, configMock.Object, loggerMock.Object);
var datasource = new PxFileDataSource(configServiceMock.Object, resolver, tablePathResolver, hostingEnvironmentMock.Object, codelistMapperMock.Object);

Expand All @@ -343,6 +345,7 @@ public void LoadDatabaseStructure_ShouldNotHaveDatabaseInId()
var hostingEnvironmentMock = new Mock<IPxHost>();
var loggerMock = new Mock<ILogger<TablePathResolverPxFile>>();
var codelistMapperMock = new Mock<ICodelistMapper>();
var cnmmConfigMock = new Mock<IOptions<CnmmConfigurationOptions>>();

var itemLoggerMock = new Mock<ILogger<ItemSelectorResolverPxFactory>>();

Expand All @@ -357,7 +360,7 @@ public void LoadDatabaseStructure_ShouldNotHaveDatabaseInId()
.Setup(m => m.RootPath)
.Returns(wwwrootPath);

var resolver = new ItemSelectionResolverCnmm(memorymock.Object, pcAxisFactory, configMock.Object);
var resolver = new ItemSelectionResolverPxFile(memorymock.Object, pcAxisFactory, configMock.Object);
var tablePathResolver = new TablePathResolverPxFile(memorymock.Object, hostingEnvironmentMock.Object, configMock.Object, loggerMock.Object);
var datasource = new PxFileDataSource(configServiceMock.Object, resolver, tablePathResolver, hostingEnvironmentMock.Object, codelistMapperMock.Object);

Expand Down
7 changes: 5 additions & 2 deletions PxWeb/Code/Api2/DataSource/Cnmm/CnmmDataSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@ public class CnmmDataSource : IDataSource
private readonly ITablePathResolver _tablePathResolver;
private readonly ICodelistMapper _codelistMapper;
private readonly string[] _languages;
private readonly string? _rootNode;

public CnmmDataSource(ICnmmConfigurationService cnmmConfigurationService, IItemSelectionResolver itemSelectionResolver, ITablePathResolver tablePathResolver, ICodelistMapper codelistMapper, IOptions<PxApiConfigurationOptions> configOptions)
public CnmmDataSource(ICnmmConfigurationService cnmmConfigurationService, IItemSelectionResolver itemSelectionResolver, ITablePathResolver tablePathResolver, ICodelistMapper codelistMapper, IOptions<PxApiConfigurationOptions> configOptions, IOptions<CnmmConfigurationOptions> cnmmConfigOptions)
{
_cnmmConfigurationService = cnmmConfigurationService;
_itemSelectionResolver = itemSelectionResolver;
_tablePathResolver = tablePathResolver;
_codelistMapper = codelistMapper;
_languages = [.. configOptions.Value.Languages.Select(l => l.Id)];
_rootNode = cnmmConfigOptions.Value.RootNode;
}

public IPXModelBuilder? CreateBuilder(string id, string language)
Expand Down Expand Up @@ -263,7 +265,8 @@ public List<string> GetTablesPublishedBetween(DateTime from, DateTime to)

public Item? LoadDatabaseStructure(string language)
{
ItemSelection itmSel = _itemSelectionResolver.ResolveFolder(language, "", out var selectionExists);
var rootNode = _rootNode ?? "";
ItemSelection itmSel = _itemSelectionResolver.ResolveFolder(language, rootNode, out var selectionExists);
if (!selectionExists)
{
return null;
Expand Down
73 changes: 70 additions & 3 deletions PxWeb/Code/Api2/DataSource/Cnmm/ItemSelectionResolverCnmm.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using PCAxis.Menu;
using Microsoft.Extensions.Options;

using PCAxis.Menu;

using Px.Abstractions.Interfaces;

Expand All @@ -13,12 +15,14 @@ public class ItemSelectionResolverCnmm : IItemSelectionResolver
private readonly IPxCache _pxCache;
private readonly IItemSelectionResolverFactory _itemSelectionResolverFactory;
private readonly IPxApiConfigurationService _pxApiConfigurationService;
private readonly string? _rootNode;

public ItemSelectionResolverCnmm(IPxCache pxCache, IItemSelectionResolverFactory itemSelectionResolverFactory, IPxApiConfigurationService pxApiConfigurationService)
public ItemSelectionResolverCnmm(IPxCache pxCache, IItemSelectionResolverFactory itemSelectionResolverFactory, IPxApiConfigurationService pxApiConfigurationService, IOptions<CnmmConfigurationOptions> cnmmConfigOptions)
{
_pxCache = pxCache;
_itemSelectionResolverFactory = itemSelectionResolverFactory;
_pxApiConfigurationService = pxApiConfigurationService;
_rootNode = cnmmConfigOptions.Value.RootNode;
}

public ItemSelection ResolveFolder(string language, string selection, out bool selectionExists)
Expand All @@ -31,6 +35,11 @@ public ItemSelection ResolveFolder(string language, string selection, out bool s
if (lookupTable is null)
{
lookupTable = _itemSelectionResolverFactory.GetMenuLookupFolders(language);
if (!string.IsNullOrEmpty(_rootNode))
{
// TODO remove unrooted entry from lookup table
lookupTable = RemoveUnrootedEntries(lookupTable, _rootNode);
}
_pxCache.Set(lookupTableName, lookupTable);
}

Expand All @@ -50,7 +59,6 @@ public ItemSelection ResolveFolder(string language, string selection, out bool s
return itemSelection;
}


public ItemSelection ResolveTable(string language, string selection, out bool selectionExists)
{
selectionExists = false;
Expand All @@ -61,6 +69,19 @@ public ItemSelection ResolveTable(string language, string selection, out bool se
if (lookupTable is null)
{
lookupTable = _itemSelectionResolverFactory.GetMenuLookupTables(language);
var newLookupTable = new Dictionary<string, ItemSelection>();
if (!string.IsNullOrEmpty(_rootNode))
{
foreach (var kvp in lookupTable)
{
ResolveFolder(language, kvp.Value.Menu, out bool folderExists);
if (folderExists)
{
newLookupTable.Add(kvp.Key, kvp.Value);
}
}
lookupTable = newLookupTable;
}
_pxCache.Set(lookupTableName, lookupTable);
}

Expand All @@ -74,5 +95,51 @@ public ItemSelection ResolveTable(string language, string selection, out bool se

return itemSelection;
}


private static Dictionary<string, ItemSelection> RemoveUnrootedEntries(Dictionary<string, ItemSelection> lookupTable, string rootItem)
{
var newLookup = new Dictionary<string, ItemSelection>();
var filter = new Dictionary<string, List<ItemSelection>>();

foreach (var selection in lookupTable.Values)
{
if (filter.ContainsKey(selection.Menu))
{
filter[selection.Menu].Add(selection);
}
else
{
filter[selection.Menu] = new List<ItemSelection>() { selection };
}
}

if (filter.ContainsKey(rootItem))
{
newLookup.Add(rootItem, lookupTable[rootItem]);
AddRecursive(rootItem, newLookup, filter);
}

return newLookup;
}

private static void AddRecursive(string item, Dictionary<string, ItemSelection> result, Dictionary<string, List<ItemSelection>> lookup)
{
if (!lookup.ContainsKey(item))
{
return;
}

var selections = lookup[item];

if (selections != null && selections.Count > 0)
{
foreach (var selection in selections)
{
result.Add(selection.Selection, selection);
AddRecursive(selection.Selection, result, lookup);
}
}
}
}
}
2 changes: 2 additions & 0 deletions PxWeb/Config/Api2/CnmmConfigurationOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ public class CnmmConfigurationOptions
public string DatabaseID { get; set; } = string.Empty;

public string HealthCheckQuery { get; set; } = DEFAULT_QUERY;

public string? RootNode { get; set; }
}
}
Loading