diff --git a/PostalRegistry.sln.DotSettings b/PostalRegistry.sln.DotSettings
index e98ba642..59c37cee 100644
--- a/PostalRegistry.sln.DotSettings
+++ b/PostalRegistry.sln.DotSettings
@@ -1,6 +1,7 @@
True
<Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="" Style="aa_bb" /></Policy>
+ <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Types and namespaces"><ElementKinds><Kind Name="NAMESPACE" /><Kind Name="CLASS" /><Kind Name="STRUCT" /><Kind Name="ENUM" /><Kind Name="DELEGATE" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="" Style="aa_bb" /></Policy></Policy>
<Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
<Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
<Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
@@ -65,4 +66,5 @@
True
True
True
+ True
diff --git a/src/PostalRegistry.Api.Oslo/Convertors/PostalInformationStatus.cs b/src/PostalRegistry.Api.Oslo/Convertors/PostalInformationStatus.cs
new file mode 100644
index 00000000..60157775
--- /dev/null
+++ b/src/PostalRegistry.Api.Oslo/Convertors/PostalInformationStatus.cs
@@ -0,0 +1,20 @@
+namespace PostalRegistry.Api.Oslo.Convertors
+{
+ using Be.Vlaanderen.Basisregisters.GrAr.Legacy;
+
+ public static class PostalInformationStatusExtensions
+ {
+ public static PostInfoStatus ConvertFromPostalInformationStatus(this PostalInformationStatus postalInformationStatus)
+ {
+ switch (postalInformationStatus)
+ {
+ case PostalInformationStatus.Retired:
+ return PostInfoStatus.Gehistoreerd;
+
+ default:
+ case PostalInformationStatus.Current:
+ return PostInfoStatus.Gerealiseerd;
+ }
+ }
+ }
+}
diff --git a/src/PostalRegistry.Api.Oslo/Infrastructure/Options/AtomFeedConfigurationBuilder.cs b/src/PostalRegistry.Api.Oslo/Infrastructure/Options/AtomFeedConfigurationBuilder.cs
new file mode 100644
index 00000000..0a097670
--- /dev/null
+++ b/src/PostalRegistry.Api.Oslo/Infrastructure/Options/AtomFeedConfigurationBuilder.cs
@@ -0,0 +1,37 @@
+namespace PostalRegistry.Api.Oslo.Infrastructure
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Reflection;
+ using Be.Vlaanderen.Basisregisters.Api.Syndication;
+ using Microsoft.Extensions.Configuration;
+ using Microsoft.SyndicationFeed;
+ using Microsoft.SyndicationFeed.Atom;
+
+ public static class AtomFeedConfigurationBuilder
+ {
+ public static AtomFeedConfiguration CreateFrom(IConfigurationSection configuration, DateTimeOffset lastUpdated)
+ {
+ return new AtomFeedConfiguration(
+ configuration["Id"],
+ configuration["Title"],
+ configuration["Subtitle"],
+ configuration["GeneratorTitle"],
+ configuration["GeneratorUri"],
+ Assembly.GetEntryAssembly().GetName().Version.ToString(),
+ configuration["Rights"],
+ lastUpdated,
+ new SyndicationPerson(configuration["AuthorName"], configuration["AuthorEmail"], AtomContributorTypes.Author),
+ new SyndicationLink(new Uri(configuration["Self"]), AtomLinkTypes.Self),
+ new List(),
+ configuration
+ .GetSection("Related")
+ .GetChildren()
+ .Select(c =>
+ new SyndicationLink(new Uri(c.Value), AtomLinkTypes.Related))
+ .ToList()
+ );
+ }
+ }
+}
diff --git a/src/PostalRegistry.Api.Oslo/PostalInformation/PostalInformationOsloController.cs b/src/PostalRegistry.Api.Oslo/PostalInformation/PostalInformationOsloController.cs
index aba8ccec..d3be61b2 100644
--- a/src/PostalRegistry.Api.Oslo/PostalInformation/PostalInformationOsloController.cs
+++ b/src/PostalRegistry.Api.Oslo/PostalInformation/PostalInformationOsloController.cs
@@ -2,8 +2,11 @@ namespace PostalRegistry.Api.Oslo.PostalInformation
{
using System;
using System.Linq;
+ using System.Net.Mime;
+ using System.Text;
using System.Threading;
using System.Threading.Tasks;
+ using System.Xml;
using Asp.Versioning;
using Be.Vlaanderen.Basisregisters.Api;
using Be.Vlaanderen.Basisregisters.Api.Exceptions;
@@ -11,16 +14,22 @@ namespace PostalRegistry.Api.Oslo.PostalInformation
using Be.Vlaanderen.Basisregisters.Api.Search.Filtering;
using Be.Vlaanderen.Basisregisters.Api.Search.Pagination;
using Be.Vlaanderen.Basisregisters.Api.Search.Sorting;
+ using Be.Vlaanderen.Basisregisters.Api.Syndication;
using Be.Vlaanderen.Basisregisters.GrAr.Common;
+ using Be.Vlaanderen.Basisregisters.GrAr.Common.Syndication;
using Be.Vlaanderen.Basisregisters.GrAr.Legacy;
using Be.Vlaanderen.Basisregisters.GrAr.Legacy.Gemeente;
using Be.Vlaanderen.Basisregisters.GrAr.Legacy.PostInfo;
using Convertors;
+ using Infrastructure;
using Infrastructure.Options;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
+ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
+ using Microsoft.SyndicationFeed;
+ using Microsoft.SyndicationFeed.Atom;
using Nuts;
using Projections.Legacy;
using Projections.Syndication;
@@ -196,6 +205,92 @@ public async Task Count(
});
}
+ ///
+ /// Vraag een lijst met wijzigingen van postinfo op.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpGet("sync")]
+ [Produces("text/xml")]
+ [ProducesResponseType(typeof(string), StatusCodes.Status200OK)]
+ [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
+ [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)]
+ [SwaggerResponseExample(StatusCodes.Status200OK, typeof(PostalInformationSyndicationResponseExamples))]
+ [SwaggerResponseExample(StatusCodes.Status400BadRequest, typeof(BadRequestResponseExamples))]
+ [SwaggerResponseExample(StatusCodes.Status500InternalServerError, typeof(InternalServerErrorResponseExamples))]
+ public async Task Sync(
+ [FromServices] IConfiguration configuration,
+ [FromServices] LegacyContext context,
+ [FromServices] IOptions responseOptions,
+ CancellationToken cancellationToken = default)
+ {
+ var filtering = Request.ExtractFilteringRequest();
+ var sorting = Request.ExtractSortingRequest();
+ var pagination = Request.ExtractPaginationRequest();
+
+ var lastFeedUpdate = await context
+ .PostalInformationSyndication
+ .AsNoTracking()
+ .OrderByDescending(item => item.Position)
+ .Select(item => item.SyndicationItemCreatedAt)
+ .FirstOrDefaultAsync(cancellationToken);
+
+ if (lastFeedUpdate == default)
+ lastFeedUpdate = new DateTimeOffset(2020, 1, 1, 0, 0, 0, TimeSpan.Zero);
+
+ var pagedPostalInformationSet =
+ new PostalInformationSyndicationQuery(
+ context,
+ filtering.Filter?.Embed)
+ .Fetch(filtering, sorting, pagination);
+
+ return new ContentResult
+ {
+ Content = await BuildAtomFeed(lastFeedUpdate, pagedPostalInformationSet, responseOptions, configuration),
+ ContentType = MediaTypeNames.Text.Xml,
+ StatusCode = StatusCodes.Status200OK
+ };
+ }
+
+ private static async Task BuildAtomFeed(
+ DateTimeOffset lastFeedUpdate,
+ PagedQueryable pagedPostalInfoItems,
+ IOptions responseOptions,
+ IConfiguration configuration)
+ {
+ var sw = new StringWriterWithEncoding(Encoding.UTF8);
+
+ using (var xmlWriter = XmlWriter.Create(sw, new XmlWriterSettings { Async = true, Indent = true, Encoding = sw.Encoding }))
+ {
+ var formatter = new AtomFormatter(null, xmlWriter.Settings) { UseCDATA = true };
+ var writer = new AtomFeedWriter(xmlWriter, null, formatter);
+ var syndicationConfiguration = configuration.GetSection("Syndication");
+ var atomFeedConfig = AtomFeedConfigurationBuilder.CreateFrom(syndicationConfiguration, lastFeedUpdate);
+
+ await writer.WriteDefaultMetadata(atomFeedConfig);
+
+ var postalInfos = pagedPostalInfoItems.Items.ToList();
+
+ var nextFrom = postalInfos.Any()
+ ? postalInfos.Max(x => x.Position) + 1
+ : (long?) null;
+
+ var nextUri = BuildNextSyncUri(pagedPostalInfoItems.PaginationInfo.Limit, nextFrom, syndicationConfiguration["NextUri"]);
+ if (nextUri != null)
+ await writer.Write(new SyndicationLink(nextUri, GrArAtomLinkTypes.Next));
+
+ foreach (var postalInfo in postalInfos)
+ await writer.WritePostalInfo(responseOptions, formatter, syndicationConfiguration["Category"], postalInfo);
+
+ xmlWriter.Flush();
+ }
+
+ return sw.ToString();
+ }
+
private static Uri? BuildNextUri(PaginationInfo paginationInfo, int itemsInCollection, string nextUrlBase)
{
var offset = paginationInfo.Offset;
@@ -206,6 +301,13 @@ public async Task Count(
: null;
}
+ private static Uri? BuildNextSyncUri(int limit, long? from, string nextUrlBase)
+ {
+ return from.HasValue
+ ? new Uri(string.Format(nextUrlBase, from.Value, limit))
+ : null;
+ }
+
private async Task GetPostinfoDetailGemeente(
SyndicationContext syndicationContext,
string? nisCode,
diff --git a/src/PostalRegistry.Api.Oslo/PostalInformation/Query/PostalInformationSyndicationQuery.cs b/src/PostalRegistry.Api.Oslo/PostalInformation/Query/PostalInformationSyndicationQuery.cs
new file mode 100644
index 00000000..7d0de240
--- /dev/null
+++ b/src/PostalRegistry.Api.Oslo/PostalInformation/Query/PostalInformationSyndicationQuery.cs
@@ -0,0 +1,240 @@
+namespace PostalRegistry.Api.Oslo.PostalInformation.Query
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Linq.Expressions;
+ using Be.Vlaanderen.Basisregisters.Api.Search;
+ using Be.Vlaanderen.Basisregisters.Api.Search.Filtering;
+ using Be.Vlaanderen.Basisregisters.Api.Search.Sorting;
+ using Be.Vlaanderen.Basisregisters.GrAr.Provenance;
+ using Microsoft.EntityFrameworkCore;
+ using NodaTime;
+ using Projections.Legacy;
+ using Projections.Legacy.PostalInformationSyndication;
+
+ public class PostalInformationSyndicationQueryResult
+ {
+ public bool ContainsEvent { get; }
+ public bool ContainsObject { get; }
+
+ public string PostalCode { get; }
+ public long Position { get; }
+ public string ChangeType { get; }
+
+ public Instant RecordCreatedAt { get; }
+ public Instant LastChangedOn { get; }
+ public PostalInformationStatus? Status { get; }
+ public IEnumerable PostalNames { get; }
+ public string MunicipalityNisCode { get; }
+ public Organisation? Organisation { get; }
+ public string Reason { get; }
+ public string EventDataAsXml { get; }
+
+ public PostalInformationSyndicationQueryResult(
+ string postalCode,
+ long position,
+ string changeType,
+ Instant recordCreatedAt,
+ Instant lastChangedOn,
+ string municipalityNisCode,
+ Organisation? organisation,
+ string reason)
+ {
+ ContainsEvent = false;
+ ContainsObject = false;
+
+ PostalCode = postalCode;
+ Position = position;
+ ChangeType = changeType;
+ RecordCreatedAt = recordCreatedAt;
+ LastChangedOn = lastChangedOn;
+ MunicipalityNisCode = municipalityNisCode;
+ Organisation = organisation;
+ Reason = reason;
+ }
+
+ public PostalInformationSyndicationQueryResult(
+ string postalCode,
+ long position,
+ string changeType,
+ Instant recordCreatedAt,
+ Instant lastChangedOn,
+ string municipalityNisCode,
+ Organisation? organisation,
+ string reason,
+ string eventDataAsXml)
+ : this(postalCode,
+ position,
+ changeType,
+ recordCreatedAt,
+ lastChangedOn,
+ municipalityNisCode,
+ organisation,
+ reason)
+ {
+ ContainsEvent = true;
+
+ EventDataAsXml = eventDataAsXml;
+ }
+
+ public PostalInformationSyndicationQueryResult(
+ string postalCode,
+ long position,
+ string changeType,
+ Instant recordCreatedAt,
+ Instant lastChangedOn,
+ PostalInformationStatus? status,
+ IEnumerable postalNames,
+ string municipalityNisCode,
+ Organisation? organisation,
+ string reason) :
+ this(
+ postalCode,
+ position,
+ changeType,
+ recordCreatedAt,
+ lastChangedOn,
+ municipalityNisCode,
+ organisation,
+ reason)
+ {
+ ContainsObject = true;
+
+ Status = status;
+ PostalNames = postalNames;
+ }
+
+ public PostalInformationSyndicationQueryResult(
+ string postalCode,
+ long position,
+ string changeType,
+ Instant recordCreatedAt,
+ Instant lastChangedOn,
+ PostalInformationStatus? status,
+ IEnumerable postalNames,
+ string municipalityNisCode,
+ Organisation? organisation,
+ string reason,
+ string eventDataAsXml)
+ : this(
+ postalCode,
+ position,
+ changeType,
+ recordCreatedAt,
+ lastChangedOn,
+ status,
+ postalNames,
+ municipalityNisCode,
+ organisation,
+ reason)
+ {
+ ContainsEvent = true;
+ EventDataAsXml = eventDataAsXml;
+ }
+ }
+
+ public class PostalInformationSyndicationQuery : Query
+ {
+ private readonly LegacyContext _context;
+ private readonly bool _embedEvent;
+ private readonly bool _embedObject;
+
+ public PostalInformationSyndicationQuery(LegacyContext context, SyncEmbedValue embed)
+ {
+ _context = context;
+ _embedEvent = embed?.Event ?? false;
+ _embedObject = embed?.Object ?? false;
+ }
+
+ protected override ISorting Sorting => new PostalInformationSyndicationSorting();
+
+ protected override Expression> Transformation
+ {
+ get
+ {
+ if (_embedEvent && _embedObject)
+ return syndicationItem => new PostalInformationSyndicationQueryResult(
+ syndicationItem.PostalCode,
+ syndicationItem.Position,
+ syndicationItem.ChangeType,
+ syndicationItem.RecordCreatedAt,
+ syndicationItem.LastChangedOn,
+ syndicationItem.Status,
+ syndicationItem.PostalNames,
+ syndicationItem.MunicipalityNisCode,
+ syndicationItem.Organisation,
+ syndicationItem.Reason,
+ syndicationItem.EventDataAsXml);
+
+ if (_embedEvent)
+ return syndicationItem => new PostalInformationSyndicationQueryResult(
+ syndicationItem.PostalCode,
+ syndicationItem.Position,
+ syndicationItem.ChangeType,
+ syndicationItem.RecordCreatedAt,
+ syndicationItem.LastChangedOn,
+ syndicationItem.MunicipalityNisCode,
+ syndicationItem.Organisation,
+ syndicationItem.Reason,
+ syndicationItem.EventDataAsXml);
+
+ if(_embedObject)
+ return syndicationItem => new PostalInformationSyndicationQueryResult(
+ syndicationItem.PostalCode,
+ syndicationItem.Position,
+ syndicationItem.ChangeType,
+ syndicationItem.RecordCreatedAt,
+ syndicationItem.LastChangedOn,
+ syndicationItem.Status,
+ syndicationItem.PostalNames,
+ syndicationItem.MunicipalityNisCode,
+ syndicationItem.Organisation,
+ syndicationItem.Reason);
+
+ return syndicationItem => new PostalInformationSyndicationQueryResult(
+ syndicationItem.PostalCode,
+ syndicationItem.Position,
+ syndicationItem.ChangeType,
+ syndicationItem.RecordCreatedAt,
+ syndicationItem.LastChangedOn,
+ syndicationItem.MunicipalityNisCode,
+ syndicationItem.Organisation,
+ syndicationItem.Reason);
+ }
+ }
+
+ protected override IQueryable Filter(FilteringHeader filtering)
+ {
+ var postalInformationSet = _context
+ .PostalInformationSyndication
+ .OrderBy(x => x.Position)
+ .AsNoTracking();
+
+ if (!filtering.ShouldFilter)
+ return postalInformationSet;
+
+ if (filtering.Filter.Position.HasValue)
+ postalInformationSet = postalInformationSet.Where(item => item.Position >= filtering.Filter.Position);
+
+ return postalInformationSet;
+ }
+ }
+
+ internal class PostalInformationSyndicationSorting : ISorting
+ {
+ public IEnumerable SortableFields { get; } = new[]
+ {
+ nameof(PostalInformationSyndicationItem.Position)
+ };
+
+ public SortingHeader DefaultSortingHeader { get; } = new SortingHeader(nameof(PostalInformationSyndicationItem.Position), SortOrder.Ascending);
+ }
+
+ public class PostalInformationSyndicationFilter
+ {
+ public long? Position { get; set; }
+ public SyncEmbedValue Embed { get; set; }
+ }
+}
diff --git a/src/PostalRegistry.Api.Oslo/PostalInformation/Responses/PostalInformationSyndicationResponse.cs b/src/PostalRegistry.Api.Oslo/PostalInformation/Responses/PostalInformationSyndicationResponse.cs
new file mode 100644
index 00000000..005a66cd
--- /dev/null
+++ b/src/PostalRegistry.Api.Oslo/PostalInformation/Responses/PostalInformationSyndicationResponse.cs
@@ -0,0 +1,240 @@
+namespace PostalRegistry.Api.Oslo.PostalInformation.Responses
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.Linq;
+ using System.Runtime.Serialization;
+ using System.Threading.Tasks;
+ using System.Xml;
+ using Be.Vlaanderen.Basisregisters.GrAr.Common;
+ using Be.Vlaanderen.Basisregisters.GrAr.Common.Syndication;
+ using Be.Vlaanderen.Basisregisters.GrAr.Legacy;
+ using Be.Vlaanderen.Basisregisters.GrAr.Legacy.PostInfo;
+ using Be.Vlaanderen.Basisregisters.GrAr.Provenance;
+ using Convertors;
+ using Infrastructure.Options;
+ using Microsoft.Extensions.Options;
+ using Microsoft.SyndicationFeed;
+ using Microsoft.SyndicationFeed.Atom;
+ using Query;
+ using Swashbuckle.AspNetCore.Filters;
+ using Provenance = Be.Vlaanderen.Basisregisters.GrAr.Provenance.Syndication.Provenance;
+
+ public static class PostalInformationSyndicationResponse
+ {
+ public static async Task WritePostalInfo(
+ this ISyndicationFeedWriter writer,
+ IOptions responseOptions,
+ AtomFormatter formatter,
+ string category,
+ PostalInformationSyndicationQueryResult postalInformation)
+ {
+ var item = new SyndicationItem
+ {
+ Id = postalInformation.Position.ToString(CultureInfo.InvariantCulture),
+ Title = $"{postalInformation.ChangeType}-{postalInformation.Position}",
+ Published = postalInformation.RecordCreatedAt.ToBelgianDateTimeOffset(),
+ LastUpdated = postalInformation.LastChangedOn.ToBelgianDateTimeOffset(),
+ Description = BuildDescription(postalInformation, responseOptions.Value.Naamruimte)
+ };
+
+ if (!string.IsNullOrWhiteSpace(postalInformation.PostalCode))
+ {
+ item.AddLink(
+ new SyndicationLink(
+ new Uri($"{responseOptions.Value.Naamruimte}/{postalInformation.PostalCode}"),
+ AtomLinkTypes.Related));
+
+ //item.AddLink(
+ // new SyndicationLink(
+ // new Uri(string.Format(responseOptions.Value.DetailUrl, postalInformation.PostalCode)),
+ // AtomLinkTypes.Self));
+
+ //item.AddLink(
+ // new SyndicationLink(
+ // new Uri(string.Format($"{responseOptions.Value.DetailUrl}.xml", postalInformation.PostalCode)),
+ // AtomLinkTypes.Alternate)
+ // { MediaType = MediaTypeNames.Application.Xml });
+
+ //item.AddLink(
+ // new SyndicationLink(
+ // new Uri(string.Format($"{responseOptions.Value.DetailUrl}.json", postalInformation.PostalCode)),
+ // AtomLinkTypes.Alternate)
+ // { MediaType = MediaTypeNames.Application.Json });
+ }
+
+ item.AddCategory(
+ new SyndicationCategory(category));
+
+ item.AddContributor(
+ new SyndicationPerson(
+ postalInformation.Organisation == null ? Organisation.Unknown.ToName() : postalInformation.Organisation.Value.ToName(),
+ string.Empty,
+ AtomContributorTypes.Author));
+
+ await writer.Write(item);
+ }
+
+ private static string BuildDescription(PostalInformationSyndicationQueryResult postalInformation, string naamruimte)
+ {
+ if (!postalInformation.ContainsEvent && !postalInformation.ContainsObject)
+ return "No data embedded";
+
+ var content = new SyndicationContent();
+ if (postalInformation.ContainsObject)
+ content.Object = new PostalInfoSyndicationContent(
+ naamruimte,
+ postalInformation.PostalCode,
+ postalInformation.LastChangedOn.ToBelgianDateTimeOffset(),
+ postalInformation.Status,
+ postalInformation.PostalNames,
+ postalInformation.MunicipalityNisCode,
+ postalInformation.Organisation,
+ postalInformation.Reason);
+
+ if (postalInformation.ContainsEvent)
+ {
+ var doc = new XmlDocument();
+ doc.LoadXml(postalInformation.EventDataAsXml);
+ content.Event = doc.DocumentElement;
+ }
+
+ return content.ToXml();
+ }
+ }
+
+ [DataContract(Name = "Content", Namespace = "")]
+ public class SyndicationContent : SyndicationContentBase
+ {
+ [DataMember(Name = "Event")]
+ public XmlElement Event { get; set; }
+
+ [DataMember(Name = "Object")]
+ public PostalInfoSyndicationContent Object { get; set; }
+ }
+
+ [DataContract(Name = "PostInfo", Namespace = "")]
+ public class PostalInfoSyndicationContent
+ {
+ ///
+ /// De technische id van de postinfo.
+ ///
+ [DataMember(Name = "Id", Order = 1)]
+ public string PostalCode { get; set; }
+
+ ///
+ /// De identificator van de postcode.
+ ///
+ [DataMember(Name = "Identificator", Order = 1)]
+ public PostinfoIdentificator Identificator { get; set; }
+
+ ///
+ /// De namen van het gebied dat de postcode beslaat, in de taal afkomstig uit het bPost bestand.
+ ///
+ [DataMember(Name = "Postnamen", Order = 2)]
+ public List PostalNames { get; set; }
+
+ ///
+ /// De huidige fase in de doorlooptijd van de postcode.
+ ///
+ [DataMember(Name = "PostInfoStatus", Order = 3)]
+ public PostInfoStatus? Status { get; set; }
+
+ ///
+ /// De NisCode van de gemeente waarmee de postcode verwant is.
+ ///
+ [DataMember(Name = "NisCode", Order = 3)]
+ public string MunicipalityNisCode { get; set; }
+
+ ///
+ /// Creatie data ivm het item.
+ ///
+ [DataMember(Name = "Creatie", Order = 4)]
+ public Provenance Provenance { get; set; }
+
+ public PostalInfoSyndicationContent(
+ string naamruimte,
+ string postcode,
+ DateTimeOffset version,
+ PostalInformationStatus? status,
+ IEnumerable postalNames,
+ string municipalityNisCode,
+ Organisation? organisation,
+ string reason)
+ {
+ PostalCode = postcode;
+ Identificator = new PostinfoIdentificator(naamruimte, postcode, version);
+ Status = status?.ConvertFromPostalInformationStatus();
+ MunicipalityNisCode = municipalityNisCode;
+ PostalNames = postalNames?
+ .Select(name => new Postnaam(new GeografischeNaam(name.Name, name.Language.ConvertFromLanguage())))
+ .ToList()
+ ?? new List();
+ Provenance = new Provenance(version, organisation, new Reason(reason));
+ }
+ }
+
+ public class PostalInformationSyndicationResponseExamples : IExamplesProvider
+ {
+ const string RawXml = @"
+
+ https://api.basisregisters.vlaanderen.be/v2/feeds/postinfo.atom
+ Basisregisters Vlaanderen - feed 'postinfo'
+ Deze Atom feed geeft leestoegang tot events op de resource 'postinfo'.
+ Basisregisters Vlaanderen
+ Gratis hergebruik volgens https://overheid.vlaanderen.be/sites/default/files/documenten/ict-egov/licenties/hergebruik/modellicentie_gratis_hergebruik_v1_0.html
+ 2020-09-17T09:14:41Z
+
+ Digitaal Vlaanderen
+ digitaal.vlaanderen@vlaanderen.be
+
+
+
+
+
+
+
+ 0
+ PostalInformationWasRegistered-0
+ 2019-11-21T09:34:51+01:00
+ 2019-11-21T09:34:51+01:00
+
+
+ bpost
+
+
+
+ 89002019-11-21T08:34:51ZDePostCentrale bijhouding o.b.v. bPost-bestand
+
+ ]]>
+
+
+
+ 1
+ PostalInformationBecameCurrent-1
+ 2019-11-21T09:34:51+01:00
+ 2019-11-21T09:34:51+01:00
+
+
+ bpost
+
+
+
+ 89002019-11-21T08:34:51ZDePostCentrale bijhouding o.b.v. bPost-bestand
+
+ ]]>
+
+
+";
+
+ public XmlElement GetExamples()
+ {
+ var example = new XmlDocument();
+ example.LoadXml(RawXml);
+ return example.DocumentElement;
+ }
+ }
+}
diff --git a/src/PostalRegistry.Api.Oslo/appsettings.json b/src/PostalRegistry.Api.Oslo/appsettings.json
index 0e66447b..f8f8e41f 100644
--- a/src/PostalRegistry.Api.Oslo/appsettings.json
+++ b/src/PostalRegistry.Api.Oslo/appsettings.json
@@ -12,13 +12,30 @@
"http://localhost:5000"
],
+ "Syndication": {
+ "Category": "https://data.vlaanderen.be/ns/postinfo",
+ "Id": "https://legacy.staging-basisregisters.vlaanderen/v2/feeds/postinfo.atom",
+ "Title": "Basisregisters Vlaanderen - PostInfo register",
+ "Subtitle": "Deze Atom feed geeft leestoegang tot events op de resource 'postinfo'.",
+ "GeneratorTitle": "Basisregisters Vlaanderen",
+ "GeneratorUri": "",
+ "Rights": "Gratis hergebruik volgens https://overheid.vlaanderen.be/sites/default/files/documenten/ict-egov/licenties/hergebruik/modellicentie_gratis_hergebruik_v1_0.html",
+ "AuthorName": "Digitaal Vlaanderen",
+ "AuthorEmail": "digitaal.vlaanderen@vlaanderen.be",
+ "Self": "https://legacy.staging-basisregisters.vlaanderen/syndication/feed/postalinfo",
+ "NextUri": "https://legacy.staging-basisregisters.vlaanderen/v2/feeds/postinfo.atom?from={0}&limit={1}",
+ "Related": [
+ "https://legacy.staging-basisregisters.vlaanderen"
+ ]
+ },
+
"Naamruimte": "https://data.vlaanderen.be/id/postinfo",
"DetailUrl": "https://basisregisters.vlaanderen.be/api/v2/postinfo/{0}",
"VolgendeUrl": "https://basisregisters.vlaanderen.be/api/v2/postinfo?offset={0}&limit={1}",
"ContextUrlList": "https://docs.basisregisters.dev-vlaanderen.be/context/postinfo/2022-01-11/postinfo_list.jsonld",
"ContextUrlDetail": "https://docs.basisregisters.dev-vlaanderen.be/context/postinfo/2022-01-11/postinfo_detail.jsonld",
"GemeenteNaamruimte": "https://data.vlaanderen.be/id/gemeente",
- "GemeenteDetailUrl": "https://basisregisters.vlaanderen.be/api/v1/gemeenten/{0}",
+ "GemeenteDetailUrl": "https://basisregisters.vlaanderen.be/api/v2/gemeenten/{0}",
"Serilog": {
"MinimumLevel": {