Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#2910 Make Base implement IScopedNode - phase 1 #2913

Open
wants to merge 30 commits into
base: develop-6.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
30fa951
Folded PocoElementNode into Resource
ewoutkramer Sep 23, 2024
d9bcf37
Merge branch 'develop-6.0' into spike/make-resource-implement-itypede…
ewoutkramer Oct 14, 2024
061a0fd
WIP voor Kas
ewoutkramer Oct 14, 2024
2bc3152
wip
Kasdejong Oct 14, 2024
a35a365
Removed ElementNode from Base
Kasdejong Oct 15, 2024
6847fc2
Removed ElementNode from Base
Kasdejong Oct 15, 2024
13f4286
Merge remote-tracking branch 'origin/spike/make-resource-implement-is…
Kasdejong Oct 16, 2024
80ec690
small oversight here :)
Kasdejong Oct 16, 2024
a6e1eb5
trying this to fix the pipeline
Kasdejong Oct 16, 2024
e7e3dab
disable package validation
Kasdejong Oct 16, 2024
ac73de8
Fixed serializer again?
Kasdejong Oct 16, 2024
ce5b1e8
runs locally, let's see if it works on the pipeline?
Kasdejong Oct 16, 2024
716f620
runs locally, let's see if it works on the pipeline?
Kasdejong Oct 16, 2024
35379b4
Merge remote-tracking branch 'origin/spike/make-resource-implement-is…
Kasdejong Oct 16, 2024
c61fd46
why is this needed???????
Kasdejong Oct 16, 2024
209e0be
Removed IBaseElementNavigator
Kasdejong Oct 16, 2024
41e2ec5
Merge branch 'develop-6.0' into spike/remove-IBaseElementNavigator
Kasdejong Oct 16, 2024
95cdbe8
defined IScopedNode (for now) and made base implement it.
Kasdejong Oct 16, 2024
8454cbd
Merge branch 'spike/define-Iscopednode' into spike/remove-IBaseElemen…
Kasdejong Oct 16, 2024
a75232a
Merge branch 'develop-6.0' into spike/make-resource-implement-iscoped…
Kasdejong Oct 16, 2024
06470cb
Revert "defined IScopedNode (for now) and made base implement it."
Kasdejong Oct 16, 2024
451de22
removed pragmas
Kasdejong Oct 16, 2024
e8556e2
applied PR requested changes
Kasdejong Oct 17, 2024
6142626
Merge pull request #2920 from FirelyTeam/spike/remove-IBaseElementNav…
ewoutkramer Oct 17, 2024
ab9f46b
updated compatibility suppressions
Kasdejong Oct 18, 2024
10d91b3
Merge branch 'develop-6.0' into spike/make-resource-implement-iscoped…
Kasdejong Oct 21, 2024
48b7f7b
removed unused imports after merge
Kasdejong Oct 21, 2024
f3f50fc
applied PR requested changes
Kasdejong Oct 21, 2024
c5dec88
applied PR requested changes
Kasdejong Oct 21, 2024
34c4d0c
Merge remote-tracking branch 'origin/spike/make-resource-implement-is…
Kasdejong Oct 21, 2024
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
322 changes: 322 additions & 0 deletions src/Hl7.Fhir.Base/CompatibilitySuppressions.xml

Large diffs are not rendered by default.

70 changes: 0 additions & 70 deletions src/Hl7.Fhir.Base/ElementModel/IBaseElementNavigator.cs

This file was deleted.

45 changes: 44 additions & 1 deletion src/Hl7.Fhir.Base/ElementModel/ITypedElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

using Hl7.Fhir.Specification;
using System.Collections.Generic;

#nullable enable

Expand All @@ -22,10 +23,52 @@ namespace Hl7.Fhir.ElementModel
/// </remarks>

