use of beast.core.Param in project beast2 by CompEvol.
the class XMLParser method useAnnotatedConstructor.
@SuppressWarnings({ "rawtypes", "unchecked" })
private BEASTInterface useAnnotatedConstructor(Node node, String _id, String clazzName, List<NameValuePair> inputInfo) throws XMLParserException {
Class<?> clazz = null;
try {
clazz = Class.forName(clazzName);
} catch (ClassNotFoundException e) {
// cannot get here, since we checked the class existed before
e.printStackTrace();
}
Constructor<?>[] allConstructors = clazz.getDeclaredConstructors();
for (Constructor<?> ctor : allConstructors) {
Annotation[][] annotations = ctor.getParameterAnnotations();
List<Param> paramAnnotations = new ArrayList<>();
for (Annotation[] a0 : annotations) {
for (Annotation a : a0) {
if (a instanceof Param) {
paramAnnotations.add((Param) a);
}
}
}
for (NameValuePair pair : inputInfo) {
pair.processed = false;
}
Class<?>[] types = ctor.getParameterTypes();
// Type[] gtypes = ctor.getGenericParameterTypes();
if (types.length > 0 && paramAnnotations.size() == types.length) {
try {
Object[] args = new Object[types.length];
for (int i = 0; i < types.length; i++) {
Param param = paramAnnotations.get(i);
Type type = types[i];
if (type.getTypeName().equals("java.util.List")) {
if (args[i] == null) {
// no need to parameterise list due to type erasure
args[i] = new ArrayList();
}
List<Object> values = getListOfValues(param, inputInfo);
((List) args[i]).addAll(values);
} else {
args[i] = getValue(param, types[i], inputInfo);
// and the args[i] is a String -- we need to invoke the String constructor
if (args[i].getClass().equals(String.class) && types[i] != String.class) {
for (Constructor<?> argctor : types[i].getDeclaredConstructors()) {
Class<?>[] argtypes = argctor.getParameterTypes();
if (argtypes.length == 1 && argtypes[0] == String.class) {
Object o = argctor.newInstance(args[i]);
args[i] = o;
break;
}
}
}
}
}
// ensure all inputs are used
boolean allUsed = true;
for (NameValuePair pair : inputInfo) {
if (!pair.processed) {
allUsed = false;
}
}
if (allUsed) {
try {
Object o = ctor.newInstance(args);
BEASTInterface beastObject = (BEASTInterface) o;
register(node, beastObject);
return beastObject;
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new XMLParserException(node, "Could not create object: " + e.getMessage(), 1012);
}
}
} catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
// we get here when a param value cannot be constructed from a default value
// let's try the next constructor (if any)
}
}
}
return null;
}
use of beast.core.Param in project beast2 by CompEvol.
the class XMLParserUtils method listInputs.
// replace
/**
* return list of input types specified by Inputs or Param annotations
* @param clazz Class to generate the list for
* @param beastObject instantiation of the class, or null if not available
* @return
* @throws InstantiationException
* @throws IllegalAccessException
* @throws SecurityException
* @throws NoSuchMethodException
* @throws IllegalArgumentException
*/
public static List<InputType> listInputs(Class<?> clazz, BEASTInterface beastObject) throws InstantiationException, IllegalAccessException, IllegalArgumentException, NoSuchMethodException, SecurityException {
List<InputType> inputTypes = new ArrayList<>();
// First, collect Input members
try {
if (beastObject == null) {
beastObject = (BEASTInterface) clazz.newInstance();
}
List<Input<?>> inputs = null;
inputs = beastObject.listInputs();
for (Input<?> input : inputs) {
if (!(input instanceof InputForAnnotatedConstructor)) {
try {
// force class types to be determined
if (input.getType() == null) {
input.determineClass(beastObject);
}
inputTypes.add(new InputType(input.getName(), input.getType(), true, input.defaultValue));
} catch (Exception e) {
// seems safe to ignore
e.printStackTrace();
}
}
}
} catch (InstantiationException e) {
// this can happen if there is no constructor without arguments,
// e.g. when there are annotated constructors only
}
// Second, collect types of annotated constructor
Constructor<?>[] allConstructors = clazz.getDeclaredConstructors();
for (Constructor<?> ctor : allConstructors) {
Annotation[][] annotations = ctor.getParameterAnnotations();
List<Param> paramAnnotations = new ArrayList<>();
for (Annotation[] a0 : annotations) {
for (Annotation a : a0) {
if (a instanceof Param) {
paramAnnotations.add((Param) a);
}
}
}
Class<?>[] types = ctor.getParameterTypes();
Type[] gtypes = ctor.getGenericParameterTypes();
if (types.length > 0 && paramAnnotations.size() > 0) {
int offset = 0;
if (types.length == paramAnnotations.size() + 1) {
offset = 1;
}
for (int i = 0; i < paramAnnotations.size(); i++) {
Param param = paramAnnotations.get(i);
Type type = types[i + offset];
Class<?> clazz2 = null;
try {
clazz2 = Class.forName(type.getTypeName());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (clazz2.isAssignableFrom(List.class)) {
Type[] genericTypes2 = ((ParameterizedType) gtypes[i + offset]).getActualTypeArguments();
Class<?> theClass = (Class<?>) genericTypes2[0];
InputType t = new InputType(param.name(), theClass, false, param.defaultValue());
inputTypes.add(t);
} else {
InputType t = new InputType(param.name(), types[i + offset], false, param.defaultValue());
inputTypes.add(t);
}
}
}
}
return inputTypes;
}
use of beast.core.Param in project beast2 by CompEvol.
the class JSONParser method useAnnotatedConstructor.
@SuppressWarnings({ "rawtypes", "unchecked" })
private BEASTInterface useAnnotatedConstructor(JSONObject node, String _id, String clazzName, List<NameValuePair> inputInfo) throws JSONParserException {
Class<?> clazz = null;
try {
clazz = Class.forName(clazzName);
} catch (ClassNotFoundException e) {
// cannot get here, since we checked the class existed before
e.printStackTrace();
}
Constructor<?>[] allConstructors = clazz.getDeclaredConstructors();
for (Constructor<?> ctor : allConstructors) {
// collect Param annotations on constructor parameters
Annotation[][] annotations = ctor.getParameterAnnotations();
List<Param> paramAnnotations = new ArrayList<>();
for (Annotation[] a0 : annotations) {
for (Annotation a : a0) {
if (a instanceof Param) {
paramAnnotations.add((Param) a);
}
}
}
for (NameValuePair pair : inputInfo) {
pair.processed = false;
}
Class<?>[] types = ctor.getParameterTypes();
if (types.length > 0 && paramAnnotations.size() == types.length) {
try {
// if all constructor parameters have Param annotations, try to call constructor
// first, build up argument list, then create object
Object[] args = new Object[types.length];
for (int i = 0; i < types.length; i++) {
Param param = paramAnnotations.get(i);
Type type = types[i];
if (type.getTypeName().equals("java.util.List")) {
if (args[i] == null) {
// no need to parameterise list due to type erasure
args[i] = new ArrayList();
}
List<Object> values = XMLParser.getListOfValues(param, inputInfo);
((List<Object>) args[i]).addAll(values);
} else {
args[i] = getValue(param, (Class<?>) type, inputInfo);
}
}
// ensure all inputs are used
boolean allUsed = true;
for (NameValuePair pair : inputInfo) {
if (!pair.processed) {
allUsed = false;
}
}
// if all inputs are used, call the constructor, otherwise, look for another constructor
if (allUsed) {
try {
Object o = ctor.newInstance(args);
BEASTInterface beastObject = (BEASTInterface) o;
register(node, beastObject);
return beastObject;
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new JSONParserException(node, "Could not create object: " + e.getMessage(), 1012);
}
}
} catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
// we get here when a param value cannot be constructed from a default value
// let's try the next constructor (if any)
}
}
}
return null;
}
use of beast.core.Param in project beast2 by CompEvol.
the class InputTypeTest method testAnnotatedInputHasGetters.
public void testAnnotatedInputHasGetters(String[] packages) throws Exception {
List<String> beastObjectNames = PackageManager.find(Object.class, packages);
System.err.println("Testing " + beastObjectNames.size() + " classes");
List<String> failingInputs = new ArrayList<String>();
for (String beastObject : beastObjectNames) {
try {
Class<?> _class = Class.forName(beastObject);
Constructor<?>[] allConstructors = _class.getDeclaredConstructors();
for (Constructor<?> ctor : allConstructors) {
Annotation[][] annotations = ctor.getParameterAnnotations();
List<Param> paramAnnotations = new ArrayList<>();
for (Annotation[] a0 : annotations) {
for (Annotation a : a0) {
if (a instanceof Param) {
paramAnnotations.add((Param) a);
}
}
}
if (paramAnnotations.size() > 0 && !BEASTInterface.class.isAssignableFrom(_class)) {
failingInputs.add(_class.getName() + " has Param annotations but does not implement BEASTInterface\n");
}
Class<?>[] types = ctor.getParameterTypes();
Type[] gtypes = ctor.getGenericParameterTypes();
if (types.length > 0 && paramAnnotations.size() > 0) {
int offset = 0;
if (types.length == paramAnnotations.size() + 1) {
offset = 1;
}
for (int i = 0; i < paramAnnotations.size(); i++) {
Class<?> type;
Class<?> clazz = null;
boolean isList = false;
String typeName = types[i + offset].getTypeName();
if (typeName.endsWith("[]")) {
failingInputs.add(_class.getName() + " constructor has arrray as argument, should be a List\n");
} else {
switch(typeName) {
case "int":
type = Integer.class;
break;
case "long":
type = Long.class;
break;
case "float":
type = Float.class;
break;
case "double":
type = Double.class;
break;
case "boolean":
type = Boolean.class;
break;
default:
clazz = Class.forName(typeName);
if (clazz.isAssignableFrom(List.class)) {
Type[] genericTypes2 = ((ParameterizedType) gtypes[i + offset]).getActualTypeArguments();
type = (Class<?>) genericTypes2[0];
isList = true;
} else {
type = types[i + offset];
}
}
String name = paramAnnotations.get(i).name();
String getter = "get" + name.substring(0, 1).toUpperCase() + name.substring(1);
try {
Method method = _class.getMethod(getter);
if (isList) {
if (!method.getReturnType().isAssignableFrom(List.class)) {
failingInputs.add(_class.getName() + ":" + getter + "() should return List<" + type.getName() + "> instead of " + method.getReturnType().getName() + "\n");
}
} else if (!method.getReturnType().isAssignableFrom(type)) {
failingInputs.add(_class.getName() + ":" + getter + "() should return " + type.getName() + " instead of " + method.getReturnType().getName() + "\n");
}
} catch (NoSuchMethodException e) {
failingInputs.add(_class.getName() + ":" + getter + "() missing\n");
}
String setter = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
try {
_class.getMethod(setter, type);
} catch (NoSuchMethodException e) {
failingInputs.add(_class.getName() + ":" + setter + "(" + type.getName() + ") missing, or does not have correct argument\n");
}
}
}
}
}
} catch (Exception e) {
System.err.println(beastObject + " " + e.getClass().getName() + " " + e.getMessage());
}
}
System.err.println("Done!");
assertTrue("Something is wrong with these annotated constructor(s): \n" + failingInputs.toString(), failingInputs.size() == 0);
}
Aggregations