Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds compatibility with dotnet 6 #39

Open
wants to merge 2 commits into
base: vNext
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions OpenXmlPowerTools.Tests/OpenXmlPowerTools.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net452;net461;netcoreapp2.0</TargetFrameworks>
<TargetFrameworks>net452;net461;net6.0</TargetFrameworks>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
@@ -19,7 +19,7 @@
<ProjectReference Include="..\OpenXmlPowerTools\OpenXmlPowerTools.csproj" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
<ItemGroup Condition=" '$(TargetFramework)' == 'net452' ">
<Reference Include="WindowsBase" />
</ItemGroup>

67 changes: 67 additions & 0 deletions OpenXmlPowerTools/Comparer/ComparisonUnit.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace OpenXmlPowerTools
{
public abstract class ComparisonUnit
{
private int? _descendantContentAtomsCount;

public CorrelationStatus CorrelationStatus { get; set; }

public List<ComparisonUnit> Contents { get; protected set; }

public string SHA1Hash { get; protected set; }

public int DescendantContentAtomsCount
{
get
{
if (_descendantContentAtomsCount != null) return (int) _descendantContentAtomsCount;

_descendantContentAtomsCount = DescendantContentAtoms().Count();
return (int) _descendantContentAtomsCount;
}
}

private IEnumerable<ComparisonUnit> Descendants()
{
var comparisonUnitList = new List<ComparisonUnit>();
DescendantsInternal(this, comparisonUnitList);
return comparisonUnitList;
}

public IEnumerable<ComparisonUnitAtom> DescendantContentAtoms()
{
return Descendants().OfType<ComparisonUnitAtom>();
}

private static void DescendantsInternal(
ComparisonUnit comparisonUnit,
List<ComparisonUnit> comparisonUnitList)
{
foreach (ComparisonUnit cu in comparisonUnit.Contents)
{
comparisonUnitList.Add(cu);
if (cu.Contents != null && cu.Contents.Any())
DescendantsInternal(cu, comparisonUnitList);
}
}

public abstract string ToString(int indent);

internal static string ComparisonUnitListToString(ComparisonUnit[] cul)
{
var sb = new StringBuilder();
sb.Append("Dump Comparision Unit List To String" + Environment.NewLine);
foreach (ComparisonUnit item in cul) sb.Append(item.ToString(2) + Environment.NewLine);

return sb.ToString();
}
}
}
215 changes: 215 additions & 0 deletions OpenXmlPowerTools/Comparer/ComparisonUnitAtom.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using DocumentFormat.OpenXml.Packaging;

