Skip to content

Diffing_Engine: IsEqual method added #3338

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

Merged
merged 3 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion Diffing_Engine/Compute/DiffOneByOne.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public static Diff DiffOneByOne(IEnumerable<object> pastObjects, IEnumerable<obj
{
ObjectDifferences objectDifferences = Query.ObjectDifferences(pastObjects_cloned[i], currentObjects_cloned[i], diffConfigCopy.ComparisonConfig);

if (objectDifferences != null && (objectDifferences.Differences?.Any() ?? false))
if (objectDifferences.Differences?.Any() ?? false)
{
modifiedObjects.Add(currentObjects_cloned[i]);
anyChangeDetected = true;
Expand Down
2 changes: 1 addition & 1 deletion Diffing_Engine/Compute/DiffRevisions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ private static Diff DiffRevisionObjects(IEnumerable<IBHoMObject> pastObjects, IE
// To compute differentProps in a Revision-Diffing, make sure we remove the RevisionFragment. We don't want to consider that.
ObjectDifferences objectDifferences = Query.ObjectDifferences(oldBhomObj.RemoveFragment(typeof(RevisionFragment)), bhomObj.RemoveFragment(typeof(RevisionFragment)), dc.ComparisonConfig);

if (objectDifferences != null)
if (objectDifferences.Differences.Any())
modifiedObjectDifferences.Add(objectDifferences);
}
}
Expand Down
6 changes: 3 additions & 3 deletions Diffing_Engine/Compute/DiffWithCustomIds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,14 +167,14 @@ private static Diff Diffing(IEnumerable<object> pastObjects, IEnumerable<string>
{
List<IPropertyDifference> customObjectDifferences = customComparer.Invoke(correspondingPastObj, followingObj, diffingConfig.ComparisonConfig);

if (objectDifferences == null)
objectDifferences = new ObjectDifferences() { PastObject = correspondingPastObj, FollowingObject = followingObj };
//if (objectDifferences == null)
// objectDifferences = new ObjectDifferences() { PastObject = correspondingPastObj, FollowingObject = followingObj };

objectDifferences.Differences.AddRange(customObjectDifferences);
}
}

if (objectDifferences != null && (objectDifferences.Differences?.Any() ?? false))
if (objectDifferences.Differences?.Any() ?? false)
{
// It's been modified
modifiedObjs.Add(followingObj);
Expand Down
2 changes: 1 addition & 1 deletion Diffing_Engine/Query/DifferentProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public static Dictionary<string, Tuple<object,object>> DifferentProperties(this
ObjectDifferences objectDifferences = Query.ObjectDifferences(obj1, obj2, comparisonConfig);

if (objectDifferences == null)
return null;
return new Dictionary<string, Tuple<object, object>>();

// Group the `ObjectDifferences` in a Dictionary.
Dictionary<string, Tuple<object, object>> result = objectDifferences.Differences.GroupBy(d => d.FullName)
Expand Down
54 changes: 54 additions & 0 deletions Diffing_Engine/Query/IsEqual.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* This file is part of the Buildings and Habitats object Model (BHoM)
* Copyright (c) 2015 - 2024, the respective contributors. All rights reserved.
*
* Each contributor holds copyright over their respective contributions.
* The project versioning (Git) records all such contribution source information.
*
*
* The BHoM is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3.0 of the License, or
* (at your option) any later version.
*
* The BHoM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
*/

using BH.oM.Base;
using BH.oM.Base.Attributes;
using System.ComponentModel;
using System.Linq;

namespace BH.Engine.Diffing
{
public static partial class Query
{
/***************************************************/
/**** Public Methods ****/
/***************************************************/

[Description("Checks whether the two objects are the same within the scope defined by the ComparisonConfig.")]
[Input("obj1", "First object to check for equality.")]
[Input("obj2", "Second object to check for equality.")]
[Input("comparisonConfig", "Comparison configuration to be used for the comparison.")]
[Output("equal", "True if the two objects are the same within the scope defined by the provided ComparisonConfig, otherwise false.")]
public static bool IsEqual(this object obj1, object obj2, BaseComparisonConfig comparisonConfig = null)
{
if (obj1 == null || obj2 == null)
return obj1 == obj2;

if (obj1.GetType() != obj2.GetType())
return false;

return !obj1.Differences(obj2, comparisonConfig).Any();
}

/***************************************************/
}
}
89 changes: 49 additions & 40 deletions Diffing_Engine/Query/ObjectDifferences.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,16 @@
* along with this code. If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
*/

using BH.Engine.Base;
using BH.oM.Base;
using BH.oM.Base.Attributes;
using BH.oM.Diffing;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using BH.oM.Base.Attributes;
using BH.oM.Diffing;
using BH.oM.Base;
using System.Linq;
using kellerman = KellermanSoftware.CompareNetObjects;
using System.Reflection;
using BH.Engine.Base;
using BH.Engine.Reflection;
using System.Collections;

namespace BH.Engine.Diffing
{
Expand All @@ -51,13 +47,28 @@ public static partial class Query
"\nIf no difference was found, returns null.")]
public static ObjectDifferences ObjectDifferences(this object pastObject, object followingObject, BaseComparisonConfig comparisonConfig = null)
{
// Result object.
ObjectDifferences result = new ObjectDifferences() { PastObject = pastObject, FollowingObject = followingObject };

// Null check. At least one of the objects must be not null.
if (pastObject == null && followingObject == null)
return result;

result.Differences.AddRange(pastObject.Differences(followingObject, comparisonConfig));
return result;
}


/***************************************************/
/**** Private Methods ****/
/***************************************************/

[Description("Finds the actual differences between the objects.")]
private static IEnumerable<PropertyDifference> Differences(this object pastObject, object followingObject, BaseComparisonConfig comparisonConfig = null)
{
// Result object.
List<PropertyDifference> returned = new List<PropertyDifference>();
PropertyDifference toReturn;

// Set ComparisonConfig if null. Clone it for immutability in the UI.
BaseComparisonConfig cc = comparisonConfig == null ? new ComparisonConfig() : comparisonConfig.DeepClone();

Expand Down Expand Up @@ -122,8 +133,12 @@ public static ObjectDifferences ObjectDifferences(this object pastObject, object
{
ComparisonInclusion comparisonInclusion = comparisonInclusionFromExtensionMethod as ComparisonInclusion;
if (comparisonInclusion != null && comparisonInclusion.Include)
{
// Add to the final result.
result.AddPropertyDifference(comparisonInclusion.DisplayName, kellermanPropertyDifference.Object1, kellermanPropertyDifference.Object2, propertyFullName);
toReturn = PropertyDifference(pastObject, followingObject, comparisonInclusion.DisplayName, kellermanPropertyDifference.Object1, kellermanPropertyDifference.Object2, propertyFullName);
returned.Add(toReturn);
yield return toReturn;
}

// Because a `ComparisonInclusion()` extension method was found, we've already determined if this difference was to be considered or not. Continue.
continue;
Expand All @@ -142,7 +157,7 @@ public static ObjectDifferences ObjectDifferences(this object pastObject, object
propertyFullName = propertyFullName.Replace(".Value", "");

// Workaround for Kellerman duplicating the CustomData differences.
if (result.Differences.Any(d => d.FullName == propertyFullName))
if (returned.Any(d => d.FullName == propertyFullName))
continue;

// Check if we are talking about CustomObjects.
Expand Down Expand Up @@ -185,40 +200,37 @@ public static ObjectDifferences ObjectDifferences(this object pastObject, object
continue;

// Add to the final result.
result.AddPropertyDifference(propertyDisplayName, kellermanPropertyDifference.Object1, kellermanPropertyDifference.Object2, propertyFullName);
toReturn = PropertyDifference(pastObject, followingObject, propertyDisplayName, kellermanPropertyDifference.Object1, kellermanPropertyDifference.Object2, propertyFullName);
returned.Add(toReturn);
yield return toReturn;
}

if (result.Differences.Count == 0)
return null;

return result;
}

/***************************************************/
/**** Private Methods ****/
/***************************************************/

[Description("Removes square bracket indexing from property paths, e.g. `Bar.Fragments[0].Something` is returned as `Bar.Fragments.Something`.")]
private static void AddPropertyDifference(this ObjectDifferences objectDifferences, string propertyDiffDisplayName, object pastValue, object follValue, string fullName, string description = null)
private static PropertyDifference PropertyDifference(this object pastObject, object followingObject, string propertyDiffDisplayName, object pastValue, object follValue, string fullName, string description = null)
{
description = string.IsNullOrWhiteSpace(description) ?
PropertyDifferenceDescription(objectDifferences, propertyDiffDisplayName, pastValue, follValue)
PropertyDifferenceDescription(pastObject, followingObject, propertyDiffDisplayName, pastValue, follValue)
: description;

objectDifferences.Differences.Add(new PropertyDifference()
return new PropertyDifference()
{
Name = propertyDiffDisplayName,
Description = description,
PastValue = pastValue,
FollowingValue = follValue,
FullName = fullName
}); ;
};
}

private static string PropertyDifferenceDescription(ObjectDifferences objectDifferences, string propertyDiffDisplayName, object pastValue, object follValue, bool includeObjName = true, bool includeObjType = false, bool includeObjGuid = false)
/***************************************************/

private static string PropertyDifferenceDescription(this object pastObject, object followingObject, string propertyDiffDisplayName, object pastValue, object follValue, bool includeObjName = true, bool includeObjType = false, bool includeObjGuid = false)
{
if (pastValue is IEnumerable && follValue is IEnumerable)
return $"The collection stored in the property `{propertyDiffDisplayName}` of the `{objectDifferences.PastObject.GetType().FullName}` was modified.";
return $"The collection stored in the property `{propertyDiffDisplayName}` of the `{pastObject.GetType().FullName}` was modified.";

Type t = pastValue?.GetType() ?? follValue?.GetType() ?? typeof(object);

Expand All @@ -228,12 +240,12 @@ private static string PropertyDifferenceDescription(ObjectDifferences objectDiff
{
bool addedObjectDescription = false;

objectDescription = objectDifferences.PastObject is CustomObject ? "CustomObject " : "Object ";
objectDescription = pastObject is CustomObject ? "CustomObject " : "Object ";

if (includeObjName)
{
string pastObjName = (objectDifferences.PastObject as IBHoMObject)?.Name;
string follObjName = (objectDifferences.FollowingObject as IBHoMObject)?.Name;
string pastObjName = (pastObject as IBHoMObject)?.Name;
string follObjName = (followingObject as IBHoMObject)?.Name;

if (!string.IsNullOrWhiteSpace(pastObjName) && pastObjName == follObjName)
{
Expand All @@ -242,16 +254,16 @@ private static string PropertyDifferenceDescription(ObjectDifferences objectDiff
}
}

if (includeObjType && !(objectDifferences.PastObject is CustomObject))
if (includeObjType && !(pastObject is CustomObject))
{
objectDescription += $"of type `{objectDifferences.PastObject.GetType().FullName}` ";
objectDescription += $"of type `{pastObject.GetType().FullName}` ";
addedObjectDescription = true;
}

if (includeObjGuid)
{
Guid? pastObjGuid = (objectDifferences.PastObject as IBHoMObject)?.BHoM_Guid;
Guid? follObjGuid = (objectDifferences.FollowingObject as IBHoMObject)?.BHoM_Guid;
Guid? pastObjGuid = (pastObject as IBHoMObject)?.BHoM_Guid;
Guid? follObjGuid = (followingObject as IBHoMObject)?.BHoM_Guid;

if (pastObjGuid != null && pastObjGuid == follObjGuid)
{
Expand Down Expand Up @@ -301,10 +313,7 @@ private static bool PropertyNameWildcardMatch(this string propertyName, string w

return propertyName.WildcardMatch(wildcardPattern);
}

/***************************************************/
}
}