Skip to content

Commit

Permalink
Added IsEquivalent method to both LogixElement.cs and LogixType.cs to…
Browse files Browse the repository at this point in the history
… allow check of the underlying XML structure between two objects. Also some other clean up, documenting, and testing
  • Loading branch information
tnunnink committed Feb 3, 2024
1 parent 476cc05 commit 95b3ec4
Show file tree
Hide file tree
Showing 26 changed files with 522 additions and 36 deletions.
18 changes: 12 additions & 6 deletions src/.idea/.idea.L5Sharp/.idea/workspace.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/L5Sharp.Core/Components/AddOnInstruction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using JetBrains.Annotations;

namespace L5Sharp.Core;

Expand All @@ -14,6 +15,7 @@ namespace L5Sharp.Core;
/// See <a href="https://literature.rockwellautomation.com/idc/groups/literature/documents/rm/1756-rm084_-en-p.pdf">
/// `Logix 5000 Controllers Import/Export`</a> for more information.
/// </footer>
[PublicAPI]
[L5XType(L5XName.AddOnInstructionDefinition)]
public class AddOnInstruction : LogixComponent
{
Expand Down
2 changes: 2 additions & 0 deletions src/L5Sharp.Core/Components/Controller.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Xml.Linq;
using JetBrains.Annotations;

namespace L5Sharp.Core;

Expand All @@ -26,6 +27,7 @@ namespace L5Sharp.Core;
/// See <a href="https://literature.rockwellautomation.com/idc/groups/literature/documents/rm/1756-rm084_-en-p.pdf">
/// `Logix 5000 Controllers Import/Export`</a> for more information.
/// </footer>
[PublicAPI]
public class Controller : LogixComponent
{
private const string DateTimeFormat = "ddd MMM d HH:mm:ss yyyy";
Expand Down
2 changes: 2 additions & 0 deletions src/L5Sharp.Core/Components/DataType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using JetBrains.Annotations;

namespace L5Sharp.Core;

Expand All @@ -23,6 +24,7 @@ namespace L5Sharp.Core;
/// See <a href="https://literature.rockwellautomation.com/idc/groups/literature/documents/rm/1756-rm084_-en-p.pdf">
/// `Logix 5000 Controllers Import/Export`</a> for more information.
/// </footer>
[PublicAPI]
public class DataType : LogixComponent
{
/// <summary>
Expand Down
1 change: 1 addition & 0 deletions src/L5Sharp.Core/Components/Module.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace L5Sharp.Core;
/// See <a href="https://literature.rockwellautomation.com/idc/groups/literature/documents/rm/1756-rm084_-en-p.pdf">
/// `Logix 5000 Controllers Import/Export`</a> for more information.
/// </footer>
[PublicAPI]
public class Module : LogixComponent
{
/// <inheritdoc />
Expand Down
2 changes: 2 additions & 0 deletions src/L5Sharp.Core/Components/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using JetBrains.Annotations;

namespace L5Sharp.Core;

Expand All @@ -12,6 +13,7 @@ namespace L5Sharp.Core;
/// See <a href="https://literature.rockwellautomation.com/idc/groups/literature/documents/rm/1756-rm084_-en-p.pdf">
/// `Logix 5000 Controllers Import/Export`</a> for more information.
/// </footer>
[PublicAPI]
public class Program : LogixComponent
{
/// <summary>
Expand Down
2 changes: 2 additions & 0 deletions src/L5Sharp.Core/Components/Routine.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Xml.Linq;
using JetBrains.Annotations;

namespace L5Sharp.Core;

Expand All @@ -11,6 +12,7 @@ namespace L5Sharp.Core;
/// See <a href="https://literature.rockwellautomation.com/idc/groups/literature/documents/rm/1756-rm084_-en-p.pdf">
/// `Logix 5000 Controllers Import/Export`</a> for more information.
/// </footer>
[PublicAPI]
public class Routine : LogixComponent
{
/// <summary>
Expand Down
8 changes: 5 additions & 3 deletions src/L5Sharp.Core/Components/Tag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using JetBrains.Annotations;

namespace L5Sharp.Core;

Expand All @@ -12,6 +13,7 @@ namespace L5Sharp.Core;
/// See <a href="https://literature.rockwellautomation.com/idc/groups/literature/documents/rm/1756-rm084_-en-p.pdf">
/// `Logix 5000 Controllers Import/Export`</a> for more information.
/// </footer>
[PublicAPI]
[L5XType(L5XName.Tag)]
[L5XType(L5XName.LocalTag)]
[L5XType(L5XName.ConfigTag)]
Expand Down Expand Up @@ -384,7 +386,7 @@ public void Add(string name, LogixType value)
/// </remarks>
public IEnumerable<Tag> Members()
{
var members = Parent is null ? new List<Tag> {this} : new List<Tag>();
var members = Parent is null ? [this] : new List<Tag>();

foreach (var member in Value.Members)
{
Expand All @@ -409,7 +411,7 @@ public IEnumerable<Tag> Members(Predicate<TagName> predicate)
{
if (predicate is null) throw new ArgumentNullException(nameof(predicate));

var members = Parent is null && predicate.Invoke(TagName) ? new List<Tag> {this} : new List<Tag>();
var members = Parent is null && predicate.Invoke(TagName) ? [this] : new List<Tag>();

foreach (var member in Value.Members)
{
Expand Down Expand Up @@ -437,7 +439,7 @@ public IEnumerable<Tag> Members(Predicate<Tag> predicate)
{
if (predicate is null) throw new ArgumentNullException(nameof(predicate));

var members = Parent is null && predicate.Invoke(this) ? new List<Tag> {this} : new List<Tag>();
var members = Parent is null && predicate.Invoke(this) ? [this] : new List<Tag>();

foreach (var member in Value.Members)
{
Expand Down
18 changes: 9 additions & 9 deletions src/L5Sharp.Core/L5Sharp.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
<Title>L5Sharp</Title>
<Authors>Timothy Nunnink</Authors>
<Version>0.19.1</Version>
<AssemblyVersion>0.19.1</AssemblyVersion>
<FileVersion>0.19.1.0</FileVersion>
<Version>0.19.2</Version>
<AssemblyVersion>0.19.3</AssemblyVersion>
<FileVersion>0.19.3.0</FileVersion>
<Description>A library for intuitively interacting with Rockwell's L5X import/export files.</Description>
<RepositoryUrl>https://github.com/tnunnink/L5Sharp</RepositoryUrl>
<PackageTags>csharp allen-bradely l5x logix plc-programming rockwell-automation logix5000</PackageTags>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<!--<PackageIcon>icon.png</PackageIcon>-->
<RepositoryType>git</RepositoryType>
<PackageReleaseNotes>Upgraded to .NET7. Reworked LogixParser.cs. Added new ILogixParsable.cs. Fixed tests and documentation.</PackageReleaseNotes>
<PackageReleaseNotes>Added some equivalency methods to the LogixElement.cs and LogixType.cs to allow checks against entire XML structure..</PackageReleaseNotes>
<Copyright>Copyright (c) Timothy Nunnink 2022</Copyright>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageId>L5Sharp</PackageId>
Expand All @@ -27,16 +27,16 @@
</PropertyGroup>

<ItemGroup>
<None Include="..\..\README.md" Pack="true" PackagePath="\" />
<None Remove="L5Sharp.csproj.DotSettings" />
<None Remove="L5Sharp.Core.csproj.DotSettings" />
<None Include="..\..\README.md" Pack="true" PackagePath="\"/>
<None Remove="L5Sharp.csproj.DotSettings"/>
<None Remove="L5Sharp.Core.csproj.DotSettings"/>
</ItemGroup>

<ItemGroup>
<None Remove="L5Sharp.sln.DotSettings" />
<None Remove="L5Sharp.sln.DotSettings"/>
</ItemGroup>

<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2023.2.0" />
<PackageReference Include="JetBrains.Annotations" Version="2023.2.0"/>
</ItemGroup>
</Project>
16 changes: 16 additions & 0 deletions src/L5Sharp.Core/LogixElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,22 @@ public void Replace(LogixElement element)
/// </remarks>
public virtual XElement Serialize() => Element;

/// <summary>
/// Determines if the provided <see cref="LogixElement"/> is equivalent to this element in terms of both type and
/// state, including all child elements and values.
/// </summary>
/// <param name="other">The <see cref="LogixElement"/> to compare.</param>
/// <returns><c>ture</c> if the elements are equivalent; Otherwise, <c>false</c>.</returns>
/// <remarks>
/// This internally compares the underlying XML nodes of the two elements to determine if all their
/// elements, attributes, and values are equal. This includes all nested or descendant elements (i.e. it
/// compares the entire XML structure).
/// </remarks>
public bool IsEquivalent(LogixElement other)
{
return XNode.DeepEquals(Element, other.Element);
}

/// <summary>
/// Gets the value of the specified attribute name from the element parsed as the specified generic type parameter if it exists.
/// If the attribute does not exist, returns <c>default</c> value of the generic type parameter.
Expand Down
4 changes: 0 additions & 4 deletions src/L5Sharp.Core/LogixParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,6 @@ private static IEnumerable<KeyValuePair<Type, Parsers>> GetParsers()

foreach (var type in types)
{
if (!type.IsPublic)
{
Console.WriteLine(type.Name);
}
var parse = BuildParseFunction(type);
var tryParse = BuildTryParseFunction(type);
var parsers = new Parsers(parse, tryParse);
Expand Down
24 changes: 20 additions & 4 deletions src/L5Sharp.Core/LogixType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,22 @@ public override bool Equals(object? obj)

/// <inheritdoc />
public override int GetHashCode() => Name.GetHashCode();

/// <summary>
/// Determines if the provided <see cref="LogixType"/> is equivalent to this type in terms of the underlying XML
/// data that comprise the complex object.
/// </summary>
/// <param name="other">The <see cref="LogixType"/> to compare.</param>
/// <returns><c>ture</c> if the types are equivalent; Otherwise, <c>false</c>.</returns>
/// <remarks>
/// This internally compares the underlying XML nodes of the two types to determine if all their
/// elements, attributes, and values are equal. This includes all nested or descendant elements (i.e. it
/// compares the entire XML structure).
/// </remarks>
public bool IsEquivalent(LogixType other)
{
return XNode.DeepEquals(Serialize(), other.Serialize());
}

/// <summary>
/// Gets a <see cref="LogixMember"/> with the specified name if it exists for the <see cref="LogixType"/>;
Expand Down Expand Up @@ -284,7 +300,7 @@ public override bool Equals(object? obj)
/// </summary>
/// <param name="value">The value to convert.</param>
/// <returns>A <see cref="LogixType"/> representing the converted value.</returns>
public static implicit operator LogixType(LogixType[,] value) =>ToArrayType(value);
public static implicit operator LogixType(LogixType[,] value) => ToArrayType(value);

/// <summary>
/// Converts the provided <see cref="Array"/> to a <see cref="LogixType"/>.
Expand All @@ -300,7 +316,7 @@ public override bool Equals(object? obj)
/// <returns>A <see cref="LogixType"/> representing the converted value.</returns>
public static implicit operator LogixType(Dictionary<string, LogixType> value) =>
new ComplexType(nameof(ComplexType), value.Select(m => new LogixMember(m.Key, m.Value)));

/// <summary>
/// Converts the current array object to a <see cref="ArrayType{TLogixType}"/> of the concrete logix type by
/// inspecting the first element's type in the array.
Expand All @@ -321,7 +337,7 @@ private static ArrayType ToArrayType(Array array)
var type = array.Cast<LogixType>().First().GetType();
var arrayType = typeof(ArrayType<>).MakeGenericType(type);
var parameterType = typeof(Array);
var constructor = arrayType.GetConstructor(new[] { parameterType })!;
var constructor = arrayType.GetConstructor([parameterType])!;
var parameter = Expression.Parameter(parameterType, "array");
var creator = Expression.New(constructor, parameter);
var lambda = Expression.Lambda<Func<Array, ArrayType>>(creator, parameter);
Expand Down Expand Up @@ -360,4 +376,4 @@ public static ArrayType<TLogixType> ToArrayType<TLogixType>(this IEnumerable<TLo
var func = lambda.Compile();
return func.Invoke(array.ToArray());
}
}
}
22 changes: 22 additions & 0 deletions tests/L5Sharp.Tests/Elements/RungTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,26 @@ public void New_Default_ShouldHaveDefaultValues()
rung.Comment.Should().BeNull();
rung.Text.Should().Be(NeutralText.Empty);
}

[Test]
public void IsEquivalent_AreEqual_ShouldBeTrue()
{
var first = new Rung("XIC(SomeTag)OTE(AnotherTag);");
var second = new Rung("XIC(SomeTag)OTE(AnotherTag);");

var result = first.IsEquivalent(second);

result.Should().BeTrue();
}

[Test]
public void IsEquivalent_AreNotEqual_ShouldBeFalse()
{
var first = new Rung("XIC(SomeTag)OTL(AnotherTag);");
var second = new Rung("XIC(SomeTag)OTE(AnotherTag);");

var result = first.IsEquivalent(second);

result.Should().BeFalse();
}
}
Loading

0 comments on commit 95b3ec4

Please sign in to comment.