#pragma warning disable CS0618 // Type or member is obsolete
public interface ITypedElement : IBaseElementNavigator<ITypedElement>
public interface ITypedElement
#pragma warning restore CS0618 // Type or member is obsolete
{
/// <summary>
/// Enumerate the child nodes present in the source representation (if any)
/// </summary>
/// <param name="name">Return only the children with the given name.</param>
/// <returns></returns>
IEnumerable<ITypedElement> Children(string? name = null);

/// <summary>
/// Name of the node, e.g. "active", "value".
/// </summary>
string Name { get; }

/// <summary>
/// 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.
/// </summary>
string? InstanceType { get; }

/// <summary>
/// The value of the node (if it represents a primitive FHIR value)
/// </summary>
/// <remarks>
/// 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
/// </remarks>
object? Value { get; }

/// <summary>
/// An indication of the location of this node within the data represented by the <c>ITypedElement</c>.
Expand Down
63 changes: 21 additions & 42 deletions src/Hl7.Fhir.Base/ElementModel/PocoElementNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using P = Hl7.Fhir.ElementModel.Types;

namespace Hl7.Fhir.ElementModel
Expand All @@ -32,7 +31,7 @@ internal PocoElementNode(ModelInspector inspector, Base root, string rootName =
{
Current = root;
_inspector = inspector;
_myClassMapping = _inspector.FindOrImportClassMapping(root.GetType());
_myClassMapping = _inspector.FindOrImportClassMapping(root.GetType())!;

InstanceType = ((IStructureDefinitionSummary)_myClassMapping).TypeName;
Definition = ElementDefinitionSummary.ForRoot(_myClassMapping, rootName ?? root.TypeName);
Expand Down Expand Up @@ -70,7 +69,7 @@ private Type determineInstanceType(PropertyMapping definition)
{
"url" => typeof(FhirUri),
"id" => typeof(FhirString),
"div" => typeof(XHtml),
//"div" => typeof(XHtml),
_ => throw new NotSupportedException(
$"Encountered unexpected primitive type {Name} in backward compat behaviour for PocoElementNode.InstanceType.")
};
Expand Down Expand Up @@ -205,39 +204,20 @@ internal object ToITypedElementValue()
{
try
{
switch (Current)
return Current switch
{
case Hl7.Fhir.Model.Instant ins when ins.Value.HasValue:
return P.DateTime.FromDateTimeOffset(ins.Value.Value);
case Hl7.Fhir.Model.Time time when time.Value is { }:
return P.Time.Parse(time.Value);
case Hl7.Fhir.Model.Date dt when dt.Value is { }:
return P.Date.Parse(dt.Value);
case FhirDateTime fdt when fdt.Value is { }:
return P.DateTime.Parse(fdt.Value);
case Hl7.Fhir.Model.Integer fint:
if (!fint.Value.HasValue)
return null;
return (int)fint.Value;
case Hl7.Fhir.Model.Integer64 fint64:
if (!fint64.Value.HasValue)
return null;
return (long)fint64.Value;
case Hl7.Fhir.Model.PositiveInt pint:
if (!pint.Value.HasValue)
return null;
return (int)pint.Value;
case Hl7.Fhir.Model.UnsignedInt unsint:
if (!unsint.Value.HasValue)
return null;
return (int)unsint.Value;
case Hl7.Fhir.Model.Base64Binary b64:
return b64.Value != null ? PrimitiveTypeConverter.ConvertTo<string>(b64.Value) : null;
case PrimitiveType prim:
return prim.ObjectValue;
default:
return null;
}
Instant { Value: { } ins } => P.DateTime.FromDateTimeOffset(ins),
Time { Value: { } time } => P.Time.Parse(time),
Date { Value: { } dt } => P.Date.Parse(dt),
FhirDateTime { Value: { } fdt } => P.DateTime.Parse(fdt),
Integer fint => fint.Value,
Integer64 fint64 => fint64.Value,
PositiveInt pint => pint.Value,
UnsignedInt unsint => unsint.Value,
Base64Binary { Value: { } b64 } => PrimitiveTypeConverter.ConvertTo<string>(b64),
PrimitiveType prim => prim.ObjectValue,
_ => null
};
}
catch (FormatException)
{
Expand All @@ -247,25 +227,24 @@ internal object ToITypedElementValue()
}


public string InstanceType { get; private set; }
public string InstanceType { get; }

public string Location { get; private set; }
public string Location { get; }

public string ResourceType => Current is Resource ? InstanceType : null;

public IEnumerable<object> Annotations(Type type)
{
if (type == typeof(PocoElementNode) || type == typeof(ITypedElement) || type == typeof(IShortPathGenerator))
return new[] { this };
return [this];
else if (type == typeof(IFhirValueProvider))
return new[] { this };
return [this];
else if (type == typeof(IResourceTypeSupplier))
return new[] { this };
return [this];
else if (FhirValue is IAnnotated ia)
return ia.Annotations(type);

else
return Enumerable.Empty<object>();
return [];
}
}
}
8 changes: 5 additions & 3 deletions src/Hl7.Fhir.Base/ElementModel/TypedElementExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Hl7.Fhir.Model;
using System;
using System.Linq;
using System.Runtime.CompilerServices;

namespace Hl7.Fhir.ElementModel
{
Expand All @@ -26,6 +27,7 @@ public static class TypedElementExtensions
/// <param name="modelInspector">The <see cref="ModelInspector"/> containing the POCO classes to be used for deserialization.</param>
/// <param name="rootName"></param>
/// <returns></returns>
[TemporarilyChanged]
public static ITypedElement ToTypedElement(this Base @base, ModelInspector modelInspector, string? rootName = null)
=> new PocoElementNode(modelInspector, @base, rootName: rootName);

Expand All @@ -39,7 +41,7 @@ public static ITypedElement ToTypedElement(this Base @base, ModelInspector model
/// of the equation.</param>
/// <returns><c>true</c> when the ITypedElements are equal, <c>false</c> otherwise.</returns>
#pragma warning disable CS0618 // Type or member is obsolete
public static bool IsExactlyEqualTo<T>(this T? left, T? right, bool ignoreOrder = false) where T : IBaseElementNavigator<T>
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;
Expand Down Expand Up @@ -102,7 +104,7 @@ public static bool ValueEquality<T1, T2>(T1? val1, T2? val2)
/// <param name="pattern"></param>
/// <returns><c>true</c> when <paramref name="value"/> matches the <paramref name="pattern"/>, <c>false</c> otherwise.</returns>
#pragma warning disable CS0618 // Type or member is obsolete
public static bool Matches<T>(this T value, T pattern) where T : IBaseElementNavigator<T>
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;
Expand All @@ -120,4 +122,4 @@ public static bool Matches<T>(this T value, T pattern) where T : IBaseElementNav
}
}
}
#nullable restore
#nullable restore
22 changes: 11 additions & 11 deletions src/Hl7.Fhir.Base/ElementModel/TypedElementParseExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ public static class TypedElementParseExtensions
/// <inheritdoc cref="ParseBindable"/>
[Obsolete("WARNING! Intended for internal API usage exclusively, interface IBaseElementNavigator can be changed in " +
"the near future.")]
public static Element? ParseBindableInternal<T>(this IBaseElementNavigator<T> instance) where T : IBaseElementNavigator<T>
internal static Element? ParseBindableInternal(this ITypedElement instance)
{
return instance.InstanceType switch
{
FhirTypeConstants.CODE => instance.ParsePrimitiveInternal<Code, T>(),
FhirTypeConstants.STRING => new Code(instance.ParsePrimitiveInternal<FhirString, T>().Value),
FhirTypeConstants.URI => new Code(instance.ParsePrimitiveInternal<FhirUri, T>().Value),
FhirTypeConstants.CODE => instance.ParsePrimitiveInternal<Code>(),
FhirTypeConstants.STRING => new Code(instance.ParsePrimitiveInternal<FhirString>().Value),
FhirTypeConstants.URI => new Code(instance.ParsePrimitiveInternal<FhirUri>().Value),
FhirTypeConstants.CODING => instance.ParseCodingInternal(),
FhirTypeConstants.CODEABLE_CONCEPT => instance.ParseCodeableConceptInternal(),
FhirTypeConstants.QUANTITY => parseQuantity(),
Expand Down Expand Up @@ -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<T>(this IBaseElementNavigator<T> instance) where T : IBaseElementNavigator<T>
public static Quantity ParseQuantityInternal(this ITypedElement instance)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The introduction of IBaseElementNavigator made it necessary to make these public, I think they can be internal again - in any case the reference to IBaseElementNavigator in the Obsolete should be changed!

{
var newQuantity = new Quantity
{
Expand All @@ -111,12 +111,12 @@ public static Quantity ParseQuantityInternal<T>(this IBaseElementNavigator<T> in
#region ParsePrimitive
public static T ParsePrimitive<T>(this ITypedElement instance) where T : PrimitiveType, new()
#pragma warning disable CS0618 // Type or member is obsolete
=> ParsePrimitiveInternal<T, ITypedElement>(instance);
=> ParsePrimitiveInternal<T>(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<T, U>(this IBaseElementNavigator<U> instance) where T : PrimitiveType, new() where U : IBaseElementNavigator<U>
public static T ParsePrimitiveInternal<T>(this ITypedElement instance) where T : PrimitiveType, new()
=> new() { ObjectValue = instance.Value };

#endregion
Expand All @@ -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<T>(this IBaseElementNavigator<T> instance) where T : IBaseElementNavigator<T>
public static Coding ParseCodingInternal(this ITypedElement instance)
{
return new Coding()
{
Expand All @@ -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<T>(this IBaseElementNavigator<T> instance) where T : IBaseElementNavigator<T>
public static ResourceReference ParseResourceReferenceInternal(this ITypedElement instance)
{
return new ResourceReference()
{
Expand All @@ -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<T>(this IBaseElementNavigator<T> instance) where T : IBaseElementNavigator<T>
public static CodeableConcept ParseCodeableConceptInternal(this ITypedElement instance)
{
return new CodeableConcept()
{
Expand All @@ -181,7 +181,7 @@ public static CodeableConcept ParseCodeableConceptInternal<T>(this IBaseElementN
#endregion

#pragma warning disable CS0618 // Type or member is obsolete
public static string? GetString<T>(this IEnumerable<T> instance) where T : IBaseElementNavigator<T>
public static string? GetString(this IEnumerable<ITypedElement> instance)
#pragma warning restore CS0618 // Type or member is obsolete
=> instance.SingleOrDefault()?.Value as string;
}
Expand Down
3 changes: 0 additions & 3 deletions src/Hl7.Fhir.Base/FhirPath/Expressions/Closure.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@

using Hl7.Fhir.ElementModel;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Dynamic;
using System.Linq;

namespace Hl7.FhirPath.Expressions
{
Expand Down
Loading