package configuration;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import util.InferenceUtil;
public class RoundDesign extends TaskDesign {
private static final RoundDesign defRnd = new RoundDesign();
/**
* Takes a RoundDesign and gives back a list of methods that it contains
* @param other
* @return
*/
protected List<Method> differenceBetween(RoundDesign other) {
final List<Method> li = difference();
return filter(other.difference(), new FilterMethod() {
@Override
public boolean keepMethod(RoundDesign dsg, Method meth) {
for (Method method : li) {
if (method == meth) {
return false;
}
}
return true;
}
});
}
/**
*Returns a map of which methods have changed from the default
*/
public List<Method> difference() {
List<Method> meths = getGetters();
meths = filter(meths, new FilterMethod() {
@Override
public boolean keepMethod(RoundDesign dsg, Method meth) {
try {
return !meth.invoke(dsg).equals(meth.invoke(defRnd));
} catch (Exception ex) {
return false;
}
}
});
return meths;
}
private List<Method> getGetters() {
Method[] meths = RoundDesign.class.getMethods();
List<Method> li = Arrays.asList(meths);
return filter(li, new FilterMethod() {
@Override
public boolean keepMethod(RoundDesign dsg, Method method) {
return !method.getName().equalsIgnoreCase("getBaseDesign") && (method.getName().startsWith(InferenceUtil.PRE_GETTER) && method.getParameterTypes().length == 0);
}
});
}
/**
* Takes a RoundDesign and applies properties to current RoundDesign that have not been set yet
* @param rnd2
*/
void merge(RoundDesign other) {
List<Method> toOverwrite = differenceBetween(other);
for (Method method : toOverwrite) {
try {
InferenceUtil.getterFromSetter(RoundDesign.class, method).invoke(this, method.invoke(other));
} catch (IllegalAccessException ex) {
Logger.getLogger(RoundDesign.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalArgumentException ex) {
Logger.getLogger(RoundDesign.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(RoundDesign.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
interface FilterMethod {
/**
* Simple function which decided whether a function should be kept or thrown away
* @param dsg, current rounddesign
* @param meth
* @return
*/
boolean keepMethod(RoundDesign dsg, Method meth);
}
/**
* Given a list of Methods and a Filterer, keep only those Methods that pass the keepMethod calling
* @param meths
* @param filterer
* @return
*/
private List<Method> filter(List<Method> meths, FilterMethod filterer) {
List<Method> filtered = new ArrayList<Method>();
for (Method method : meths) {
if (filterer.keepMethod(this, method)) {
filtered.add(method);
}
}
return filtered;
}
/**
* Equality is based on qualities of an object itself not those of simply its hashcode...(default behaviour)
* @param des
* @return
*/
@Override
public boolean equals(Object des) {
if (des instanceof RoundDesign) {
RoundDesign rdes = RoundDesign.class.cast(des);
return differenceBetween(rdes).size() > 0;
}
return false;
}
@Override
public String toString() {
String res = "";
for (Method meth : difference()) {
res += meth.getName() + ",";
}
return res;
}
}