Mapping read attributes to an existing model via Java Reflection API
Wednesday, June 30th, 2010Here´s a way, how to map read Key / Value Pairs to a Model with the Java Reflection API.
First of all, let´s say you have a reader (e.g. a BufferedReader) which reads Key/Value Pairs. So you´ll get from one Line of the Reader something like this:
name=fred surname=fart
Now you have a modell, which provides all the keys as attributes.
public class Person {
private String name;
private String surname;
...
setName(String newName) {
this.name = newName;
}
setSurname(String newName) {
this.name = newName;
}
...
}
now we´ll get to the reading routine
public class xxx {
...
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
...
//this method reads the information e.g. with the help of an bufferedReader
public Person readPersonInformation(PersonInformationObject pio) {
...
Person newPerson = new Person();
while ((line = reader.readLine()) != null) {
parseReadPersonAttributes(newPerson, line);
}
...
return newPerson;
}
/**this method parses the read information
* @newPerson the object, where the new value is beeing invoked on
* @codedInformation the read key-value line
**/
private void parseReadPersonAttributes(Person newPerson, String codedInformation) {
String information = codedInformation;
//if there is noch equal symbol, than isnt able to be interpreted
if (information.contains("=")) {
String interpretedInformation[] = new String[2];
interpretedInformation = information.split("=");
if (interpretedInformation.length > 1) {
//now for the Reflaction API
Method personMethods[] = Person.class.getMethods();
for (Method method : personMethods) {
//find the setter Method for the Attribute
if (method.getName().equalsIgnoreCase("set" + interpretedInformation[0])) {
try {
//now that a Method is found, try to invoke the method with the read Information
method.invoke(newPerson, interpretedInformation[1]);
} catch (Exception ex) {
//errorhandling
}
}
}
}
}
}
}
The code searchs for a fitting setter Method in the Person Modell. If he finds a appropriate Method, its invoking this method on the given Person Object, in order to set the read Information
Note that if there are more keys read than there are attributes in the modell, you just have to add those attributes to the modell. I think that this is a good way, to map read information to a modell
July 4th, 2010 at 09:19
Nice post. I just finished implementing the same thing for parsing a large amount of data that comes in a format like key1=val1,…,key20=val20
The problem is that I also get data updates where I have input lines containing only a few key/value pairs.
I kinda knew that reflection could help me here, but I’ve never used reflection before, so I didn’t do now. However your example has shown me how easy it is. One problem I see here, though, is that all setters must have the same signature, that is, setter( String), so either you overload the setters that don’t take String, or find other solution. I did it the expected way: populate a map with the input and then try to retrieve the keys, setting the ones that don’t return null.
I like the reflection solution because, as you mention, the model can be extended/reduced without needing to modify the data writer nor the parser. The only concern I’d have is how much a performance hit will take the parsing by using reflection. I will test it when I find the time.
Thanks.
[Reply]