0

I wanted to know how I can achieve the following:

Given in config file: key = "order.getItems().get(0).getId().getItemId()"

I want to invoke the above call in java code so if I am given this method signature:

public String getKey(String key) {

   // where key = "order.getItems().get(0).getId().getItemId()"
   // invoke the key and get the value
   String val = order.getItems().get(0).getId().getItemId();
}

Atihska
  • 4,803
  • 10
  • 56
  • 98
  • 1
    you need to use reflection. Also I think better to update your method to take 3 parameter. Such as - object, method, index, and fieldName. Check this post for reflection -- https://stackoverflow.com/questions/160970/how-do-i-invoke-a-java-method-when-given-the-method-name-as-a-string#:~:text=objectToInvokeOn%20is%20of%20type%20Object,be%20passed%20to%20the%20method – Aditya Jun 15 '21 at 02:19

2 Answers2

0

No, I don't think you can do this, but if you use new com.example.Order().getItems().get(0).getId().getItemId(), that might be possible.

Or use some reflect coding, the following might be possible.

    public String getKey(Order order, String key) {
    
       // where key = "getItems().get(0).getId().getItemId()"
       // do some reflect coding here

       String val = order.getItems().get(0).getId().getItemId();
    }
Keijack
  • 778
  • 6
  • 12
0

So I was able to create this with the link @Aditya mentioned and improvising based on my use case:

//Here key = "com.order.getItems().get(0).getId().getItemId()"
//instance = createOrder(); // instance with some values populated
public String getValue(String key, Object instance) {

        String[] valuePath = key.split("\\.");
        int serviceTypeIndex = 0;

        if (valuePath[serviceTypeIndex].equalsIgnoreCase("com")) {
            try {
     
                Class clz = Class.forName(dataConfig.getOrder()); // FQ class name passed as string so "com.example.abc.Order" in my case
                Object obj = getValueHelper(clz, instance, valuePath);
                if (obj != null) {
                    return obj.toString();
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    private Object getValueHelper(Class<?> clazz, Object instance, String[] valuePath) {
        int valuePathCounter = 2;
        while (valuePathCounter < valuePath.length) {
            try {
                if (!methodExists(clazz, valuePath[valuePathCounter])) {
                    return null;
                }
                Method m = clazz.getMethod(valuePath[valuePathCounter]);

                if (m.invoke(instance) == null) {
                    return null;
                }
                instance = m.invoke(instance);
                clazz = instance.getClass();
                valuePathCounter++;

            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                return null;
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
        return instance;
    }

    private boolean methodExists(Class<?> clazz, String method) {
        try {
            clazz.getMethod(method);
        } catch (NoSuchMethodException e) {
            return false;
        }
        return true;
    }

Atihska
  • 4,803
  • 10
  • 56
  • 98