Search in sources :

Example 1 with Param

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;
}
Also used : ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) NodeList(org.w3c.dom.NodeList) List(java.util.List) Constructor(java.lang.reflect.Constructor) Annotation(java.lang.annotation.Annotation) InvocationTargetException(java.lang.reflect.InvocationTargetException) Type(java.lang.reflect.Type) Param(beast.core.Param) BEASTInterface(beast.core.BEASTInterface)

Example 2 with Param

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;
}
Also used : InputForAnnotatedConstructor(beast.core.InputForAnnotatedConstructor) ArrayList(java.util.ArrayList) ParameterizedType(java.lang.reflect.ParameterizedType) Input(beast.core.Input) InputForAnnotatedConstructor(beast.core.InputForAnnotatedConstructor) Constructor(java.lang.reflect.Constructor) Annotation(java.lang.annotation.Annotation) ParameterizedType(java.lang.reflect.ParameterizedType) Type(java.lang.reflect.Type) Param(beast.core.Param)

Example 3 with Param

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;
}
Also used : ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) NameValuePair(beast.util.XMLParser.NameValuePair) Constructor(java.lang.reflect.Constructor) Annotation(java.lang.annotation.Annotation) InvocationTargetException(java.lang.reflect.InvocationTargetException) Type(java.lang.reflect.Type) Param(beast.core.Param) JSONObject(org.json.JSONObject) BEASTInterface(beast.core.BEASTInterface)

Example 4 with Param

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);
}
Also used : Constructor(java.lang.reflect.Constructor) ArrayList(java.util.ArrayList) Method(java.lang.reflect.Method) Annotation(java.lang.annotation.Annotation) ParameterizedType(java.lang.reflect.ParameterizedType) ParameterizedType(java.lang.reflect.ParameterizedType) Type(java.lang.reflect.Type) Param(beast.core.Param) ArrayList(java.util.ArrayList) List(java.util.List)

Aggregations

Param (beast.core.Param)4 Annotation (java.lang.annotation.Annotation)4 Constructor (java.lang.reflect.Constructor)4 Type (java.lang.reflect.Type)4 ArrayList (java.util.ArrayList)4 List (java.util.List)3 BEASTInterface (beast.core.BEASTInterface)2 InvocationTargetException (java.lang.reflect.InvocationTargetException)2 ParameterizedType (java.lang.reflect.ParameterizedType)2 Input (beast.core.Input)1 InputForAnnotatedConstructor (beast.core.InputForAnnotatedConstructor)1 NameValuePair (beast.util.XMLParser.NameValuePair)1 Method (java.lang.reflect.Method)1 JSONObject (org.json.JSONObject)1 NodeList (org.w3c.dom.NodeList)1