From 209e0be446b251c759d56f5a5104ee629bc062d2 Mon Sep 17 00:00:00 2001 From: Kasdejong Date: Wed, 16 Oct 2024 15:26:50 +0200 Subject: [PATCH 1/4] Removed IBaseElementNavigator --- .../ElementModel/IBaseElementNavigator.cs | 70 ------------------- .../ElementModel/ITypedElement.cs | 45 +++++++++++- .../ElementModel/TypedElementExtensions.cs | 4 +- .../TypedElementParseExtensions.cs | 22 +++--- src/Hl7.Fhir.Base/Model/Base.TypedElement.cs | 20 ++---- 5 files changed, 63 insertions(+), 98 deletions(-) delete mode 100644 src/Hl7.Fhir.Base/ElementModel/IBaseElementNavigator.cs diff --git a/src/Hl7.Fhir.Base/ElementModel/IBaseElementNavigator.cs b/src/Hl7.Fhir.Base/ElementModel/IBaseElementNavigator.cs deleted file mode 100644 index e1855bb731..0000000000 --- a/src/Hl7.Fhir.Base/ElementModel/IBaseElementNavigator.cs +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2023, Firely (info@fire.ly) and contributors - * See the file CONTRIBUTORS for details. - * - * This file is licensed under the BSD 3-Clause license - * available at https://raw.githubusercontent.com/FirelyTeam/firely-net-sdk/master/LICENSE - */ - -using System; -using System.Collections.Generic; - -#nullable enable - -namespace Hl7.Fhir.ElementModel -{ - /// - /// The base interface for ."/> - /// - /// - [Obsolete("WARNING! Intended for internal API usage exclusively, this interface ideally should be kept internal. " + - "However, due to its derivation by the public interface ITypedElement, maintaining its internal status is impossible.")] - public interface IBaseElementNavigator where TDerived : IBaseElementNavigator - { - /// - /// Enumerate the child nodes present in the source representation (if any) - /// - /// Return only the children with the given name. - /// - IEnumerable Children(string? name = null); - - /// - /// Name of the node, e.g. "active", "value". - /// - string Name { get; } - - /// - /// Type of the node. If a FHIR type, this is just a simple string, otherwise a StructureDefinition url for a type defined as a logical model. - /// - string? InstanceType { get; } - - /// - /// The value of the node (if it represents a primitive FHIR value) - /// - /// - /// FHIR primitives are mapped to underlying C# types as follows: - /// - /// instant Hl7.Fhir.ElementModel.Types.DateTime - /// time Hl7.Fhir.ElementModel.Types.Time - /// date Hl7.Fhir.ElementModel.Types.Date - /// dateTime Hl7.Fhir.ElementModel.Types.DateTime - /// decimal decimal - /// boolean bool - /// integer int - /// unsignedInt int - /// positiveInt int - /// long/integer64 long (name will be finalized in R5) - /// string string - /// code string - /// id string - /// uri, oid, uuid, - /// canonical, url string - /// markdown string - /// base64Binary string (uuencoded) - /// xhtml string - /// - object? Value { get; } - } -} - -#nullable restore \ No newline at end of file diff --git a/src/Hl7.Fhir.Base/ElementModel/ITypedElement.cs b/src/Hl7.Fhir.Base/ElementModel/ITypedElement.cs index bfe5cc4cb6..8c08bd9ccd 100644 --- a/src/Hl7.Fhir.Base/ElementModel/ITypedElement.cs +++ b/src/Hl7.Fhir.Base/ElementModel/ITypedElement.cs @@ -7,6 +7,7 @@ */ using Hl7.Fhir.Specification; +using System.Collections.Generic; #nullable enable @@ -22,10 +23,52 @@ namespace Hl7.Fhir.ElementModel /// #pragma warning disable CS0618 // Type or member is obsolete - public interface ITypedElement : IBaseElementNavigator + public interface ITypedElement #pragma warning restore CS0618 // Type or member is obsolete { + /// + /// Enumerate the child nodes present in the source representation (if any) + /// + /// Return only the children with the given name. + /// + IEnumerable Children(string? name = null); + + /// + /// Name of the node, e.g. "active", "value". + /// + string Name { get; } + /// + /// Type of the node. If a FHIR type, this is just a simple string, otherwise a StructureDefinition url for a type defined as a logical model. + /// + string? InstanceType { get; } + + /// + /// The value of the node (if it represents a primitive FHIR value) + /// + /// + /// FHIR primitives are mapped to underlying C# types as follows: + /// + /// instant Hl7.Fhir.ElementModel.Types.DateTime + /// time Hl7.Fhir.ElementModel.Types.Time + /// date Hl7.Fhir.ElementModel.Types.Date + /// dateTime Hl7.Fhir.ElementModel.Types.DateTime + /// decimal decimal + /// boolean bool + /// integer int + /// unsignedInt int + /// positiveInt int + /// long/integer64 long (name will be finalized in R5) + /// string string + /// code string + /// id string + /// uri, oid, uuid, + /// canonical, url string + /// markdown string + /// base64Binary string (uuencoded) + /// xhtml string + /// + object? Value { get; } /// /// An indication of the location of this node within the data represented by the ITypedElement. diff --git a/src/Hl7.Fhir.Base/ElementModel/TypedElementExtensions.cs b/src/Hl7.Fhir.Base/ElementModel/TypedElementExtensions.cs index 9732a7a846..cf1920b52a 100644 --- a/src/Hl7.Fhir.Base/ElementModel/TypedElementExtensions.cs +++ b/src/Hl7.Fhir.Base/ElementModel/TypedElementExtensions.cs @@ -39,7 +39,7 @@ public static ITypedElement ToTypedElement(this Base @base, ModelInspector model /// of the equation. /// true when the ITypedElements are equal, false otherwise. #pragma warning disable CS0618 // Type or member is obsolete - public static bool IsExactlyEqualTo(this T? left, T? right, bool ignoreOrder = false) where T : IBaseElementNavigator + public static bool IsExactlyEqualTo(this ITypedElement? left, ITypedElement? right, bool ignoreOrder = false) #pragma warning restore CS0618 // Type or member is obsolete { if (left == null && right == null) return true; @@ -102,7 +102,7 @@ public static bool ValueEquality(T1? val1, T2? val2) /// /// true when matches the , false otherwise. #pragma warning disable CS0618 // Type or member is obsolete - public static bool Matches(this T value, T pattern) where T : IBaseElementNavigator + public static bool Matches(this ITypedElement value, ITypedElement pattern) #pragma warning restore CS0618 // Type or member is obsolete { if (value == null && pattern == null) return true; diff --git a/src/Hl7.Fhir.Base/ElementModel/TypedElementParseExtensions.cs b/src/Hl7.Fhir.Base/ElementModel/TypedElementParseExtensions.cs index 14889d90e2..b08ef52cde 100644 --- a/src/Hl7.Fhir.Base/ElementModel/TypedElementParseExtensions.cs +++ b/src/Hl7.Fhir.Base/ElementModel/TypedElementParseExtensions.cs @@ -44,13 +44,13 @@ public static class TypedElementParseExtensions /// [Obsolete("WARNING! Intended for internal API usage exclusively, interface IBaseElementNavigator can be changed in " + "the near future.")] - public static Element? ParseBindableInternal(this IBaseElementNavigator instance) where T : IBaseElementNavigator + public static Element? ParseBindableInternal(this ITypedElement instance) { return instance.InstanceType switch { - FhirTypeConstants.CODE => instance.ParsePrimitiveInternal(), - FhirTypeConstants.STRING => new Code(instance.ParsePrimitiveInternal().Value), - FhirTypeConstants.URI => new Code(instance.ParsePrimitiveInternal().Value), + FhirTypeConstants.CODE => instance.ParsePrimitiveInternal(), + FhirTypeConstants.STRING => new Code(instance.ParsePrimitiveInternal().Value), + FhirTypeConstants.URI => new Code(instance.ParsePrimitiveInternal().Value), FhirTypeConstants.CODING => instance.ParseCodingInternal(), FhirTypeConstants.CODEABLE_CONCEPT => instance.ParseCodeableConceptInternal(), FhirTypeConstants.QUANTITY => parseQuantity(), @@ -90,7 +90,7 @@ public static Quantity ParseQuantity(this ITypedElement instance) [Obsolete("WARNING! Intended for internal API usage exclusively, interface IBaseElementNavigator can be changed in " + "the near future.")] - public static Quantity ParseQuantityInternal(this IBaseElementNavigator instance) where T : IBaseElementNavigator + public static Quantity ParseQuantityInternal(this ITypedElement instance) { var newQuantity = new Quantity { @@ -111,12 +111,12 @@ public static Quantity ParseQuantityInternal(this IBaseElementNavigator in #region ParsePrimitive public static T ParsePrimitive(this ITypedElement instance) where T : PrimitiveType, new() #pragma warning disable CS0618 // Type or member is obsolete - => ParsePrimitiveInternal(instance); + => ParsePrimitiveInternal(instance); #pragma warning restore CS0618 // Type or member is obsolete [Obsolete("WARNING! Intended for internal API usage exclusively, interface IBaseElementNavigator can be changed in " + "the near future.")] - public static T ParsePrimitiveInternal(this IBaseElementNavigator instance) where T : PrimitiveType, new() where U : IBaseElementNavigator + public static T ParsePrimitiveInternal(this ITypedElement instance) where T : PrimitiveType, new() => new() { ObjectValue = instance.Value }; #endregion @@ -130,7 +130,7 @@ public static Coding ParseCoding(this ITypedElement instance) [Obsolete("WARNING! Intended for internal API usage exclusively, interface IBaseElementNavigator can be changed in " + "the near future.")] - public static Coding ParseCodingInternal(this IBaseElementNavigator instance) where T : IBaseElementNavigator + public static Coding ParseCodingInternal(this ITypedElement instance) { return new Coding() { @@ -151,7 +151,7 @@ public static ResourceReference ParseResourceReference(this ITypedElement instan [Obsolete("WARNING! Intended for internal API usage exclusively, interface IBaseElementNavigator can be changed in " + "the near future.")] - public static ResourceReference ParseResourceReferenceInternal(this IBaseElementNavigator instance) where T : IBaseElementNavigator + public static ResourceReference ParseResourceReferenceInternal(this ITypedElement instance) { return new ResourceReference() { @@ -169,7 +169,7 @@ public static CodeableConcept ParseCodeableConcept(this ITypedElement instance) [Obsolete("WARNING! Intended for internal API usage exclusively, interface IBaseElementNavigator can be changed in " + "the near future.")] - public static CodeableConcept ParseCodeableConceptInternal(this IBaseElementNavigator instance) where T : IBaseElementNavigator + public static CodeableConcept ParseCodeableConceptInternal(this ITypedElement instance) { return new CodeableConcept() { @@ -181,7 +181,7 @@ public static CodeableConcept ParseCodeableConceptInternal(this IBaseElementN #endregion #pragma warning disable CS0618 // Type or member is obsolete - public static string? GetString(this IEnumerable instance) where T : IBaseElementNavigator + public static string? GetString(this IEnumerable instance) #pragma warning restore CS0618 // Type or member is obsolete => instance.SingleOrDefault()?.Value as string; } diff --git a/src/Hl7.Fhir.Base/Model/Base.TypedElement.cs b/src/Hl7.Fhir.Base/Model/Base.TypedElement.cs index 856cce5c69..8fb961768c 100644 --- a/src/Hl7.Fhir.Base/Model/Base.TypedElement.cs +++ b/src/Hl7.Fhir.Base/Model/Base.TypedElement.cs @@ -31,15 +31,7 @@ public interface IScopedNode : ITypedElement, IShortPathGenerator /// /// The parent node of this node, or null if this is the root node. /// - IScopedNode? Parent { get; } - - // /// - // /// An indication of the location of this node within the data represented by the ITypedElement. - // /// - // /// The format of the location is the dotted name of the property, including indices to make - // /// sure repeated occurrences of an element can be distinguished. It needs to be sufficiently precise to aid - // /// the user in locating issues in the data. - // string Location { get; } + IScopedNode? Parent { get; } } internal record ScopeInformation(IScopedNode? Parent, string Name, int? Index); @@ -65,7 +57,7 @@ internal Base WithScopeInfo(ScopeInformation info) return this; } - IEnumerable IBaseElementNavigator.Children(string? name) => + IEnumerable ITypedElement.Children(string? name) => this.GetElementPairs() .Where(ep => (name == null || name == ep.Key)) .SelectMany, Base>(ep => @@ -82,7 +74,7 @@ IEnumerable IBaseElementNavigator.Children(string? IScopedNode? IScopedNode.Parent => ScopeInfo.Parent; - string IBaseElementNavigator.Name => ScopeInfo.Name; + string ITypedElement.Name => ScopeInfo.Name; // TODO: // Als wij een BackboneElement zijn, dan is onze naam niet this.TypeName maar "BackboneElement" of @@ -90,7 +82,7 @@ IEnumerable IBaseElementNavigator.Children(string? // HEt moet "code" zijn als dit een "Code" is. Dat zijn geloof ik de afwijkingen. // Wellioht is er ook nog iets met de directe properties "Extension.url" en "Element.id" die van een // system type zijn ipv een FHIR type. - string? IBaseElementNavigator.InstanceType => + string? ITypedElement.InstanceType => ((IStructureDefinitionSummary) ModelInspector .ForType(this.GetType()) @@ -127,7 +119,7 @@ IEnumerable IBaseElementNavigator.Children(string? } } - object? IBaseElementNavigator.Value + object? ITypedElement.Value { get { @@ -169,7 +161,7 @@ IEnumerable IBaseElementNavigator.Children(string? string? IResourceTypeSupplier.ResourceType => this is Resource #pragma warning disable CS0618 // Type or member is obsolete - ? ((IBaseElementNavigator)this).InstanceType + ? ((ITypedElement)this).InstanceType #pragma warning restore CS0618 // Type or member is obsolete : null; } From 95cdbe8bfe87591cb27039130ced39db8f336fc7 Mon Sep 17 00:00:00 2001 From: Kasdejong Date: Wed, 16 Oct 2024 16:52:06 +0200 Subject: [PATCH 2/4] defined IScopedNode (for now) and made base implement it. --- src/Hl7.Fhir.Base/Model/IScopedNode.cs | 75 ++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/Hl7.Fhir.Base/Model/IScopedNode.cs diff --git a/src/Hl7.Fhir.Base/Model/IScopedNode.cs b/src/Hl7.Fhir.Base/Model/IScopedNode.cs new file mode 100644 index 0000000000..7ff104ae45 --- /dev/null +++ b/src/Hl7.Fhir.Base/Model/IScopedNode.cs @@ -0,0 +1,75 @@ +using Hl7.Fhir.ElementModel; +using System.Collections.Generic; + +namespace Hl7.Fhir.Model; + +#nullable enable + +/// +/// An element within a tree of typed FHIR data with also a parent element. +/// +/// +/// This interface represents FHIR data as a tree of elements, including type information either present in +/// the instance or derived from fully aware of the FHIR definitions and types +/// +#pragma warning disable CS0618 // Type or member is obsolete +public interface IScopedNode : ITypedElement, IShortPathGenerator +#pragma warning restore CS0618 // Type or member is obsolete +{ + /// + /// The parent node of this node, or null if this is the root node. + /// + IScopedNode? Parent { get; } + + /// + /// Enumerates the children of this instance. If name is given, only the children with that name are returned. + /// + /// If given, specifies the children to return based on this parameter. + /// An IEnumerable containing the children of this instance, including scope data. + new IEnumerable Children(string? name = null); + + /// + /// Name of the node, e.g. "active", "value". + /// + new string Name { get; } + + /// + /// Type of the node. If a FHIR type, this is just a simple string, otherwise a StructureDefinition url for a type defined as a logical model. + /// + new string? InstanceType { get; } + + /// + /// The value of the node (if it represents a primitive FHIR value) + /// + /// + /// FHIR primitives are mapped to underlying C# types as follows: + /// + /// instant Hl7.Fhir.ElementModel.Types.DateTime + /// time Hl7.Fhir.ElementModel.Types.Time + /// date Hl7.Fhir.ElementModel.Types.Date + /// dateTime Hl7.Fhir.ElementModel.Types.DateTime + /// decimal decimal + /// boolean bool + /// integer int + /// unsignedInt int + /// positiveInt int + /// long/integer64 long (name will be finalized in R5) + /// string string + /// code string + /// id string + /// uri, oid, uuid, + /// canonical, url string + /// markdown string + /// base64Binary string (uuencoded) + /// xhtml string + /// + new object? Value { get; } + + /// + /// An indication of the location of this node within the data represented by the ITypedElement. + /// + /// The format of the location is the dotted name of the property, including indices to make + /// sure repeated occurrences of an element can be distinguished. It needs to be sufficiently precise to aid + /// the user in locating issues in the data. + new string Location { get; } +} \ No newline at end of file From 06470cb9b0e3a043368bdef0bf8ce2482954da80 Mon Sep 17 00:00:00 2001 From: Kasdejong Date: Wed, 16 Oct 2024 17:32:22 +0200 Subject: [PATCH 3/4] Revert "defined IScopedNode (for now) and made base implement it." This reverts commit 95cdbe8bfe87591cb27039130ced39db8f336fc7. --- src/Hl7.Fhir.Base/Model/IScopedNode.cs | 75 -------------------------- 1 file changed, 75 deletions(-) delete mode 100644 src/Hl7.Fhir.Base/Model/IScopedNode.cs diff --git a/src/Hl7.Fhir.Base/Model/IScopedNode.cs b/src/Hl7.Fhir.Base/Model/IScopedNode.cs deleted file mode 100644 index 7ff104ae45..0000000000 --- a/src/Hl7.Fhir.Base/Model/IScopedNode.cs +++ /dev/null @@ -1,75 +0,0 @@ -using Hl7.Fhir.ElementModel; -using System.Collections.Generic; - -namespace Hl7.Fhir.Model; - -#nullable enable - -/// -/// An element within a tree of typed FHIR data with also a parent element. -/// -/// -/// This interface represents FHIR data as a tree of elements, including type information either present in -/// the instance or derived from fully aware of the FHIR definitions and types -/// -#pragma warning disable CS0618 // Type or member is obsolete -public interface IScopedNode : ITypedElement, IShortPathGenerator -#pragma warning restore CS0618 // Type or member is obsolete -{ - /// - /// The parent node of this node, or null if this is the root node. - /// - IScopedNode? Parent { get; } - - /// - /// Enumerates the children of this instance. If name is given, only the children with that name are returned. - /// - /// If given, specifies the children to return based on this parameter. - /// An IEnumerable containing the children of this instance, including scope data. - new IEnumerable Children(string? name = null); - - /// - /// Name of the node, e.g. "active", "value". - /// - new string Name { get; } - - /// - /// Type of the node. If a FHIR type, this is just a simple string, otherwise a StructureDefinition url for a type defined as a logical model. - /// - new string? InstanceType { get; } - - /// - /// The value of the node (if it represents a primitive FHIR value) - /// - /// - /// FHIR primitives are mapped to underlying C# types as follows: - /// - /// instant Hl7.Fhir.ElementModel.Types.DateTime - /// time Hl7.Fhir.ElementModel.Types.Time - /// date Hl7.Fhir.ElementModel.Types.Date - /// dateTime Hl7.Fhir.ElementModel.Types.DateTime - /// decimal decimal - /// boolean bool - /// integer int - /// unsignedInt int - /// positiveInt int - /// long/integer64 long (name will be finalized in R5) - /// string string - /// code string - /// id string - /// uri, oid, uuid, - /// canonical, url string - /// markdown string - /// base64Binary string (uuencoded) - /// xhtml string - /// - new object? Value { get; } - - /// - /// An indication of the location of this node within the data represented by the ITypedElement. - /// - /// The format of the location is the dotted name of the property, including indices to make - /// sure repeated occurrences of an element can be distinguished. It needs to be sufficiently precise to aid - /// the user in locating issues in the data. - new string Location { get; } -} \ No newline at end of file From 451de228e8b48e06dabf0d6175fd695203aa812b Mon Sep 17 00:00:00 2001 From: Kasdejong Date: Wed, 16 Oct 2024 17:34:21 +0200 Subject: [PATCH 4/4] removed pragmas --- src/Hl7.Fhir.Base/Model/Base.TypedElement.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Hl7.Fhir.Base/Model/Base.TypedElement.cs b/src/Hl7.Fhir.Base/Model/Base.TypedElement.cs index 8fb961768c..06e469816d 100644 --- a/src/Hl7.Fhir.Base/Model/Base.TypedElement.cs +++ b/src/Hl7.Fhir.Base/Model/Base.TypedElement.cs @@ -160,9 +160,7 @@ IEnumerable ITypedElement.Children(string? name) => string? IResourceTypeSupplier.ResourceType => this is Resource -#pragma warning disable CS0618 // Type or member is obsolete ? ((ITypedElement)this).InstanceType -#pragma warning restore CS0618 // Type or member is obsolete : null; }