Skip to content

Commit

Permalink
Merge pull request #2858 from FirelyTeam/bundled-resource-cache-hotfix
Browse files Browse the repository at this point in the history
Fixed NullReferenceException when enumerating bundled/contained resources
  • Loading branch information
mmsmits authored Sep 11, 2024
2 parents 574fea8 + fc3c203 commit dea1ba0
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 7 deletions.
24 changes: 18 additions & 6 deletions src/Hl7.Fhir.Base/ElementModel/ReferencedResourceCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,37 @@ namespace Hl7.Fhir.ElementModel;

internal class ReferencedResourceCache : IEnumerable<ScopedNode.BundledResource>
{
private Dictionary<string, ScopedNode?> _items;
private Dictionary<string, ScopedNode> _items;
private List<ScopedNode> _unreferenceableItems; // some resources may not have a reference, but are included nonetheless.

public ReferencedResourceCache(IEnumerable<KeyValuePair<string, ScopedNode?>> items)
public ReferencedResourceCache(IEnumerable<KeyValuePair<string, ScopedNode>> items)
{
_items = new Dictionary<string, ScopedNode?>();
_items = new Dictionary<string, ScopedNode>();
_unreferenceableItems = [];
foreach (var item in items)
{
_items.Add(item.Key, item.Value);
if (item.Key is not null)
_items.Add(item.Key, item.Value);
else
_unreferenceableItems.Add(item.Value);

}
}

internal IEnumerable<ScopedNode> Resources => _items.Values.OfType<ScopedNode>();
internal IEnumerable<ScopedNode> Resources => _items.Values.Concat(_unreferenceableItems);

internal ScopedNode? ResolveReference(string reference)
{
return _items.TryGetValue(reference, out var node) ? node : null;
}

public IEnumerator<ScopedNode.BundledResource> GetEnumerator() => _items.Select(i => new ScopedNode.BundledResource(i.Key, i.Value)).GetEnumerator();
public IEnumerator<ScopedNode.BundledResource> GetEnumerator() =>
_items
.Select(i => new ScopedNode.BundledResource(i.Key, i.Value))
.Concat(
_unreferenceableItems.Select(i => new ScopedNode.BundledResource(null, i))
)
.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

Expand Down
12 changes: 11 additions & 1 deletion src/Hl7.Fhir.ElementModel.Shared.Tests/ScopedNodeTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Hl7.Fhir.Model;
using FluentAssertions;
using Hl7.Fhir.Model;
using Hl7.Fhir.Serialization;
using Hl7.Fhir.Specification;
using Hl7.Fhir.Specification.Snapshot;
Expand Down Expand Up @@ -273,6 +274,15 @@ static bool CCDATypeNameMapper(string typeName, out string canonical)


}

[TestMethod]
public void Bundle_WithEntryWithoutFullUrl_ShouldNotThrow()
{
var bundle = new Bundle() { Type = Bundle.BundleType.Batch, Entry = [new Bundle.EntryComponent() { Resource = new Patient() }]}.ToTypedElement().ToScopedNode();

var enumerate = () => bundle.BundledResources();
enumerate.Should().NotThrow().Subject.Should().ContainSingle(c => c.FullUrl == null);
}

private class CCDAResourceResolver : IAsyncResourceResolver
{
Expand Down

0 comments on commit dea1ba0

Please sign in to comment.