/** * Adds a delegate method to the target class node where the first argument is to the delegate * method is 'this'. In other words a method such as foo(Object instance, String bar) would be * added with a signature of foo(String) and 'this' is passed to the delegate instance * * @param classNode The class node * @param delegate The expression that looks up the delegate * @param declaredMethod The declared method * @param thisAsFirstArgument Whether 'this' should be passed as the first argument to the method * @return The added method node or null if it couldn't be added */ public static MethodNode addDelegateInstanceMethod( ClassNode classNode, Expression delegate, MethodNode declaredMethod, boolean thisAsFirstArgument) { Parameter[] parameterTypes = thisAsFirstArgument ? getRemainingParameterTypes(declaredMethod.getParameters()) : declaredMethod.getParameters(); String methodName = declaredMethod.getName(); if (classNode.hasDeclaredMethod(methodName, parameterTypes)) { return null; } String propertyName = GrailsClassUtils.getPropertyForGetter(methodName); if (propertyName != null && parameterTypes.length == 0 && classNode.hasProperty(propertyName)) { return null; } propertyName = GrailsClassUtils.getPropertyForSetter(methodName); if (propertyName != null && parameterTypes.length == 1 && classNode.hasProperty(propertyName)) { return null; } BlockStatement methodBody = new BlockStatement(); ArgumentListExpression arguments = createArgumentListFromParameters(parameterTypes, thisAsFirstArgument); ClassNode returnType = nonGeneric(declaredMethod.getReturnType()); MethodCallExpression methodCallExpression = new MethodCallExpression(delegate, methodName, arguments); methodCallExpression.setMethodTarget(declaredMethod); ThrowStatement missingMethodException = createMissingMethodThrowable(classNode, declaredMethod); VariableExpression apiVar = addApiVariableDeclaration(delegate, declaredMethod, methodBody); IfStatement ifStatement = createIfElseStatementForApiMethodCall(methodCallExpression, apiVar, missingMethodException); methodBody.addStatement(ifStatement); MethodNode methodNode = new MethodNode( methodName, Modifier.PUBLIC, returnType, copyParameters(parameterTypes), GrailsArtefactClassInjector.EMPTY_CLASS_ARRAY, methodBody); methodNode.addAnnotations(declaredMethod.getAnnotations()); classNode.addMethod(methodNode); return methodNode; }
/** * Adds a static method to the given class node that delegates to the given method and resolves * the object to invoke the method on from the given expression. * * @param expression The expression * @param classNode The class node * @param delegateMethod The delegate method * @return The added method node or null if it couldn't be added */ public static MethodNode addDelegateStaticMethod( Expression expression, ClassNode classNode, MethodNode delegateMethod) { Parameter[] parameterTypes = delegateMethod.getParameters(); String declaredMethodName = delegateMethod.getName(); if (classNode.hasDeclaredMethod(declaredMethodName, parameterTypes)) { return null; } BlockStatement methodBody = new BlockStatement(); ArgumentListExpression arguments = new ArgumentListExpression(); for (Parameter parameterType : parameterTypes) { arguments.addExpression(new VariableExpression(parameterType.getName())); } MethodCallExpression methodCallExpression = new MethodCallExpression(expression, declaredMethodName, arguments); methodCallExpression.setMethodTarget(delegateMethod); ThrowStatement missingMethodException = createMissingMethodThrowable(classNode, delegateMethod); VariableExpression apiVar = addApiVariableDeclaration(expression, delegateMethod, methodBody); IfStatement ifStatement = createIfElseStatementForApiMethodCall(methodCallExpression, apiVar, missingMethodException); methodBody.addStatement(ifStatement); ClassNode returnType = nonGeneric(delegateMethod.getReturnType()); if (METHOD_MISSING_METHOD_NAME.equals(declaredMethodName)) { declaredMethodName = STATIC_METHOD_MISSING_METHOD_NAME; } MethodNode methodNode = classNode.getDeclaredMethod(declaredMethodName, parameterTypes); if (methodNode == null) { methodNode = new MethodNode( declaredMethodName, Modifier.PUBLIC | Modifier.STATIC, returnType, copyParameters(parameterTypes), GrailsArtefactClassInjector.EMPTY_CLASS_ARRAY, methodBody); methodNode.addAnnotations(delegateMethod.getAnnotations()); classNode.addMethod(methodNode); } return methodNode; }