namespace OpenXmlPowerTools
{
public class ComparisonUnitAtom : ComparisonUnit
{
public ComparisonUnitAtom(
XElement contentElement,
XElement[] ancestorElements,
OpenXmlPart part,
WmlComparerSettings settings)
{
ContentElement = contentElement;
AncestorElements = ancestorElements;
Part = part;
RevTrackElement = GetRevisionTrackingElementFromAncestors(contentElement, AncestorElements);

if (RevTrackElement == null)
{
CorrelationStatus = CorrelationStatus.Equal;
}
else
{
if (RevTrackElement.Name == W.del)
{
CorrelationStatus = CorrelationStatus.Deleted;
}
else if (RevTrackElement.Name == W.ins)
{
CorrelationStatus = CorrelationStatus.Inserted;
}
}

var sha1Hash = (string) contentElement.Attribute(PtOpenXml.SHA1Hash);
if (sha1Hash != null)
{
SHA1Hash = sha1Hash;
}
else
{
string shaHashString = GetSha1HashStringForElement(ContentElement, settings);
SHA1Hash = WmlComparerUtil.SHA1HashStringForUTF8String(shaHashString);
}
}

// AncestorElements are kept in order from the body to the leaf, because this is the order in which we need to access in order
// to reassemble the document. However, in many places in the code, it is necessary to find the nearest ancestor, i.e. cell
// so it is necessary to reverse the order when looking for it, i.e. look from the leaf back to the body element.

public XElement[] AncestorElements { get; }

public XElement ContentElement { get; }

public XElement RevTrackElement { get; }

public string[] AncestorUnids { get; set; }

public ComparisonUnitAtom ComparisonUnitAtomBefore { get; set; }

public XElement ContentElementBefore { get; set; }

public OpenXmlPart Part { get; }

private static string GetSha1HashStringForElement(XElement contentElement, WmlComparerSettings settings)
{
string text = contentElement.Value;
if (settings.CaseInsensitive)
{
text = text.ToUpper(settings.CultureInfo);
}

return contentElement.Name.LocalName + text;
}

private static XElement GetRevisionTrackingElementFromAncestors(
XElement contentElement,
IEnumerable<XElement> ancestors)
{
return contentElement.Name == W.pPr
? contentElement.Elements(W.rPr).Elements().FirstOrDefault(e => e.Name == W.del || e.Name == W.ins)
: ancestors.FirstOrDefault(a => a.Name == W.del || a.Name == W.ins);
}

public override string ToString()
{
return ToString(0);
}

public override string ToString(int indent)
{
const int xNamePad = 16;
string indentString = "".PadRight(indent);

var sb = new StringBuilder();
sb.Append(indentString);

var correlationStatus = "";
if (CorrelationStatus != CorrelationStatus.Nil)
{
correlationStatus = $"[{CorrelationStatus.ToString().PadRight(8)}] ";
}

if (ContentElement.Name == W.t || ContentElement.Name == W.delText)
{
sb.AppendFormat(
"Atom {0}: {1} {2} SHA1:{3} ",
PadLocalName(xNamePad, this),
ContentElement.Value,
correlationStatus,
SHA1Hash.Substring(0, 8));

AppendAncestorsDump(sb, this);
}
else
{
sb.AppendFormat(
"Atom {0}: {1} SHA1:{2} ",
PadLocalName(xNamePad, this),
correlationStatus,
SHA1Hash.Substring(0, 8));

AppendAncestorsDump(sb, this);
}

return sb.ToString();
}

public string ToStringAncestorUnids()
{
return ToStringAncestorUnids(0);
}

private string ToStringAncestorUnids(int indent)
{
const int xNamePad = 16;
string indentString = "".PadRight(indent);

var sb = new StringBuilder();
sb.Append(indentString);

var correlationStatus = "";
if (CorrelationStatus != CorrelationStatus.Nil)
{
correlationStatus = $"[{CorrelationStatus.ToString().PadRight(8)}] ";
}

if (ContentElement.Name == W.t || ContentElement.Name == W.delText)
{
sb.AppendFormat(
"Atom {0}: {1} {2} SHA1:{3} ",
PadLocalName(xNamePad, this),
ContentElement.Value,
correlationStatus,
SHA1Hash.Substring(0, 8));

AppendAncestorsUnidsDump(sb, this);
}
else
{
sb.AppendFormat(
"Atom {0}: {1} SHA1:{2} ",
PadLocalName(xNamePad, this),
correlationStatus,
SHA1Hash.Substring(0, 8));

AppendAncestorsUnidsDump(sb, this);
}

return sb.ToString();
}

private static string PadLocalName(int xNamePad, ComparisonUnitAtom item)
{
return (item.ContentElement.Name.LocalName + " ").PadRight(xNamePad, '-') + " ";
}

private static void AppendAncestorsDump(StringBuilder sb, ComparisonUnitAtom sr)
{
string s = sr
.AncestorElements.Select(p => p.Name.LocalName + GetUnid(p) + "/")
.StringConcatenate()
.TrimEnd('/');

sb.Append("Ancestors:" + s);
}

private static void AppendAncestorsUnidsDump(StringBuilder sb, ComparisonUnitAtom sr)
{
var zipped = sr.AncestorElements.Zip(sr.AncestorUnids, (a, u) => new
{
AncestorElement = a,
AncestorUnid = u
});

string s = zipped
.Select(p => p.AncestorElement.Name.LocalName + "[" + p.AncestorUnid.Substring(0, 8) + "]/")
.StringConcatenate().TrimEnd('/');

sb.Append("Ancestors:" + s);
}

private static string GetUnid(XElement p)
{
var unid = (string) p.Attribute(PtOpenXml.Unid);
return unid == null ? "" : "[" + unid.Substring(0, 8) + "]";
}
}
}
77 changes: 77 additions & 0 deletions OpenXmlPowerTools/Comparer/ComparisonUnitGroup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace OpenXmlPowerTools
{
internal class ComparisonUnitGroup : ComparisonUnit
{
public ComparisonUnitGroup(
IEnumerable<ComparisonUnit> comparisonUnitList,
ComparisonUnitGroupType groupType,
int level)
{
Contents = comparisonUnitList.ToList();
ComparisonUnitGroupType = groupType;
ComparisonUnit first = Contents.First();
ComparisonUnitAtom comparisonUnitAtom = GetFirstComparisonUnitAtomOfGroup(first);

XElement[] ancestorsToLookAt = comparisonUnitAtom
.AncestorElements
.Where(e => e.Name == W.tbl || e.Name == W.tr || e.Name == W.tc || e.Name == W.p || e.Name == W.txbxContent)
.ToArray();

XElement ancestor = ancestorsToLookAt[level];
if (ancestor == null) throw new OpenXmlPowerToolsException("Internal error: ComparisonUnitGroup");

SHA1Hash = (string) ancestor.Attribute(PtOpenXml.SHA1Hash);
CorrelatedSHA1Hash = (string) ancestor.Attribute(PtOpenXml.CorrelatedSHA1Hash);
StructureSHA1Hash = (string) ancestor.Attribute(PtOpenXml.StructureSHA1Hash);
}

public ComparisonUnitGroupType ComparisonUnitGroupType { get; }

public string CorrelatedSHA1Hash { get; }

public string StructureSHA1Hash { get; }

private static ComparisonUnitAtom GetFirstComparisonUnitAtomOfGroup(ComparisonUnit group)
{
ComparisonUnit thisGroup = group;
while (true)
{
if (thisGroup is ComparisonUnitGroup tg)
{
thisGroup = tg.Contents.First();
continue;
}

if (!(thisGroup is ComparisonUnitWord tw))
{
throw new OpenXmlPowerToolsException("Internal error: GetFirstComparisonUnitAtomOfGroup");
}

var ca = (ComparisonUnitAtom) tw.Contents.First();
return ca;
}
}

public override string ToString(int indent)
{
var sb = new StringBuilder();
sb.Append("".PadRight(indent) + "Group Type: " + ComparisonUnitGroupType + " SHA1:" + SHA1Hash + Environment.NewLine);

foreach (ComparisonUnit comparisonUnitAtom in Contents)
{
sb.Append(comparisonUnitAtom.ToString(indent + 2));
}

return sb.ToString();
}
}
}
14 changes: 14 additions & 0 deletions OpenXmlPowerTools/Comparer/ComparisonUnitGroupType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace OpenXmlPowerTools
{
internal enum ComparisonUnitGroupType
{
Paragraph,
Table,
Row,
Cell,
Textbox,
};
}
Loading