/// <summary> /// Advance the navigator to the first reslice of the current named slice. /// Skip any existing child elements and/or child reslicing constraints. /// Otherwise remain positioned at the current element. /// </summary> /// <returns><c>true</c> if succesful, <c>false</c> otherwise.</returns> public static bool MoveToFirstReslice(this ElementDefinitionNavigator nav) { if (nav == null) { throw Error.ArgumentNull(nameof(nav)); } if (nav.Current == null) { throw Error.Argument(nameof(nav), "Cannot move navigator to previous slice. Current node is not set."); } var sliceName = nav.Current.Name; if (string.IsNullOrEmpty(sliceName)) { throw Error.Argument(nameof(nav), "The current element is not a named slice."); } var bm = nav.Bookmark(); if (nav.MoveToNextSliceAtAnyLevel()) { if (ElementDefinitionNavigator.IsResliceOf(nav.Current.Name, sliceName)) { return(true); } } // No match, restore original position nav.ReturnToBookmark(bm); return(false); }
/// <summary>Determines if the element with the specified name represents a type slice for the current (choice) element.</summary> /// <returns><c>true</c> if the element name represents a type slice of the current element, <c>false</c> otherwise.</returns> internal static bool IsRenamedChoiceTypeElement(this ElementDefinitionNavigator nav, string diffName) { if (nav == null) { throw Error.ArgumentNull(nameof(nav)); } return(ElementDefinitionNavigator.IsRenamedChoiceTypeElement(nav.PathName, diffName)); }
public ElementDefinitionNavigator ShallowCopy() { var result = new ElementDefinitionNavigator(); result.Elements = this.Elements; result.OrdinalPosition = this.OrdinalPosition; result.StructureDefinition = this.StructureDefinition; return(result); }
public ElementDefinitionNavigator(ElementDefinitionNavigator other) { if (other == null) { throw Error.ArgumentNull(nameof(other)); } Elements = other.Elements.ToList(); OrdinalPosition = other.OrdinalPosition; StructureDefinition = other.StructureDefinition; }
public static bool DeleteChildren(this ElementDefinitionNavigator nav) { var parent = nav.Bookmark(); if (nav.MoveToFirstChild()) { while (!nav.IsAtBookmark(parent)) { nav.DeleteTree(); } } return(true); }
/// <summary> /// Advance the navigator forward to the slicing constraint in the current slice group with the specified slice name. /// Otherwise remain positioned at the current element. /// </summary> /// <returns><c>true</c> if succesful, <c>false</c> otherwise.</returns> public static bool MoveToNextSliceAtAnyLevel(this ElementDefinitionNavigator nav, string sliceName) { var bm = nav.Bookmark(); while (nav.MoveToNextSliceAtAnyLevel()) { if (StringComparer.Ordinal.Equals(nav.Current.Name, sliceName)) { return(true); } } nav.ReturnToBookmark(bm); return(false); }
// [WMR 20160802] NEW - Move to the specified ElementDefinition /// <summary>Move the navigator to the specified element.</summary> /// <returns><c>true</c> if succesful, <c>false</c> otherwise.</returns> public static bool MoveTo(this ElementDefinitionNavigator nav, ElementDefinition element) { if (nav == null) { throw Error.ArgumentNull(nameof(nav)); } if (element == null) { throw Error.ArgumentNull(nameof(element)); } var bm = new Bookmark(element); return(nav.ReturnToBookmark(bm)); }
/// <summary>Move the navigator to the first element with the specified path.</summary> /// <returns><c>true</c> if succesful, <c>false</c> otherwise.</returns> public static bool JumpToFirst(this ElementDefinitionNavigator nav, string path) { // Find method performs parameter validation // if (nav == null) { throw Error.ArgumentNull(nameof(nav)); } // if (path == null) { throw Error.ArgumentNull(nameof(path)); } var matches = Find(nav, path); if (matches.Any()) { nav.ReturnToBookmark(matches.First()); return(true); } return(false); }
/// <summary>Recursively clone the current element and all it's children and return a new navigator for the resulting subtree.</summary> /// <returns>A new <see cref="ElementDefinitionNavigator"/> instance that wraps the cloned element list.</returns> internal static ElementDefinitionNavigator CloneSubtree(this ElementDefinitionNavigator nav) { if (nav == null) { throw new ArgumentNullException(nameof(nav)); } if (nav.Current == null) { throw new ArgumentException(nameof(nav)); } var result = new ElementDefinitionNavigator(new ElementDefinition[] { (ElementDefinition)nav.Current.DeepCopy() }); result.MoveToFirstChild(); result.CopyChildren(nav); return(result); }
private static IEnumerable <Bookmark> locateChildren(ElementDefinitionNavigator nav, IEnumerable <string> path, bool partial) { Debug.Assert(nav != null); // Caller should validate var child = path.First(); var rest = path.Skip(1); var bm = nav.Bookmark(); if (nav.MoveToChild(child)) { var result = new List <Bookmark>(); do { if (!rest.Any()) { // Exact match! result.Add(nav.Bookmark()); } else if (!nav.HasChildren && partial) { // This is as far as we can get in this structure, // so this is a hit too if partial hits are OK result.Add(nav.Bookmark()); } else { // So, no hit, but we have children that might fit the bill. result.AddRange(locateChildren(nav, rest, partial)); } // Try this for the other matching siblings too... }while (nav.MoveToNext(child)); // We've scanned all my children and collected the results, // move the navigator back to where we were before nav.ReturnToBookmark(bm); return(result); } else { return(Enumerable.Empty <Bookmark>()); } }
// [WMR 20160802] NEW /// <summary>Move the navigator to the first preceding sibling element with the specified name, if it exists.</summary> /// <returns><c>true</c> if succesful, <c>false</c> otherwise.</returns> public static bool MoveToPrevious(this ElementDefinitionNavigator nav, string name) { if (nav == null) { throw Error.ArgumentNull(nameof(nav)); } var bm = nav.Bookmark(); while (nav.MoveToPrevious()) { if (nav.PathName == name) { return(true); } } nav.ReturnToBookmark(bm); return(false); }
/// <summary> /// Enumerate any succeeding direct child slices of the specified element. /// Skip any intermediate child elements and re-slice elements. /// When finished, return the navigator to the initial position. /// </summary> /// <param name="intro"></param> /// <param name="atRoot">Specify <c>true</c> for finding direct (simple) slices, or <c>false</c> for finding re-slices.</param> /// <returns>A sequence of <see cref="Bookmark"/> instances.</returns> internal static IEnumerable <Bookmark> FindMemberSlices(this ElementDefinitionNavigator intro, bool atRoot) { var bm = intro.Bookmark(); var path = intro.Current.Path; var pathName = intro.PathName; var name = intro.Current.Name; while (intro.MoveToNext(pathName)) { var curName = intro.Current.Name; if (atRoot) { // Is this the slice-intro of the un-resliced original element? Then my name == null or // (in DSTU2) my name has no slicing separator (since name is used both for slicing and // re-use of constraints, e.g. Composition.section.name, just == null is not enough) // I am the root slice, my slices would be the unnamed slices (though this is strictly seen not correct, every slice needs a name) // and every slice with a non-resliced name if (curName == null) { yield return(intro.Bookmark()); } if (!ElementDefinitionNavigator.IsResliceName(curName)) { yield return(intro.Bookmark()); } } else { // Else, if I am a named slice, I am a slice myself, but also the intro to a nested re-sliced group, // so include only my children in my group... if (ElementDefinitionNavigator.IsResliceOf(curName, name)) { yield return(intro.Bookmark()); } } // Else...there might be something wrong, I need to add logic here to find slices that are out of // order, of have a resliced name that does not start with the last slice intro we found. } intro.ReturnToBookmark(bm); }
/// <summary> /// Insert the children of the source navigator under the node pointed to by this Navigator. /// </summary> /// <param name="dest"></param> /// <param name="source"></param> /// <returns></returns> public static bool CopyChildren(this ElementDefinitionNavigator dest, ElementDefinitionNavigator source) { if (dest.HasChildren) { return(false); // Protect children from being overwritten } if (!source.MoveToFirstChild()) { return(true); // Nothing to copy, but successful anyway } bool firstChild = true; do { var copiedChild = (ElementDefinition)source.Current.DeepCopy(); if (firstChild) { // The first time, create a new child in the destination dest.InsertFirstChild(copiedChild); firstChild = false; } else { // Then insert other childs after that dest.InsertAfter(copiedChild); } // If there are nested children in the source, insert them under // the newly inserted node in the destination if (source.HasChildren) { dest.CopyChildren(source); } }while (source.MoveToNext()); // Bring both source & destination back one step to the original parents source.MoveToParent(); dest.MoveToParent(); return(true); }
/// <summary>Move the navigator to the first child element with the specified name, if it exists.</summary> /// <returns><c>true</c> if succesful, <c>false</c> otherwise.</returns> public static bool MoveToChild(this ElementDefinitionNavigator nav, string name) { if (nav == null) { throw Error.ArgumentNull(nameof(nav)); } if (nav.MoveToFirstChild()) { do { if (nav.PathName == name) { return(true); } }while (nav.MoveToNext()); nav.MoveToParent(); } return(false); }
/* * /// <summary> * /// If the current element is a slice entry, then advance the navigator to the first associated named slice. * /// Otherwise remain positioned at the current element. * /// </summary> * /// <returns><c>true</c> if succesful, <c>false</c> otherwise.</returns> * public static bool MoveToFirstSlice(this ElementDefinitionNavigator nav) * { * if (nav == null) { throw Error.ArgumentNull(nameof(nav)); } * if (nav.Current == null) { throw Error.Argument(nameof(nav), "Cannot move navigator to previous slice. Current node is not set."); } * if (nav.Current.Slicing != null) * { * var bm = nav.Bookmark(); * if (nav.MoveToNextSliceAtAnyLevel()) { return true; } * nav.ReturnToBookmark(bm); * } * return false; * } */ /// <summary> /// Advance the navigator to the next slice in the current slice group and on the current slicing level. /// Skip any existing child elements and/or child reslicing constraints. /// Otherwise remain positioned at the current element. /// </summary> /// <returns><c>true</c> if succesful, <c>false</c> otherwise.</returns> public static bool MoveToNextSlice(this ElementDefinitionNavigator nav) { if (nav == null) { throw Error.ArgumentNull(nameof(nav)); } if (nav.Current == null) { throw Error.Argument(nameof(nav), "Cannot move navigator to next slice. Current node is not set."); } var bm = nav.Bookmark(); var name = nav.PathName; var startSliceName = nav.Current.Name; var startBaseSliceName = ElementDefinitionNavigator.GetBaseSliceName(startSliceName); while (nav.MoveToNext(name)) { var sliceName = nav.Current.Name; // Handle unnamed slices, eg. extensions if (startSliceName == null && sliceName == null) { return(true); } if (ElementDefinitionNavigator.IsSiblingSliceOf(startSliceName, sliceName)) { return(true); } if (startBaseSliceName != null && sliceName.Length > startBaseSliceName.Length && !sliceName.StartsWith(startBaseSliceName)) { break; } } // No match, restore original position nav.ReturnToBookmark(bm); return(false); }
private static void rebaseChildren(ElementDefinitionNavigator nav, string path, List <string> newPaths) { var bm = nav.Bookmark(); if (nav.MoveToFirstChild()) { do { var newPath = path + "." + nav.Current.GetNameFromPath(); newPaths.Add(newPath); if (nav.HasChildren) { rebaseChildren(nav, newPath, newPaths); } }while (nav.MoveToNext()); nav.ReturnToBookmark(bm); } }
public static IEnumerable <Bookmark> Approach(this ElementDefinitionNavigator nav, string path) { if (nav == null) { throw Error.ArgumentNull(nameof(nav)); } if (path == null) { throw Error.ArgumentNull(nameof(path)); } var parts = path.Split('.'); var bm = nav.Bookmark(); nav.Reset(); var result = locateChildren(nav, parts, partial: true); nav.ReturnToBookmark(bm); return(result); }
/// <summary> /// Rewrites the Path's of the elements in a structure so they are based on the given path: the root /// of the given structure will become the given path, it's children will be relocated below that path /// </summary> /// <param name="elements">A list of element definitions that will be rebased on the path.</param> /// <param name="path">The path to rebase the structure on.</param> public static void Rebase(this IList <ElementDefinition> elements, string path) { var nav = new ElementDefinitionNavigator(elements); if (nav.MoveToFirstChild()) { var newPaths = new List <string>() { path }; rebaseChildren(nav, path, newPaths); Debug.Assert(elements.Count == newPaths.Count); // Can only change the paths after navigating the tree, otherwise the // navigation functions (which are based on the paths) won't function correctly for (var i = 0; i < elements.Count; i++) { elements[i].Path = newPaths[i]; } } }
public static bool AppendChild(this ElementDefinitionNavigator nav, ElementDefinition child) { var bm = nav.Bookmark(); if (nav.MoveToFirstChild()) { while (nav.MoveToNext()) { ; } var result = nav.InsertAfter(child); if (!result) { nav.ReturnToBookmark(bm); } return(result); } else { return(nav.InsertFirstChild(child)); } }
public static string GetParentNameFromPath(this ElementDefinition defn) { return(ElementDefinitionNavigator.GetParentPath(defn.Path)); }
// [WMR 20160805] New public static bool IsRootElement(this ElementDefinition defn) => defn != null && ElementDefinitionNavigator.IsRootPath(defn.Path);
public static bool IsExtension(this ElementDefinition defn) => defn != null && ElementDefinitionNavigator.IsExtensionPath(defn.Path);
/// <summary> /// Advance the navigator to the immediately following slicing constraint in the current slice group, at any (re)slicing level. /// Skip any existing child elements. /// Otherwise remain positioned at the current element. /// </summary> /// <returns><c>true</c> if succesful, <c>false</c> otherwise.</returns> public static bool MoveToNextSliceAtAnyLevel(this ElementDefinitionNavigator nav) => nav.MoveToNext(nav.PathName);
/// <summary>Move the navigator to the first preceding or following sibling element with the specified name, if it exists.</summary> /// <returns><c>true</c> if succesful, <c>false</c> otherwise.</returns> public static bool MoveTo(this ElementDefinitionNavigator nav, string name) { // MoveNext method performs parameter validation return(MoveToNext(nav, name) || MoveToPrevious(nav, name)); }