From 867911f7d3ce3dc195c2bdbadb425d8a5bca2067 Mon Sep 17 00:00:00 2001 From: Johannes Date: Fri, 24 May 2024 09:14:49 +0200 Subject: [PATCH] initial, metadata endpoint for json-stat2 --- PxWeb/Controllers/Api2/TableApiController.cs | 8 +- PxWeb/Mappers/DatasetMapper.cs | 484 ++++++++++++++++++ PxWeb/Mappers/IDatasetMapper.cs | 11 + PxWeb/Models/Api2/DatasetSubclass.cs | 314 ++++++++++++ PxWeb/Program.cs | 1 + .../TableController/TableApiControllerTest.cs | 3 +- 6 files changed, 818 insertions(+), 3 deletions(-) create mode 100644 PxWeb/Mappers/DatasetMapper.cs create mode 100644 PxWeb/Mappers/IDatasetMapper.cs create mode 100644 PxWeb/Models/Api2/DatasetSubclass.cs diff --git a/PxWeb/Controllers/Api2/TableApiController.cs b/PxWeb/Controllers/Api2/TableApiController.cs index 8e34032d..1365211e 100644 --- a/PxWeb/Controllers/Api2/TableApiController.cs +++ b/PxWeb/Controllers/Api2/TableApiController.cs @@ -39,6 +39,7 @@ public class TableApiController : PxWeb.Api2.Server.Controllers.TableApiControll private readonly IDataSource _dataSource; private readonly ILanguageHelper _languageHelper; private readonly ITableMetadataResponseMapper _tableMetadataResponseMapper; + private readonly IDatasetMapper _datasetMapper; private readonly ITablesResponseMapper _tablesResponseMapper; private readonly ITableResponseMapper _tableResponseMapper; private readonly ICodelistResponseMapper _codelistResponseMapper; @@ -48,11 +49,12 @@ public class TableApiController : PxWeb.Api2.Server.Controllers.TableApiControll private readonly ISelectionHandler _selectionHandler; private readonly ISelectionResponseMapper _selectionResponseMapper; - public TableApiController(IDataSource dataSource, ILanguageHelper languageHelper, ITableMetadataResponseMapper responseMapper, ISearchBackend backend, IOptions configOptions, ITablesResponseMapper tablesResponseMapper, ITableResponseMapper tableResponseMapper, ICodelistResponseMapper codelistResponseMapper, ISelectionResponseMapper selectionResponseMapper, ISerializeManager serializeManager, ISelectionHandler selectionHandler) + public TableApiController(IDataSource dataSource, ILanguageHelper languageHelper, ITableMetadataResponseMapper responseMapper, IDatasetMapper datasetMapper, ISearchBackend backend, IOptions configOptions, ITablesResponseMapper tablesResponseMapper, ITableResponseMapper tableResponseMapper, ICodelistResponseMapper codelistResponseMapper, ISelectionResponseMapper selectionResponseMapper, ISerializeManager serializeManager, ISelectionHandler selectionHandler) { _dataSource = dataSource; _languageHelper = languageHelper; _tableMetadataResponseMapper = responseMapper; + _datasetMapper = datasetMapper; _backend = backend; _configOptions = configOptions.Value; _tablesResponseMapper = tablesResponseMapper; @@ -77,7 +79,9 @@ public override IActionResult GetMetadataById([FromRoute(Name = "id"), Required] if (outputFormat != null && outputFormat == MetadataOutputFormatType.Stat2Enum) { - throw new NotImplementedException(); + + Dataset ds = _datasetMapper.Map(model, id, lang); + return new ObjectResult(ds); } else { diff --git a/PxWeb/Mappers/DatasetMapper.cs b/PxWeb/Mappers/DatasetMapper.cs new file mode 100644 index 00000000..02c2a966 --- /dev/null +++ b/PxWeb/Mappers/DatasetMapper.cs @@ -0,0 +1,484 @@ +using System.Linq; +using System.Text; + +using Microsoft.Extensions.Options; + +using PCAxis.Metadata; +using PCAxis.Paxiom; +using PCAxis.Paxiom.Extensions; + +using PxWeb.Api2.Server.Models; +using PxWeb.Models.Api2; + +using Value = PCAxis.Paxiom.Value; + +namespace PxWeb.Mappers +{ + public class DatasetMapper : IDatasetMapper + { + private readonly ILinkCreator _linkCreator; + private readonly PxApiConfigurationOptions _configOptions; + private string _language; + + private readonly MetaLinkManager _metaLinkManager = new MetaLinkManager(); + + public DatasetMapper(ILinkCreator linkCreator, IOptions configOptions) + { + _linkCreator = linkCreator; + _configOptions = configOptions.Value; + _language = _configOptions.DefaultLanguage; + } + + public Dataset Map(PXModel model, string id, string language) + { + + _language = language; + + DatasetSubclass dataset = new DatasetSubclass(); + + AddUpdated(model, dataset); + + //Source + dataset.AddSource(model.Meta.Source); + + //Label + dataset.AddLabel(model.Meta.Title); + + //Extension PX + AddPxToExtension(model, dataset); + + // Dimension + //Handle Elminated content variable + + if (model.Meta.ContentVariable == null) + { + AddInfoForEliminatedContentVariable(model, dataset); + } + + foreach (var variable in model.Meta.Variables) + { + //temporary collector storage + var metaIdsHelper = new Dictionary(); + + dataset.AddDimensionValue(variable.Code, variable.Name, out var dimensionValue); + + var indexCounter = 0; + + foreach (var variableValue in variable.Values) + { + dimensionValue.Category.Label.Add(variableValue.Code, variableValue.Value); + dimensionValue.Category.Index.Add(variableValue.Code, indexCounter++); + + CollectMetaIdsForValue(variableValue, ref metaIdsHelper); + + // ValueNote + AddValueNotes(variableValue, dataset, dimensionValue); + + + //Codelists + var codeLists = new System.Collections.Generic.List(); + MapCodelists(codeLists, variable); + if (codeLists != null) + { + dataset.AddCodelist(dimensionValue, codeLists); + } + + if (!variable.IsContentVariable) continue; + + var unitDecimals = (variableValue.HasPrecision()) ? variableValue.Precision : model.Meta.ShowDecimals; + dataset.AddUnitValue(dimensionValue.Category, out var unitValue); + + if (variableValue.ContentInfo != null) + { + unitValue.Base = variableValue.ContentInfo.Units; + unitValue.Decimals = unitDecimals; + + //refPeriod extension dimension + dataset.AddRefPeriod(dimensionValue, variableValue.Code, variableValue.ContentInfo.RefPeriod); + + // Contact + AddContact(dataset, variableValue.ContentInfo); + } + else + { + //TODO + // _logger.Warn("Category" + variableValue.Code + " lacks ContentInfo. Unit, refPeriod and contact not set"); + } + + dimensionValue.Category.Unit.Add(variableValue.Code, unitValue); + } + + //elimination + AddEliminationInfo(dimensionValue, variable); + + //Show + AddShow(dimensionValue, variable); + + //Variable notes + AddVariableNotes(variable, dataset, dimensionValue); + + CollectMetaIdsForVariable(variable, ref metaIdsHelper); + + if (metaIdsHelper.Count > 0) + { + dataset.AddDimensionLink(dimensionValue, metaIdsHelper); + } + + dataset.Size.Add(variable.Values.Count); + dataset.Id.Add(variable.Code); + + //Role + AddRoles(variable, dataset); + } + + AddTableNotes(model, dataset); + + List linksOnRoot = new List(); + linksOnRoot.Add(_linkCreator.GetTableMetadataJsonLink(LinkCreator.LinkRelationEnum.self, id.ToUpper(), language, true)); + linksOnRoot.Add(_linkCreator.GetTableDataLink(LinkCreator.LinkRelationEnum.data, id.ToUpper(), language, true)); + + //"type": "application/json" + + // TODO: Links to documentation + //if (!string.IsNullOrEmpty(model.Meta.MetaId)) + //{ + //} + + dataset.AddLinksOnRoot(linksOnRoot); + + + return dataset; + } + + + private void AddInfoForEliminatedContentVariable(PXModel model, DatasetSubclass dataset) + { + dataset.AddDimensionValue("ContentsCode", "EliminatedContents", out var dimensionValue); + dimensionValue.Category.Label.Add("EliminatedValue", model.Meta.Contents); + dimensionValue.Category.Index.Add("EliminatedValue", 0); + + dataset.AddUnitValue(dimensionValue.Category, out var unitValue); + unitValue.Base = model.Meta.ContentInfo.Units; + unitValue.Decimals = model.Meta.Decimals; + + dimensionValue.Category.Unit.Add("EliminatedValue", unitValue); + + dimensionValue.Extension.Elimination = true; + + //refPeriod extension dimension + dataset.AddRefPeriod(dimensionValue, "EliminatedValue", model.Meta.ContentInfo.RefPeriod); + + // Contact + AddContact(dataset, model.Meta.ContentInfo); + } + + private void AddUpdated(PXModel model, DatasetSubclass dataset) + { + DateTime tempDateTime; + if (model.Meta.ContentVariable != null && model.Meta.ContentVariable.Values.Count > 0) + { + var lastUpdatedContentsVariable = model.Meta.ContentVariable.Values + .OrderByDescending(x => x.ContentInfo.LastUpdated) + .FirstOrDefault(); + + // ReSharper disable once PossibleNullReferenceException + tempDateTime = lastUpdatedContentsVariable.ContentInfo.LastUpdated.PxDateStringToDateTime(); + } + else if (model.Meta.ContentInfo.LastUpdated != null) + { + tempDateTime = model.Meta.ContentInfo.LastUpdated.PxDateStringToDateTime(); + } + else + { + tempDateTime = model.Meta.CreationDate.PxDateStringToDateTime(); + } + + dataset.SetUpdatedAsUtcString(tempDateTime); + + /* + if (contInfo.LastUpdated.IsPxDate()) + { + DateTime tryDate = contInfo.LastUpdated.PxDateStringToDateTime().ToUniversalTime(); + if (tm.Updated == null || tryDate > tm.Updated) + { + tm.Updated = tryDate; + } + } + */ + } + + private void AddPxToExtension(PXModel model, DatasetSubclass dataset) + { + // TODO should we have included both Decimals and ShowDecimals? + var decimals = model.Meta.ShowDecimals < 0 ? model.Meta.Decimals : model.Meta.ShowDecimals; + + dataset.AddInfoFile(model.Meta.InfoFile); + dataset.AddTableId(model.Meta.TableID); + dataset.AddDecimals(decimals); + dataset.AddContents(model.Meta.Contents); + dataset.AddDescription(model.Meta.Description); + dataset.AddDescriptiondefault(model.Meta.DescriptionDefault); + dataset.AddStub(model.Meta.Stub.Select(v => v.Name).ToList()); + dataset.AddHeading(model.Meta.Heading.Select(v => v.Name).ToList()); + dataset.AddLanguage(model.Meta.Language); + dataset.AddOfficialStatistics(model.Meta.OfficialStatistics); + dataset.AddMatrix(model.Meta.Matrix); + dataset.AddSubjectCode(model.Meta.SubjectCode); + dataset.AddSubjectArea(model.Meta.SubjectArea); + dataset.AddAggRegAllowed(model.Meta.AggregAllowed); + } + + private void AddTableNotes(PXModel model, DatasetSubclass dataset) + { + var notes = model.Meta.Notes.Where(note => note.Type == NoteType.Table); + + var noteIndex = 0; + foreach (var note in notes) + { + + dataset.AddTableNote(note.Text); + + if (note.Mandantory) + dataset.AddIsMandatoryForTableNote(noteIndex.ToString()); + + noteIndex++; + + } + } + + private void AddEliminationInfo(DatasetDimensionValue dimensionValue, Variable variable) + { + dimensionValue.Extension.Elimination = variable.Elimination; + + if (!variable.Elimination || variable.EliminationValue == null) return; + + if (string.IsNullOrEmpty(variable.EliminationValue.Code)) return; + dimensionValue.Extension.EliminationValueCode = variable.EliminationValue.Code; + } + + private void AddShow(DatasetDimensionValue dimensionValue, Variable variable) + { + if (Enum.TryParse(variable.PresentationText.ToString(), out PresentationFormType presentationForm)) + { + dimensionValue.Extension.Show = presentationForm.ToString().ToLower(); + } + } + + private void AddValueNotes(Value variableValue, DatasetSubclass dataset, DatasetDimensionValue dimensionValue) + { + if (variableValue.Notes == null) return; + + var index = 0; + foreach (var note in variableValue.Notes) + { + //dataset.AddValueNoteToDimension(dimensionValue, variableValue.Code, note.Mandantory, note.Text); + dataset.AddValueNoteToCategory(dimensionValue, variableValue.Code, note.Text); + + if (note.Mandantory) + dataset.AddIsMandatoryForCategoryNote(dimensionValue, variableValue.Code, index.ToString()); + + index++; + } + } + + private void AddVariableNotes(Variable variable, DatasetSubclass dataset, DatasetDimensionValue dimensionValue) + { + if (variable.Notes == null) return; + + var noteIndex = 0; + foreach (var note in variable.Notes) + { + dataset.AddNoteToDimension(dimensionValue, note.Text); + + if (note.Mandantory) + dataset.AddIsMandatoryForDimensionNote(dimensionValue, noteIndex.ToString()); + + noteIndex++; + } + } + + private void AddContact(DatasetSubclass dataset, ContInfo contInfo) + { + if (contInfo.ContactInfo != null && contInfo.ContactInfo.Count > 0) + { + foreach (var contact in contInfo.ContactInfo) + { + MapContact(dataset, contact, contInfo); + } + } + else + { + MapContact(dataset, contInfo.Contact); + } + } + + private void MapContact(DatasetSubclass dataset, PCAxis.Paxiom.Contact contact, ContInfo contInfo) + { + + if (dataset.Extension.Contact == null) + { + dataset.Extension.Contact = new List(); + } + + StringBuilder sb = new StringBuilder(); + sb.Append(contact.Forname); + sb.Append(" "); + sb.Append(contact.Surname); + + Api2.Server.Models.Contact jsonContact = new Api2.Server.Models.Contact + { + Name = sb.ToString(), + Mail = contact.Email, + Phone = contact.PhoneNo + }; + + if (contInfo.Contact != null) + { + var contacts = contInfo.Contact.Split(new[] { "##" }, StringSplitOptions.RemoveEmptyEntries); + var res = contacts.Where(x => x.Contains(contact.Forname) && x.Contains(contact.Surname) && x.Contains(contact.Email) && x.Contains(contact.PhoneNo)).FirstOrDefault(); + + if (res != null) + { + jsonContact.Raw = res; + } + } + + // Only display unique contact once + if (!dataset.Extension.Contact.Exists(x => x.Mail.Equals(jsonContact.Mail) && x.Name.Equals(jsonContact.Name) && x.Phone.Equals(jsonContact.Phone))) + { + dataset.Extension.Contact.Add(jsonContact); + } + } + + private void MapContact(DatasetSubclass dataset, string contactString) + { + if (contactString != null) + { + if (dataset.Extension.Contact == null) + { + dataset.Extension.Contact = new List(); + } + + var contacts = contactString.Split(new[] { "##" }, StringSplitOptions.RemoveEmptyEntries); + + foreach (var contact in contacts) + { + if (!dataset.Extension.Contact.Exists(x => x.Raw.Equals(contact))) + { + dataset.Extension.Contact.Add(new Api2.Server.Models.Contact + { + Raw = contact + }); + } + } + } + } + + private void AddRoles(Variable variable, DatasetSubclass dataset) + { + if (variable.IsTime) + { + dataset.AddToTimeRole(variable.Code); + } + + if (variable.IsContentVariable) + { + dataset.AddToMetricRole(variable.Code); + } + + if (variable.VariableType == null) return; + if (variable.VariableType.ToUpper() == "G" || (variable.Map != null)) + { + dataset.AddToGeoRole(variable.Code); + } + } + + private void CollectMetaIdsForVariable(Variable variable, ref Dictionary metaIds) + { + if (!string.IsNullOrWhiteSpace(variable.MetaId)) + { + metaIds.Add(variable.Code, SerializeMetaIds(variable.MetaId)); + } + } + + private void CollectMetaIdsForValue(Value value, ref Dictionary metaIds) + { + if (!string.IsNullOrWhiteSpace(value.MetaId)) + { + metaIds.Add(value.Code, SerializeMetaIds(value.MetaId)); + } + } + + private string SerializeMetaIds(string metaId) + { + var metaIds = metaId.Split(_metaLinkManager.GetSystemSeparator(), StringSplitOptions.RemoveEmptyEntries); + var metaIdsAsString = new List(); + foreach (var meta in metaIds) + { + var metaLinks = meta.Split(_metaLinkManager.GetParamSeparator(), StringSplitOptions.RemoveEmptyEntries); + if (metaLinks.Length > 0) + { + metaIdsAsString.Add(meta); + } + } + return (string.Join(" ", metaIdsAsString)); + } + + + + // TODO: HIERARCHIES(“Country”)="parent","parent":"child", (I think child in dimention for jsonstat) + + // TODO: the below is cloned from TableMetadataResponseMapper, should be moved to common class + + + + private Api2.Server.Models.CodeListInformation Map(PCAxis.Paxiom.GroupingInfo grouping) + { + CodeListInformation codelist = new CodeListInformation(); + + codelist.Id = "agg_" + grouping.ID; + codelist.Label = grouping.Name; + codelist.Type = CodeListType.AggregationEnum; + codelist.Links = new System.Collections.Generic.List(); + codelist.Links.Add(_linkCreator.GetCodelistLink(LinkCreator.LinkRelationEnum.metadata, codelist.Id, _language)); + + return codelist; + } + private Api2.Server.Models.CodeListInformation Map(PCAxis.Paxiom.ValueSetInfo valueset) + { + CodeListInformation codelist = new CodeListInformation(); + + codelist.Id = "vs_" + valueset.ID; + codelist.Label = valueset.Name; + codelist.Type = CodeListType.ValuesetEnum; + codelist.Links = new System.Collections.Generic.List(); + codelist.Links.Add(_linkCreator.GetCodelistLink(LinkCreator.LinkRelationEnum.metadata, codelist.Id, _language)); + + return codelist; + } + + + private void MapCodelists(System.Collections.Generic.List codelists, Variable variable) + { + if (variable.HasGroupings()) + { + foreach (var grouping in variable.Groupings) + { + codelists.Add(Map(grouping)); + } + } + + if (variable.HasValuesets()) + { + foreach (var valueset in variable.ValueSets) + { + if (!valueset.ID.Equals("_ALL_")) + { + codelists.Add(Map(valueset)); + } + } + } + } + + } +} diff --git a/PxWeb/Mappers/IDatasetMapper.cs b/PxWeb/Mappers/IDatasetMapper.cs new file mode 100644 index 00000000..e167d63d --- /dev/null +++ b/PxWeb/Mappers/IDatasetMapper.cs @@ -0,0 +1,11 @@ +using PCAxis.Paxiom; + +using PxWeb.Api2.Server.Models; + +namespace PxWeb.Mappers +{ + public interface IDatasetMapper + { + Dataset Map(PXModel model, string id, string language); + } +} diff --git a/PxWeb/Models/Api2/DatasetSubclass.cs b/PxWeb/Models/Api2/DatasetSubclass.cs new file mode 100644 index 00000000..4f0056f8 --- /dev/null +++ b/PxWeb/Models/Api2/DatasetSubclass.cs @@ -0,0 +1,314 @@ +using System.Globalization; + +using PxWeb.Api2.Server.Models; + +namespace PxWeb.Models.Api2 +{ + + public class DatasetSubclass : Dataset + { + public DatasetSubclass() + { + Id = new List(); + Size = new List(); + Class = ClassType.DatasetEnum; + Role = new DatasetRole(); + Extension = new ExtensionRoot(); + Extension.Px = new ExtensionRootPx(); + } + + public void AddToTimeRole(string variableCode) + { + if (Role.Time == null) + { + Role.Time = new List(); + } + + Role.Time.Add(variableCode); + } + + public void AddToMetricRole(string variableCode) + { + if (Role.Metric == null) + { + Role.Metric = new List(); + } + + Role.Metric.Add(variableCode); + } + + public void AddToGeoRole(string variableCode) + { + if (Role.Geo == null) + { + Role.Geo = new List(); + } + + Role.Geo.Add(variableCode); + } + + public void AddInfoFile(string infoFile) + { + if (infoFile != null) + { + Extension.Px.Infofile = infoFile; + } + } + + public void AddTableId(string tableId) + { + if (tableId != null) + { + Extension.Px.Tableid = tableId; + } + } + + public void AddDecimals(int decimals) + { + if (decimals != -1) + { + Extension.Px.Decimals = decimals; + } + } + + public void AddLanguage(string language) + { + if (language != null) + { + Extension.Px.Language = language; + } + } + + public void AddContents(string contents) + { + if (contents != null) + { + Extension.Px.Contents = contents; + } + } + + public void AddHeading(List heading) + { + if (heading != null) + { + Extension.Px.Heading = heading; + } + } + public void AddStub(List stub) + { + if (stub != null) + { + Extension.Px.Stub = stub; + } + } + public void AddOfficialStatistics(bool isOfficialStatistics) + { + Extension.Px.OfficialStatistics = isOfficialStatistics; + } + + public void AddMatrix(string matrix) + { + if (matrix != null) + { + Extension.Px.Matrix = matrix; + } + } + + public void AddSubjectCode(string subjectCode) + { + if (subjectCode != null) + { + Extension.Px.SubjectCode = subjectCode; + } + } + + public void AddSubjectArea(string subjectArea) + { + if (subjectArea != null) + { + Extension.Px.SubjectArea = subjectArea; + } + } + + public void AddAggRegAllowed(bool isAggRegAllowed) + { + Extension.Px.Aggregallowed = isAggRegAllowed; + } + + public void AddDescription(string description) + { + if (description != null) + { + Extension.Px.Description = description; + } + } + + public void AddDescriptiondefault(bool isDescriptiondefault) + { + Extension.Px.Descriptiondefault = isDescriptiondefault; + } + + public void AddSource(string source) + { + if (source != null) + { + Source = source; + } + } + + public void AddLabel(string label) + { + if (label != null) + { + Label = label; + } + } + + public void AddTableNote(string text) + { + if (text != null) + { + if (Note == null) Note = new List(); + Note.Add(text); + } + } + + public void AddIsMandatoryForTableNote(string index) + { + if (Extension.NoteMandatory == null) Extension.NoteMandatory = new Dictionary(); + + Extension.NoteMandatory.Add(index, true); + } + + public void AddDimensionValue(string dimensionKey, string label, out DatasetDimensionValue dimensionValue) + { + if (Dimension == null) Dimension = new Dictionary(); + + dimensionValue = new DatasetDimensionValue() + { + Label = label, + Extension = new ExtensionDimension(), + Category = new JsonstatCategory() + { + Label = new Dictionary(), + Index = new Dictionary() + } + }; + Dimension.Add(dimensionKey, dimensionValue); + } + + public void AddNoteToDimension(DatasetDimensionValue dimensionValue, string text) + { + if (dimensionValue.Note == null) dimensionValue.Note = new List(); + + dimensionValue.Note.Add(text); + } + + public void AddIsMandatoryForDimensionNote(DatasetDimensionValue dimensionValue, string index) + { + if (dimensionValue.Extension.NoteMandatory == null) dimensionValue.Extension.NoteMandatory = new Dictionary(); + + dimensionValue.Extension.NoteMandatory.Add(index, true); + } + + public void AddValueNoteToCategory(DatasetDimensionValue dimensionValue, string valueNoteKey, string text) + { + if (dimensionValue.Category.Note == null) dimensionValue.Category.Note = new Dictionary>(); + + if (dimensionValue.Category.Note.ContainsKey(valueNoteKey)) + { + dimensionValue.Category.Note[valueNoteKey] + .Add(text); + } + else + { + dimensionValue.Category.Note.Add(valueNoteKey, + new List { text }); + } + } + + public void AddIsMandatoryForCategoryNote(DatasetDimensionValue dimensionValue, string valueNoteKey, string index) + { + if (dimensionValue.Extension.CategoryNoteMandatory == null) dimensionValue.Extension.CategoryNoteMandatory = new Dictionary>(); + + if (dimensionValue.Extension.CategoryNoteMandatory.ContainsKey(valueNoteKey)) + { + dimensionValue.Extension.CategoryNoteMandatory[valueNoteKey] + .Add(index, true); + } + else + { + dimensionValue.Extension.CategoryNoteMandatory.Add(valueNoteKey, + new Dictionary { { index, true } }); + } + } + + public void AddUnitValue(JsonstatCategory category, out JsonstatCategoryUnitValue unitValue) + { + if (category.Unit == null) category.Unit = new Dictionary(); + + unitValue = new JsonstatCategoryUnitValue(); + } + + public void AddRefPeriod(DatasetDimensionValue dimensionValue, string valueCode, string refPeriod) + { + if (refPeriod == null) return; + + if (dimensionValue.Extension.Refperiod == null) + dimensionValue.Extension.Refperiod = new Dictionary(); + + dimensionValue.Extension.Refperiod.Add(valueCode, refPeriod); + } + + public void AddDimensionLink(DatasetDimensionValue dimensionValue, Dictionary metaIds) + { + dimensionValue.Link = new JsonstatExtensionLink + { + Describedby = new List() { new DimensionExtension() { Extension = metaIds } } + }; + + } + + public void AddCodelist(DatasetDimensionValue dimensionValue, List codeLists) + { + if (dimensionValue.Extension.CodeLists == null) + { + dimensionValue.Extension.CodeLists = new List(); + } + dimensionValue.Extension.CodeLists.AddRange(codeLists); + } + + public void AddLinksOnRoot(List links) + { + + foreach (Link link in links) + { + if (link.Rel == "self") + { + this.Href = link.Href + "&outputFormat=json-stat2"; + } + else + { + this.Link ??= new Dictionary>(); + if (!this.Link.ContainsKey(link.Rel)) + { + this.Link[link.Rel] = new List(); + } + JsonstatLink linkLink = new JsonstatLink(); + linkLink.Href = link.Href; + this.Link[link.Rel].Add(linkLink); + } + + } + + + } + + + + public void SetUpdatedAsUtcString(DateTime datetime) + { + Updated = datetime.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture); + } + } +} diff --git a/PxWeb/Program.cs b/PxWeb/Program.cs index 03315b70..e19fc7ac 100644 --- a/PxWeb/Program.cs +++ b/PxWeb/Program.cs @@ -87,6 +87,7 @@ public static void Main(string[] args) builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); + builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); diff --git a/PxWebApi.BigTests/TableController/TableApiControllerTest.cs b/PxWebApi.BigTests/TableController/TableApiControllerTest.cs index bb88a107..3b74be38 100644 --- a/PxWebApi.BigTests/TableController/TableApiControllerTest.cs +++ b/PxWebApi.BigTests/TableController/TableApiControllerTest.cs @@ -153,6 +153,7 @@ private PxWeb.Controllers.Api2.TableApiController GetController() ILinkCreator linkCreator = new LinkCreator(pxApiConfigurationOptions); ITableMetadataResponseMapper responseMapper = new TableMetadataResponseMapper(linkCreator, pxApiConfigurationOptions); + IDatasetMapper datasetMapper = new DatasetMapper(linkCreator, pxApiConfigurationOptions); IOptions luceneConfigurationOptions = Util.GetIOptions(configuration, "LuceneConfiguration"); ILuceneConfigurationService luceneConfigurationService = new LuceneConfigurationService(luceneConfigurationOptions, hostingEnvironmentMock.Object); @@ -167,7 +168,7 @@ private PxWeb.Controllers.Api2.TableApiController GetController() ISelectionResponseMapper selectionResponseMapper = new SelectionResponseMapper(linkCreator); - return new PxWeb.Controllers.Api2.TableApiController(iDataSource, languageHelper, responseMapper, + return new PxWeb.Controllers.Api2.TableApiController(iDataSource, languageHelper, responseMapper, datasetMapper, backend, pxApiConfigurationOptions, tablesResponseMapper, tableResponseMapper, codelistResponseMapper, selectionResponseMapper, serializeManager, selectionHandler);