Skip to content

Commit

Permalink
Further changes to support edge cases - handling both inserts and del…
Browse files Browse the repository at this point in the history
…etes using index traits.
  • Loading branch information
Cameron Wills committed Sep 29, 2016
1 parent 61befb1 commit be83d03
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 16 deletions.
70 changes: 64 additions & 6 deletions FatAntelope.Tests/XdtDiffWriterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,64 @@ public void InsertBefore()
AssertCanTransform(source, target);
}

[TestMethod]
public void InsertFollowedByParentChange()
{
// Insert a child element into a parent element that has a change affecting its unique trait.

var source = @"
<root>
<parent name='elem1' />
<parent name='elem3'>
<child name='child1' />
<child name='child3' />
</parent>
</root>";

var target = @"
<root>
<parent name='elem1' />
<parent name='elem2' />
<parent name='DIFFERENT'>
<child name='child1' />
<child name='child2' />
<child name='child3' />
</parent>
</root>";

var patch = GetPatch(source, target);

AssertCanTransform(source, target);
}

[TestMethod]
public void InsertAndRemove()
{
// Insert a child element into a parent element that has a change affecting its unique trait.

var source = @"
<root>
<type1 />
<type1 />
<type1 />
<type1 />
</root>";

var target = @"
<root>
<type1 />
<type1 />
<type2 />
<type1 />
<type2 />
<type2 />
</root>";

var patch = GetPatch(source, target);

AssertCanTransform(source, target);
}

[TestMethod]
public void InsertChildWithParentChange()
{
Expand Down Expand Up @@ -181,14 +239,14 @@ public void InsertBeforeSingle()
var patch = GetPatch(source, target);

// Values
AssertValue(patch.SelectSingleNode("/root/child[1]/@name"), "child1");
AssertValue(patch.SelectSingleNode("/root/child[2]/@name"), "child2");

// Transform = InsertBefore
AssertTransform(patch.SelectSingleNode("/root/child[1]"), "InsertBefore(/root/*[1])");
AssertValue(patch.SelectSingleNode("/root/child[1]/@name"), "child2");
AssertValue(patch.SelectSingleNode("/root/child[2]/@name"), "child1");

// Transform = SetAttributes
AssertTransform(patch.SelectSingleNode("/root/child[2]"), "SetAttributes(value)");
AssertTransform(patch.SelectSingleNode("/root/child[1]"), "SetAttributes(value)");

// Transform = InsertBefore
AssertTransform(patch.SelectSingleNode("/root/child[2]"), "InsertBefore(/root/*[1])");

AssertCanTransform(source, target);
}
Expand Down
38 changes: 28 additions & 10 deletions FatAntelope/Writers/XdtDiffWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -226,23 +226,41 @@ private XmlNode WriteElement(XNode oldElement, XNode newElement, XmlNode target,
: null;
}

// Process child elements
// Calculate xpath to current element for use in child node changes
path = GetPath(path, oldElement, oldTrait);

// Process 'changed' child elements first
for (var i = 0; i < newElement.Elements.Length; i++ )
{
var child = newElement.Elements[i];
if (child.Match == MatchType.Change || child.Match == MatchType.NoMatch)
if (child.Match == MatchType.Change)
WriteElement(child.Matching, child, element, path, i);
}

// Remove elements that dont exist in the target config
// HACK: Reverse to remove from the end first, this prevents the condition when using
// positional predicates to remove child[1] and then try also to remove child[2],
// however, it has now moved up into position [1].
foreach(var child in oldElement.Elements.Reverse())

// Process 'inserted' and 'removed' child elements together in reverse
var newElements = newElement.Elements;
var oldElements = oldElement.Elements;
var max = newElements.Length > oldElements.Length
? newElements.Length
: oldElements.Length;

for (var i = max - 1; i >= 0; i--)
{
if (child.Match == MatchType.NoMatch)
WriteElement(child, null, element, path, 0);
// Remove child element
if(oldElements.Length > i)
{
var remove = oldElements[i];
if (remove.Match == MatchType.NoMatch)
WriteElement(remove, null, element, path, 0);
}

// Insert child element
if (newElements.Length > i)
{
var insert = newElements[i];
if (insert.Match == MatchType.NoMatch)
WriteElement(insert.Matching, insert, element, path, i);
}
}

return element;
Expand Down

0 comments on commit be83d03

Please sign in to comment.