ElementModel, manipulating IResource and ISourceNode
As stated in IResource, IResource is immutable, and so is ISourceNode that it is based on.
Still, there are cases where you would want to manipulate a resource, e.g. add, change or remove elements. The namespace Vonk.Core.ElementModel has methods to do so. All of these methods do NOT change the original structure (the input IResource or ISourceNode), but instead return an updated structure.
ISourceNode manipulation
All the ISourceNode extension methods can be used on IResource as well. If you need an IResource as result, just turn the resulting ISourceNode to an IResource again. So if you added an element to an ISourceNode:
IResource result = input.AddIfNotExists(SourceNode.Valued("active", "false")).ToIResource(input.InformationModel);
For some of the more common extension methods we provide an overload on IResource that does this for you, like IResource.Patch(...)
All the methods below are in the namespace Vonk.Core.ElementModel.ISourceNodeExtensions:
- Add(this ISourceNode original, ISourceNode newChild) ISourceNode
Add the
newChildas a child node to theoriginal. It will be added at the end of the Children.
- AddIf(this ISourceNode original, ISourceNode newChild, Func<ISourceNode, bool> addIf) ISourceNode
Add the
newChildas a child node to theoriginalif theaddIfpredicate onoriginalis met. It will be added at the end of the Children.
- AddIfNotExists(this ISourceNode original, ISourceNode newChild) ISourceNode
Add the
newChildas a child node to theoriginalif there is no child with the same name yet. It will be added at the end of the Children.
- AnnotateWith<T>(this ISourceNode original, T annotation, bool hideExisting = false) -> ISourceNode
Add an annotation of type T to the
original. When hideExisting == true, any existing annotations of type T are not visible anymore on the returned ISourceNode.
- GetBoundAnnotation<T>(this ISourceNode original, ) where T : class, IBoundAnnotation -> T
Retrieve an annotation that is bound directly to
original, not to any of the nodes it may decorate. (ISourceNode is immutable, to changes are usually a pile of wrappers around theoriginalSourceNode, and each of the wrappers can add / replace annotations.)
- RemoveEmptyNodes(this ISourceNode original, ISourceNode newChild) ISourceNode
Remove any nodes that have no value or children. This happens recursively: if a node has only children with empty values, it will be removed as well. This way the returned ISourceNode conforms to the invariant in the FHIR specification that an element either has a value or children.
- Child(this ISourceNode original, string name, int arrayIndex = 0) ISourceNode
Convenience method to get the child with name
nameat positionarrayIndex. Usually used to get a child of which you know there is only one:patientNode.Child("active")
- ChildString(this ISourceNode original, string name, int arrayIndex = 0) ISourceNode
Convenience method to get the value of the child with name
nameat positionarrayIndex. Usually used to get a child of which you know there is only one:patientNode.ChildString("id")
- ForceAdd(this ISourceNode original, string addAt, ISourceNode newChild) ISourceNode
Add the
newChildat locationaddAt. Create the intermediate nodes if necessary .
- AddOrReplace(this ISourceNode original, Func<ISourceNode, bool> match, ISourceNode toAdd, Func<ISourceNode, ISourceNode> replace) ISourceNode
Find any child nodes of
originalthat match thematchpredicate. Applyreplaceto them. If none are found, addtoAddas new child.
- Remove(this ISourceNode original, string location) ISourceNode
Remove the node at
location, if any. If that results in parent nodes becoming empty (no Text, no Children), those are removed as well.
- SelectNodes(this ISourceNode original, string fhirPath) IEnumerable<ISourceNode>
Run
fhirPathover theoriginal, but with the limitations of untyped nodes. It will return the matching nodes. Use valueDateTime/valueBoolean instead of just ‘value’ for choice types. Only use this method if you are familiar with the differences in the naming of nodes between ISourceNode and ITypedElement.
- SelectText(this ISourceNode original, string fhirPath) string
Run
fhirPathover theoriginal, but with the limitations of untyped nodes. Returns theTextof the first matching node. Use valueDateTime/valueBoolean instead of just ‘value’ for choice types. Only use this method if you are familiar with the differences in the naming of nodes between ISourceNode and ITypedElement.
- Patch(this ISourceNode original, string location, Func<ISourceNode, ISourceNode> patch) ISourceNode
Find any nodes at
locationand applypatchto them. Forpatchyou can use other methods listed here likeRename,AddorRevalue.locationis evaluated as a fhirpath statement, with the limitations of untyped nodes.
- ForcePatch(this ISourceNode original, string forcePath, Func<ISourceNode, ISourceNode> patch) ISourceNode
Enforce that
forcePathexists. Then patch the resulting node(s) withpatch.
- ForcePatchAt(this ISourceNode original, string fromLocation, string forcePath, Func<ISourceNode, ISourceNode> patch) ISourceNode
For each node matching the
fromLocation: enforce thatfromLocation.forcePathexists, then patch the resulting node(s) withpatch. E.g. someBundle.ForcePatchAt(“entry”, “request”, node => node.Add(SourceNode.Valued(“url”, “someUrl”)) will add request.url with value “someUrl” to every entry.
- Relocate(this ISourceNode original, string newLocation) ISourceNode
Set
original.Locationto the newLocation, and update all its descendants’Locationproperties recursively.
- Rename(this ISourceNode original, string newName) ISourceNode
Set
original.Nameto thenewName.
- Revalue(this ISourceNode original, string newValue) ISourceNode
Set
original.TexttonewValue.
- AnnotateWithSourceNode(this ISourceNode original) ISourceNode
Add
originalas annotation to itself. Very specific use case.
ITypedElement manipulation
All the methods below are in the namespace Vonk.Core.ElementModel.ITypedElementExtensions:
- Cache(this ITypedElement original) ITypedElement
Prevent recalculation of the Children upon every access.
- DefinitionSummary(this ITypedElement element, IStructureDefinitionSummaryProvider provider) IStructureDefinitionSummary
Returns the summary for the actual type of the element. Especially useful if the element is of a choicetype.
- AddParent(this ITypedElement element) ITypedElement
Add
Vonk.Core.ElementModel.IParentProviderannotations toelementand its descendants.
- GetParent(this ITypedElement element) ITypedElement
Get the parent of this element, through the
Vonk.Core.ElementModel.IParentProviderannotation (if present).
- AddTreePath(this ITypedElement element) ITypedElement
Add the
Vonk.Core.ElementModel.ITreePathGeneratorannotation. TreePath is the Location without any indexes (no [n] at the end).
- GetTreePath(this ITypedElement element) string
Get the value of the
Vonk.Core.ElementModel.ITreePathGeneratorannotation, if present. TreePath is the Location without any indexes (no [n] at the end).
