Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to diff two versions of same object?

I want to compare two objects of different versions and display their differences in UI.

First I call a method to know if there is any difference between the two objects

The method is:

public bool AreEqual(object object1,object object2, Type comparisionType)

If the above method returns true, I call the GetDifferences method to get the differences which is:

public ObjectDifference[] GetObjectDifferences(object object1, object object2, Type comparisionType)
{
  ArrayList memberList = new ArrayList();
  ArrayList differences = new ArrayList();

  memberList.AddRange(comparisionType.GetProperties());
  memberList.AddRange(comparisionType.GetFields());

  for (int loopCount = 0; loopCount < memberList.Count; loopCount++)
  {
    object objVal1 = null;
    object objVal2 = null;
    MemberInfo member = ((MemberInfo)memberList[loopCount]);
    switch (((MemberInfo)memberList[loopCount]).MemberType)
    {
      case MemberTypes.Field:
        objVal1 = object1 != null ? ((FieldInfo)memberList[loopCount]).GetValue(object1) : null;
        objVal2 = object2 != null ? ((FieldInfo)memberList[loopCount]).GetValue(object2) : null;
        break;
      case MemberTypes.Property:

        objVal1 = object1 != null ? ((PropertyInfo)memberList[loopCount]).GetValue(object1, null) : null;
        objVal2 = object2 != null ? ((PropertyInfo)memberList[loopCount]).GetValue(object2, null) : null;
        break;
      default:
        break;
    }

    if (AreValuesDifferentForNull(objVal1, objVal2))
    {
      ObjectDifference obj = new ObjectDifference(objVal1, objVal2, member, member.Name);
      differences.Add(obj);
    }
    else if (AreValuesDifferentForPrimitives(objVal1, objVal2))
    {
      ObjectDifference obj = new ObjectDifference(objVal1, objVal2, member, member.Name);
      differences.Add(obj);
    }
    else if (AreValuesDifferentForList(objVal1, objVal2))
    {
      ObjectDifference[] listDifference = GetListDifferences((ICollection)objVal1, (ICollection)objVal2, member);
      differences.AddRange(listDifference);
    }
    else if ((!AreValuesEqual(objVal1, objVal2)) && (objVal1 != null || objVal2 != null))
    {
      ObjectDifference obj = new ObjectDifference(objVal1, objVal2, member, member.Name);
      differences.Add(obj);
    }
  }
  return (ObjectDifference[])differences.ToArray(typeof(ObjectDifference));
}


public class ObjectDifference
{
  private readonly object objectValue1;
  private readonly object objectValue2;
  private readonly System.Reflection.MemberInfo member;
  private readonly string description;

  public object ObjectValue1
  {
    get { return objectValue1; }
  }
  public object ObjectValue2
  {
    get { return objectValue2; }
  }
  public System.Reflection.MemberInfo Member
  {
    get { return member; }
  }
  public string Description
  {
    get { return description; }
  }

  public ObjectDifference(object objVal1, object objVal2, System.Reflection.MemberInfo member, string description)
  {
    this.objectValue1 = objVal1;
    this.objectValue2 = objVal2;
    this.member = member;
    this.description = description;
  }
}

For each difference I create an object of type ObjectDifference and add it to the array. The highlighted portion is the one where I am stuck! If the object contains another complex object, My program does give me the differences but I dont know which type it belonged to

For example, I have two objects of type Name

class Name
{
  string firstName, LastName;
  List phNumber;
}

class PhoneNumber
{
  string officeNo, MobileNo, HomeNo;
}

while comparing two objects the output I get is plain -

  • firstname - John Mary
  • LastName - cooper Lor
  • officeNo - 22222 44444
  • MobileNo - 989898 089089
  • HomeNo - 4242 43535

The Hierarchy that officeNo is of type PhoneNumber is lost, which is important for me to display.

How should I maintain this type of tree while creating differences? Hope I am able to make my problem understood.

like image 384
ksa Avatar asked Mar 13 '09 08:03

ksa


People also ask

How do you compare two objects?

Whereas the equals() method compares two objects. Objects are equal when they have the same state (usually comparing variables). Objects are identical when they share the class identity. For example, the expression obj1==obj2 tests the identity, not equality.

Is there a Java library that can diff two objects?

java-object-diff is a simple, yet powerful library to find differences between Java objects. It takes two objects and generates a tree structure that represents any differences between the objects and their children.


1 Answers

What you are trying to do and display is inherently complex. I've done this in the past (for diffgram/delta-based processes), and even trying to display nested changes in a simple and friendly way is tricky.

If it fits your user-base, one option might be to simply serialize the two graphs as xml, and use something like xml diff.

like image 98
Marc Gravell Avatar answered Oct 23 '22 02:10

Marc Gravell