76 lines
2.7 KiB
Java
76 lines
2.7 KiB
Java
package com.comphenix.protocol.utility;
|
|
|
|
import java.lang.reflect.Constructor;
|
|
import java.lang.reflect.Field;
|
|
import java.lang.reflect.InvocationTargetException;
|
|
|
|
/**
|
|
* This class can be used to reconstruct objects.
|
|
*
|
|
* Note that it is limited to classes where both the order and number of member variables matches the order and number
|
|
* of arguments for the first constructor. This means that this class is mostly useful for classes generated by lambdas.
|
|
*
|
|
* @param <T> The type of the object to reconstruct.
|
|
* @author Pim
|
|
*/
|
|
public class ObjectReconstructor<T> {
|
|
|
|
private final Class<T> clz;
|
|
private final Field[] fields;
|
|
private final Constructor<?> ctor;
|
|
|
|
public ObjectReconstructor(final Class<T> clz) {
|
|
this.clz = clz;
|
|
this.fields = clz.getDeclaredFields();
|
|
for (Field field : fields)
|
|
field.setAccessible(true);
|
|
this.ctor = clz.getDeclaredConstructors()[0];
|
|
this.ctor.setAccessible(true);
|
|
}
|
|
|
|
/**
|
|
* Gets the values of all member variables of the provided instance.
|
|
* @param instance The instance for which to get all the member variables.
|
|
* @return The values of the member variables from the instance.
|
|
*/
|
|
public Object[] getValues(final Object instance) {
|
|
final Object[] values = new Object[fields.length];
|
|
for (int idx = 0; idx < fields.length; ++idx)
|
|
try {
|
|
values[idx] = fields[idx].get(instance);
|
|
} catch (IllegalAccessException e) {
|
|
throw new RuntimeException("Failed to access field: " + fields[idx].getName() +
|
|
" for class: " + clz.getName(), e);
|
|
}
|
|
return values;
|
|
}
|
|
|
|
/**
|
|
* Gets the fields in the class.
|
|
* @return The fields.
|
|
*/
|
|
public Field[] getFields() {
|
|
return fields;
|
|
}
|
|
|
|
/**
|
|
* Creates a new instance of the class using the new values.
|
|
* @param values The new values for the member variables of the class.
|
|
* @return The new instance.
|
|
*/
|
|
public T reconstruct(final Object[] values) {
|
|
if (values.length != fields.length)
|
|
throw new RuntimeException("Mismatched number of arguments for class: " + clz.getName());
|
|
|
|
try {
|
|
return (T) ctor.newInstance(values);
|
|
} catch (InstantiationException e) {
|
|
throw new RuntimeException("Failed to reconstruct object of type: " + clz.getName(), e);
|
|
} catch (IllegalAccessException e) {
|
|
throw new RuntimeException("Failed to access constructor of type: " + clz.getName(), e);
|
|
} catch (InvocationTargetException e) {
|
|
throw new RuntimeException("Failed to invoke constructor of type: " + clz.getName(), e);
|
|
}
|
|
}
|
|
}
|