Your question is not very clearly written and I believe that's why you are not getting the answer you expect but, If I understood your question correctly, you need to parse the following input string at runtime that you don't know beforehand:
myMap.friends[0]
And this should be parsed into components like:
- mapName = "myMap"
- mapKey = "friends"
- valueIndex = 0
And with this information, you need to manipulate data in a Map at runtime through reflection.
Note: This only makes sense if you could potentially have more complex expressions, using different sort of objects and accessing nested properties of retrieved objects, otherwise you wouldn't need reflection at all.
Note 2: You may want to have a look at JXPath which already does a lot of this for you based on a XPath-like syntax for navigating object graphs.
That said, if my assumptions are correct and you still want to do it yourself, consider the following example.
For the sake of demonstration, let's consider our map is returned by a method myMap inside a Context.
private static class Context {
public Map<String, Object> myMap() {
Map<String, Object> myMap = new HashMap<>();
List<String> friends = new ArrayList<>();
friends.add("Foo");
friends.add("Bar");
myMap.put("name", "Blah");
myMap.put("friends", friends);
return myMap;
}
}
I'm assuming you are already parsing the input string into the different components. If not, for this simple string you could do it with simple regular expressions. If you already have the components, let's consider the following method:
public static Object readContextMap(Context context,
String mapName, String mapKey, Integer mapValueIndex) throws Exception {
// gets Context class for inspection
Class<?> cls = context.getClass();
// search for a method based on supplied mapName
Method mapMethod = cls.getDeclaredMethod(mapName);
// get a value from the retrieved map based on mapKey
Object mapValue = mapMethod.getReturnType()
.getDeclaredMethod("get", Object.class)
.invoke(mapMethod.invoke(context), mapKey);
// if the result is of type list, use the index to return the indexed element
if (List.class.isAssignableFrom(mapValue.getClass())) {
return ((List<?>)mapValue).get(mapValueIndex);
}
// otherwise return the object itself
return mapValue;
}
For testing purposes, consider the following main method:
public static void main(String[] args) throws Exception {
Context context = new Context();
String input = "myMap.friends[0]";
// parse input into...
String mapName = "myMap";
String mapKey = "friends";
Integer valueIndex = 0;
Object firstFriend = readContextMap(context, mapName, mapKey, valueIndex);
System.out.println(firstFriend);
// prints Foo
Object name = readContextMap(context, "myMap", "name", null);
System.out.println(name);
// prints Blah
}
This should be approximately what you want. You can easily create variations of this to set values as well. Please bear in mind that this code is just for demo purposes and needs a better error handling (e.g. verify if the context is really returning a map and nothing else).
This should be something along the lines you are looking for.