/// <summary> /// Insert the children of the current source node under the node pointed to by the destination. /// </summary> /// <param name="dest"></param> /// <param name="source"></param> /// <returns></returns> public static bool CopyChildren(this BaseElementNavigator dest, ElementNavigator 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 = (Profile.ElementComponent)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; }
public Profile.ProfileStructureComponent Expand(Profile.ProfileStructureComponent differential) { var baseStructure = _loader.LocateBaseStructure(differential.TypeElement); if (baseStructure == null) throw Error.InvalidOperation("Could not locate the base profile for type {0}", differential.TypeElement.ToString()); var baseUri = StructureLoader.BuildBaseStructureUri(differential.TypeElement).ToString(); var snapshot = (Profile.ProfileStructureComponent)baseStructure.DeepCopy(); snapshot.SetStructureForm(StructureForm.Snapshot); snapshot.SetStructureBaseUri(baseUri.ToString()); mergeStructure(snapshot, differential); var fullDifferential = new DifferentialTreeConstructor(differential).MakeTree(); var snapNav = new ElementNavigator(snapshot); snapNav.MoveToFirstChild(); var diffNav = new ElementNavigator(fullDifferential); diffNav.MoveToFirstChild(); merge(snapNav, diffNav); //TODO: Merge search params? snapNav.CommitChanges(); return snapshot; }
public Profile.ProfileStructureComponent Expand(Profile.ProfileStructureComponent differential) { var baseStructure = _loader.LocateBaseStructure(differential.TypeElement); if (baseStructure == null) { throw Error.InvalidOperation("Could not locate the base profile for type {0}", differential.TypeElement.ToString()); } var baseUri = StructureLoader.BuildBaseStructureUri(differential.TypeElement).ToString(); var snapshot = (Profile.ProfileStructureComponent)baseStructure.DeepCopy(); snapshot.SetStructureForm(StructureForm.Snapshot); snapshot.SetStructureBaseUri(baseUri.ToString()); mergeStructure(snapshot, differential); var fullDifferential = new DifferentialTreeConstructor(differential).MakeTree(); var snapNav = new ElementNavigator(snapshot); snapNav.MoveToFirstChild(); var diffNav = new ElementNavigator(fullDifferential); diffNav.MoveToFirstChild(); merge(snapNav, diffNav); //TODO: Merge search params? snapNav.CommitChanges(); return(snapshot); }
private void merge(ElementNavigator snap, ElementNavigator diff) { mergeElementAttributes(snap.Current, diff.Current); // If there are children, move into them, and recursively merge them if (diff.MoveToFirstChild()) { if (!snap.HasChildren) { // The differential moves into an element that has no children in the base. // This is allowable if the base's element has a nameReference or a TypeRef, // in which case needs to be expanded before we can move to the path indicated // by the differential expandBaseElement(snap, diff); } // Due to how MoveToFirstChild() works, we have to move to the first matching *child* // when entering the loop for the first time, after that we can look for the next // matching *sibling*. bool firstEntry = true; do { if ((firstEntry && !snap.MoveToChild(diff.PathName)) || (!firstEntry && !snap.MoveToNext(diff.PathName))) { throw Error.InvalidOperation("Differential has a constraint for path {0}, which does not exist in its base", diff.PathName); } firstEntry = false; // Child found in both, merge them if (childNameRepeats(diff) || diff.Current.IsExtension()) { // The child in the diff repeats or we recognize it as an extension slice -> we're on the first element of a slice! mergeSlice(snap, diff); } else { merge(snap, diff); } }while (diff.MoveToNext()); // After the merge, return the diff and snapho back to their original position diff.MoveToParent(); snap.MoveToParent(); } }
/// <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="root">The structure that will be rebased on the path</param> /// <param name="path">The path to rebase the structure on</param> public static void Rebase(this Profile.ProfileStructureComponent root, string path) { var nav = new ElementNavigator(root); if (nav.MoveToFirstChild()) { var newPaths = new List<string>(); newPaths.Add(path); rebaseChildren(nav, path, newPaths); // 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 < root.Element.Count; i++) root.Element[i].Path = newPaths[i]; } }
private void merge(ElementNavigator snap, ElementNavigator diff) { mergeElementAttributes(snap.Current, diff.Current); // If there are children, move into them, and recursively merge them if (diff.MoveToFirstChild()) { if (!snap.HasChildren) { // The differential moves into an element that has no children in the base. // This is allowable if the base's element has a nameReference or a TypeRef, // in which case needs to be expanded before we can move to the path indicated // by the differential expandBaseElement(snap, diff); } // Due to how MoveToFirstChild() works, we have to move to the first matching *child* // when entering the loop for the first time, after that we can look for the next // matching *sibling*. bool firstEntry = true; do { if( (firstEntry && !snap.MoveToChild(diff.PathName)) || (!firstEntry && !snap.MoveToNext(diff.PathName)) ) throw Error.InvalidOperation("Differential has a constraint for path {0}, which does not exist in its base", diff.PathName); firstEntry = false; // Child found in both, merge them if (childNameRepeats(diff) || diff.Current.IsExtension()) { // The child in the diff repeats or we recognize it as an extension slice -> we're on the first element of a slice! mergeSlice(snap, diff); } else merge(snap, diff); } while (diff.MoveToNext()); // After the merge, return the diff and snapho back to their original position diff.MoveToParent(); snap.MoveToParent(); } }
/// <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="root">The structure that will be rebased on the path</param> /// <param name="path">The path to rebase the structure on</param> public static void Rebase(this Profile.ProfileStructureComponent root, string path) { var nav = new ElementNavigator(root); if (nav.MoveToFirstChild()) { var newPaths = new List <string>(); newPaths.Add(path); rebaseChildren(nav, path, newPaths); // 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 < root.Element.Count; i++) { root.Element[i].Path = newPaths[i]; } } }
/// <summary> /// Insert the children of the current source node under the node pointed to by the destination. /// </summary> /// <param name="dest"></param> /// <param name="source"></param> /// <returns></returns> public static bool CopyChildren(this BaseElementNavigator dest, ElementNavigator 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 = (Profile.ElementComponent)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); }
public void CopyChildTree() { var dest = createTestNav(); var struc = new Profile.ProfileStructureComponent(); struc.Element = new List<Profile.ElementComponent>(); struc.Element.Add(new Profile.ElementComponent() { Path = "X" }); struc.Element.Add(new Profile.ElementComponent() { Path = "X.Y1" }); struc.Element.Add(new Profile.ElementComponent() { Path = "X.Y2" }); struc.Element.Add(new Profile.ElementComponent() { Path = "X.Y2.Z1" }); struc.Element.Add(new Profile.ElementComponent() { Path = "X.Y2.Z2" }); var source = new ElementNavigator(struc); Assert.IsTrue(dest.JumpToFirst("A.D")); var dstPos = dest.OrdinalPosition; source.MoveToFirstChild(); var srcPos = source.OrdinalPosition; Assert.IsTrue(dest.CopyChildren(source)); Assert.AreEqual(srcPos, source.OrdinalPosition, "source did not remain on original position"); Assert.AreEqual(dstPos, dest.OrdinalPosition, "dest did not remain on original position"); Assert.IsTrue(dest.MoveToFirstChild()); Assert.AreEqual("Y1", dest.PathName); Assert.IsTrue(dest.MoveToNext()); Assert.AreEqual("Y2", dest.PathName); Assert.IsFalse(dest.MoveToNext()); Assert.IsTrue(dest.MoveToFirstChild()); Assert.AreEqual("Z1", dest.PathName); Assert.IsTrue(dest.MoveToNext()); Assert.AreEqual("Z2", dest.PathName); Assert.IsFalse(dest.MoveToNext()); }