Search code examples
javareflectioncomparecomparisonchain-of-responsibility

Two instances of an object with nested objects compare with dynamic (options/rules/args)


How to differ/compare two instances of an object with nested objects and more IMPORTANTLY with dynamic compare (options/rules).

So basically I don't know what of the object attributes I need to compare. The options/rules vary and are added dynamically by a user through some UI. Of course one could easily create a lot of methods with a lot of if statements. This is not what I'm looking for I have many different objects that needs this functionality.

I've thought of using Reflection, but how would this do with many nested objects? Like obj A has obj B. Obj B has a List of obj C and each of C has obj E?? That would make reflection pretty complicated right?

I've also thought of Chain of Respoibllity, but still a solution is not quite clear to me..

Example

Say I have an object A. This object contains some standard data types: int, bool etc. Also it has the object B which then have some standard data types as well. I now have 2 instances of A which I need to compare. But not just a simple compare of all attributes (CompareTo). Only what the user or some rules (preferably some strings) says that needs to be compared. How do I proceed???

public class A {
    int number;
    boolean bool;
    C other;
    List<B> list;

    public A (..... some args){ ... }

    void dynamicCompare(A otherObj, String [] rules ){
        // compare using args
    }
}

public class B {
    int number;
    boolean bool;
    D other;

    public B (..... some args){ ... }
}

Solution

  • I don't think that the chain of responsibility will help you here.
    This pattern makes sense as you have some requests to handle but you don't know or will not know which object will actually addresses it.
    To achieve it, you define a chain of objects, with a specific order, where each one may address the request or leave it to the next element of the chain.
    In our case, I don't identify any chain or order in the processing.

    For your requirement, I imagine two ways.

    1) Real dynamic solution for application users : introduce your own query language or use a query language library such as GraphQL.

    The idea behind is providing to application users a request language that may rely on JSON or any formalism and from the back end side, your application parses user queries to handle it and uses reflection to identify the nature of the object and compare it with instances of the same type.

    2) Less dynamic solution and requires more code but doesn't require a query language and is more robust as checked at compile time.
    Introduce a query class for each type of object that users may pass as request.

    For example :

    public class QueryForObjectA{
    
           private String fieldOne;
           private Integer fieldTwo;           
           private QueryForObjectB queryForObjectB;     
           ..
    
    }
    

    And inside this class (or outside) introduce a processing method to match the user query with some objectsA :

     ...
     public void List<ObjectA> match(List<ObjectA> objectsA){
    
           List<ObjectA> matched = new ArrayList<>();
    
           for (List<ObjectA> current : objectsA){
    
             if (fieldOne != null && !fieldOne.equals(current.fieldOne)){
                    continue;                    
             }
             ...
             matched.add(current);
           }
     }