public void MakeDifferentialTree() { var struc = new Profile.ProfileStructureComponent(); struc.Element = new List<Profile.ElementComponent>(); struc.Element.Add(new Profile.ElementComponent() { Path = "A.B.C1" }); struc.Element.Add(new Profile.ElementComponent() { Path = "A.B.C1" }); struc.Element.Add(new Profile.ElementComponent() { Path = "A.B.C2" }); struc.Element.Add(new Profile.ElementComponent() { Path = "A.B" }); struc.Element.Add(new Profile.ElementComponent() { Path = "A.B.C1.D" }); struc.Element.Add(new Profile.ElementComponent() { Path = "A.D.F" }); var tree = new DifferentialTreeConstructor(struc).MakeTree(); Assert.IsNotNull(tree); var nav = new ElementNavigator(tree); Assert.AreEqual(10, nav.Count); Assert.IsTrue(nav.MoveToChild("A")); Assert.IsTrue(nav.MoveToChild("B")); Assert.IsTrue(nav.MoveToChild("C1")); Assert.IsTrue(nav.MoveToNext("C1")); Assert.IsTrue(nav.MoveToNext("C2")); Assert.IsTrue(nav.MoveToParent()); // 1st A.B Assert.IsTrue(nav.MoveToNext() && nav.Path == "A.B"); // (now) 2nd A.B Assert.IsTrue(nav.MoveToChild("C1")); Assert.IsTrue(nav.MoveToChild("D")); Assert.IsTrue(nav.MoveToParent()); // A.B.C1 Assert.IsTrue(nav.MoveToParent()); // A.B (2nd) Assert.IsTrue(nav.MoveToNext() && nav.Path == "A.D"); Assert.IsTrue(nav.MoveToChild("F")); }
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> /// 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); }
/// <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; }
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(); } }