/**
*
*/
package com.ewjordan.util.objectWrap;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class PrivateMemberClass { // Do not edit!
private boolean var;
}
/**
* TODO
*/
public class PrimitiveReference {
static private boolean garbage = false; //only used to avoid dead code pruning in JVM
ReferenceType type;
Field field;
Object object;
private double minValue = -Double.MAX_VALUE;
private double maxValue = Double.MAX_VALUE;
private double standardDeviationScale = 1.0;
/**
* Gets all available primitive references out of an object, after first checking
* whether or not private access is allowed through the SecurityManager.
*
* Note that this will fail to grab Object references unless the objects
* define getAllReferences(boolean getPrivateRefs) methods that return
* PrimitiveReference[]. This method is grabbed via reflection, so no
* interface needs to be declared.
* @param o
* @return
*/
public static PrimitiveReference[] getAllReferencesFrom(Object o) {
PrivateMemberClass obj = new PrivateMemberClass();
Class<?> klazz = obj.getClass();
Field[] fields = klazz.getDeclaredFields();
for (int i=0; i<fields.length; ++i) {
try { // Can we access private fields through reflection?
fields[i].setAccessible(true);
//set garbage var to avoid pruning of unused statement
//TODO: see if JVM ever actually prunes unused code that might throw an exception...
//might be prohibited by JLS
garbage = fields[i].getBoolean(obj);
} catch (SecurityException e) { // If not, scrape the class for non-private references
return getAllReferencesFrom(o,false);
} catch (Exception e) {
throw new RuntimeException(e); //some other problem came up...
}
}
// We're all good - security policy lets us access private members thru reflection
return getAllReferencesFrom(o, true);
}
private static void logPrint(String msg) { ; }
private static void logPrintln(String msg) { ; }
public static PrimitiveReference[] getAllReferencesFrom(Object o, boolean getPrivateReferences) {
Class<?> klazz = o.getClass();
Field[] fields = klazz.getDeclaredFields();
List<PrimitiveReference> references = new ArrayList<PrimitiveReference>();
for (Field f:fields) {
f.setAccessible(true);
if (Modifier.isPublic(f.getModifiers())) {
logPrint("public ");
} else if (Modifier.isProtected(f.getModifiers())) {
logPrint("protected ");
} else if (Modifier.isPrivate(f.getModifiers())) {
logPrint("private ");
}
if (f.getAnnotation(Unwrapped.class) != null) {
logPrint(" variable "+f.getName()+" not wrapped (annotated with @Unwrapped).");
continue;
}
//System.out.println(f.getAnnotation(Unwrapped.class));
double minValue = -Double.MAX_VALUE;
double maxValue = Double.MAX_VALUE;
double stdDev = 1.0;
if (f.getAnnotation(MutationInfo.class) != null) {
MutationInfo r = f.getAnnotation(MutationInfo.class);
minValue = r.minimum();
maxValue = r.maximum();
stdDev = r.standardDeviation();
}
Class<?> fieldClass = f.getType();
if (fieldClass.isPrimitive()) {
if (fieldClass.equals(boolean.class)) {
logPrintln("boolean");
references.add(new PrimitiveReference(ReferenceType.BOOLEAN,o,f, minValue, maxValue, stdDev));
} else if (fieldClass.equals(int.class)) {
logPrintln("int");
references.add(new PrimitiveReference(ReferenceType.INT,o,f, minValue, maxValue, stdDev));
} else if (fieldClass.equals(float.class)) {
logPrintln("float");
references.add(new PrimitiveReference(ReferenceType.FLOAT,o,f, minValue, maxValue, stdDev));
} else if (fieldClass.equals(double.class)) {
logPrintln("double");
references.add(new PrimitiveReference(ReferenceType.DOUBLE,o,f, minValue, maxValue, stdDev));
} else if (fieldClass.equals(long.class)) {
logPrintln("long");
references.add(new PrimitiveReference(ReferenceType.LONG,o,f, minValue, maxValue, stdDev));
}
} else if (fieldClass.isArray()) {
try {
if (fieldClass.equals(boolean[].class)) {
logPrintln("boolean array");
boolean[] arr = (boolean[])f.get(o);
if (arr != null) {
for (int i=0; i<arr.length; ++i) {
references.add(new PrimitiveReferenceIntoArray(ReferenceType.BOOLEAN,o,f,i, minValue, maxValue, stdDev));
}
}
} else if (fieldClass.equals(int[].class)) {
logPrintln("int array");
int[] arr = (int[])f.get(o);
if (arr != null) {
for (int i=0; i<arr.length; ++i) {
references.add(new PrimitiveReferenceIntoArray(ReferenceType.INT,o,f,i, minValue, maxValue, stdDev));
}
}
} else if (fieldClass.equals(float[].class)) {
logPrintln("float array");
float[] arr = (float[])f.get(o);
if (arr != null) {
for (int i=0; i<arr.length; ++i) {
references.add(new PrimitiveReferenceIntoArray(ReferenceType.FLOAT,o,f,i, minValue, maxValue, stdDev));
}
}
} else if (fieldClass.equals(double[].class)) {
logPrintln("double array");
double[] arr = (double[])f.get(o);
if (arr != null) {
for (int i=0; i<arr.length; ++i) {
references.add(new PrimitiveReferenceIntoArray(ReferenceType.DOUBLE,o,f,i, minValue, maxValue, stdDev));
}
}
} else if (fieldClass.equals(long[].class)) {
logPrintln("long array");
long[] arr = (long[])f.get(o);
if (arr != null) {
for (int i=0; i<arr.length; ++i) {
references.add(new PrimitiveReferenceIntoArray(ReferenceType.LONG,o,f,i, minValue, maxValue, stdDev));
}
}
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} else {
try {
Method m = fieldClass.getMethod("getAllReferences", boolean.class);
if (m != null) {
PrimitiveReference[] addRefs = (PrimitiveReference[])m.invoke(o, getPrivateReferences);
Collections.addAll(references, addRefs);
} else {
logPrintln("object of type " + o.getClass().getCanonicalName() + " (skipped)");
}
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
logPrintln("object of type " + o.getClass().getCanonicalName() + " (skipped)");
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
return references.toArray(new PrimitiveReference[references.size()]);
}
public PrimitiveReference(PrimitiveReference copyMe) {
this.type = copyMe.type;
this.field = copyMe.field;
this.object = copyMe.object;
this.setMinValue(copyMe.getMinValue());
this.setMaxValue(copyMe.getMaxValue());
this.setStandardDeviationScale(copyMe.getStandardDeviationScale());
}
public PrimitiveReference clone() {
return new PrimitiveReference(this);
}
public PrimitiveReference(ReferenceType type, Object object, Field field, double minValue, double maxValue, double standardDeviationScale) {
this.type = type;
this.object = object;
this.field = field;
this.setMinValue(minValue);
this.setMaxValue(maxValue);
this.setStandardDeviationScale(standardDeviationScale);
}
public String toString() {
String result = "" + type + " field " + getFieldName() + " in " + getObjectTypeName();
return result;
}
public String getFieldName() {
return field.getName();
}
public String getObjectTypeName() {
return object.getClass().getCanonicalName();
}
public void set(float newValue) throws IllegalArgumentException, IllegalAccessException {
field.setFloat(object, newValue);
}
public void set(double newValue) throws IllegalArgumentException, IllegalAccessException {
field.setDouble(object, newValue);
}
public void set(int newValue) throws IllegalArgumentException, IllegalAccessException {
field.setInt(object, newValue);
}
public void set(long newValue) throws IllegalArgumentException, IllegalAccessException {
field.setLong(object, newValue);
}
public void set(boolean newValue) throws IllegalArgumentException, IllegalAccessException {
field.setBoolean(object, newValue);
}
public float getFloat() throws IllegalArgumentException, IllegalAccessException {
return field.getFloat(object);
}
public double getDouble() throws IllegalArgumentException, IllegalAccessException {
return field.getDouble(object);
}
public int getInt() throws IllegalArgumentException, IllegalAccessException {
return field.getInt(object);
}
public long getLong() throws IllegalArgumentException, IllegalAccessException {
return field.getLong(object);
}
public boolean getBoolean() throws IllegalArgumentException, IllegalAccessException {
return field.getBoolean(object);
}
public ReferenceType getType() {
return type;
}
public boolean isArrayMember() {
return false;
}
void setMinValue(double minValue) {
this.minValue = minValue;
}
double getMinValue() {
return minValue;
}
void setMaxValue(double maxValue) {
this.maxValue = maxValue;
}
double getMaxValue() {
return maxValue;
}
void setStandardDeviationScale(double standardDeviationScale) {
this.standardDeviationScale = standardDeviationScale;
}
double getStandardDeviationScale() {
return standardDeviationScale;
}
}