diff --git a/src/Microsoft.Health.Fhir.Core/Features/Persistence/SoftDeletedFhirPathExtension.cs b/src/Microsoft.Health.Fhir.Core/Features/Persistence/SoftDeletedFhirPathExtension.cs new file mode 100644 index 0000000000..aba64a3a9a --- /dev/null +++ b/src/Microsoft.Health.Fhir.Core/Features/Persistence/SoftDeletedFhirPathExtension.cs @@ -0,0 +1,19 @@ +// ------------------------------------------------------------------------------------------------- +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------------------------------------------- + +using Microsoft.Health.Fhir.Core.Models; + +namespace Microsoft.Health.Fhir.Core.Features.Persistence; + +public static class SoftDeletedFhirPathExtension +{ + /// + /// Return true if this resource contains the Azure 'soft-deleted' extension in meta data + /// + public static bool IsSoftDeleted(this ResourceElement resourceElement) + { + return resourceElement.Predicate(KnownFhirPaths.IsSoftDeletedExtension); + } +} diff --git a/src/Microsoft.Health.Fhir.Core/Models/KnownFhirPaths.cs b/src/Microsoft.Health.Fhir.Core/Models/KnownFhirPaths.cs index 5685d3a7a1..498cdb8ff0 100644 --- a/src/Microsoft.Health.Fhir.Core/Models/KnownFhirPaths.cs +++ b/src/Microsoft.Health.Fhir.Core/Models/KnownFhirPaths.cs @@ -7,6 +7,8 @@ namespace Microsoft.Health.Fhir.Core.Models { public static class KnownFhirPaths { + internal const string AzureSoftDeletedExtensionUrl = "http://azurehealthcareapis.com/data-extensions/deleted-state"; + public const string BundleEntries = "Resource.entry.resource"; public const string BundleNextLink = "Resource.link.where(relation = 'next').url"; @@ -16,5 +18,7 @@ public static class KnownFhirPaths public const string BundleType = "Resource.type"; public const string ResourceNarrative = "text.div"; + + public const string IsSoftDeletedExtension = $"Resource.meta.extension.where(url = '{AzureSoftDeletedExtensionUrl}').where(value='soft-deleted').exists()"; } } diff --git a/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Extensions/KnowFhirPathsTests.cs b/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Extensions/KnowFhirPathsTests.cs new file mode 100644 index 0000000000..f523bf475f --- /dev/null +++ b/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Extensions/KnowFhirPathsTests.cs @@ -0,0 +1,32 @@ +// ------------------------------------------------------------------------------------------------- +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------------------------------------------- + +using Microsoft.Health.Fhir.Core.Extensions; +using Microsoft.Health.Fhir.Core.Features.Persistence; +using Microsoft.Health.Fhir.Core.Models; +using Microsoft.Health.Fhir.Tests.Common; +using Microsoft.Health.Test.Utilities; +using Xunit; + +namespace Microsoft.Health.Fhir.Shared.Core.UnitTests.Extensions; + +[Trait(Traits.OwningTeam, OwningTeam.Fhir)] +[Trait(Traits.Category, Categories.Import)] +public class KnowFhirPathsTests +{ + [Fact] + public void GivenAResource_WhenEvaluatingIfSoftDeleted_ThenTheCorrectFlagIsReturned() + { + ResourceElement patient = Samples.GetDefaultPatient(); + + var isDeleted = patient.IsSoftDeleted(); + Assert.False(isDeleted); + + ResourceElement withExtension = patient.TryAddSoftDeletedExtension(); + + isDeleted = withExtension.IsSoftDeleted(); + Assert.True(isDeleted); + } +} diff --git a/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Microsoft.Health.Fhir.Shared.Core.UnitTests.projitems b/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Microsoft.Health.Fhir.Shared.Core.UnitTests.projitems index af51a256fb..d9d8c9cc7b 100644 --- a/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Microsoft.Health.Fhir.Shared.Core.UnitTests.projitems +++ b/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Microsoft.Health.Fhir.Shared.Core.UnitTests.projitems @@ -10,6 +10,7 @@ + diff --git a/src/Microsoft.Health.Fhir.Shared.Core/Extensions/ModelExtensions.cs b/src/Microsoft.Health.Fhir.Shared.Core/Extensions/ModelExtensions.cs index 3f976bad19..88187468e2 100644 --- a/src/Microsoft.Health.Fhir.Shared.Core/Extensions/ModelExtensions.cs +++ b/src/Microsoft.Health.Fhir.Shared.Core/Extensions/ModelExtensions.cs @@ -130,6 +130,26 @@ public static ResourceElement UpdateLastUpdated(this ResourceElement resource, D return poco.ToResourceElement(); } + public static ResourceElement TryAddSoftDeletedExtension(this ResourceElement resource) + { + EnsureArg.IsNotNull(resource, nameof(resource)); + + Resource poco = resource.ToPoco(); + poco.Meta ??= new Meta(); + + if (!poco.Meta.Extension.Any(x => string.Equals(x.Url, KnownFhirPaths.AzureSoftDeletedExtensionUrl, StringComparison.OrdinalIgnoreCase))) + { + poco.Meta.Extension.Add( + new Extension + { + Url = KnownFhirPaths.AzureSoftDeletedExtensionUrl, + Value = new FhirString("soft-deleted"), + }); + } + + return poco.ToResourceElement(); + } + public static SearchParameterInfo ToInfo(this SearchParameter searchParam) { EnsureArg.IsNotNull(searchParam, nameof(searchParam));