org.codehaus.griffon.ast.GriffonASTUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.codehaus.griffon.ast.GriffonASTUtils.java

Source

/*
 * Copyright 2004-2011 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.codehaus.griffon.ast;

import griffon.util.GriffonUtil;
import org.apache.commons.lang.StringUtils;
import org.codehaus.groovy.ast.*;
import org.codehaus.groovy.ast.expr.*;
import org.codehaus.groovy.ast.stmt.*;
import org.codehaus.groovy.runtime.MetaClassHelper;
import org.codehaus.groovy.syntax.Token;
import org.codehaus.groovy.syntax.Types;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

/**
 * Helper methods for working with Groovy AST trees.
 *
 * @author Graeme Rocher (Grails 0.3)
 */
public class GriffonASTUtils {
    /**
     * Returns whether a classNode has the specified property or not
     *
     * @param classNode    The ClassNode
     * @param propertyName The name of the property
     * @return True if the property exists in the ClassNode
     */
    public static boolean hasProperty(ClassNode classNode, String propertyName) {
        if (classNode == null || StringUtils.isBlank(propertyName)) {
            return false;
        }

        final MethodNode method = classNode.getMethod(GriffonUtil.getGetterName(propertyName), new Parameter[0]);
        if (method != null)
            return true;

        for (PropertyNode pn : classNode.getProperties()) {
            if (pn.getName().equals(propertyName) && !pn.isPrivate()) {
                return true;
            }
        }

        return false;
    }

    public static boolean hasOrInheritsProperty(ClassNode classNode, String propertyName) {
        if (hasProperty(classNode, propertyName)) {
            return true;
        }

        ClassNode parent = classNode.getSuperClass();
        while (parent != null && !getFullName(parent).equals("java.lang.Object")) {
            if (hasProperty(parent, propertyName)) {
                return true;
            }
            parent = parent.getSuperClass();
        }

        return false;
    }

    /**
     * Tests whether the ClasNode implements the specified method name.
     *
     * @param classNode  The ClassNode
     * @param methodName The method name
     * @return True if it does implement the method
     */
    public static boolean implementsZeroArgMethod(ClassNode classNode, String methodName) {
        MethodNode method = classNode.getDeclaredMethod(methodName, new Parameter[] {});
        return method != null && (method.isPublic() || method.isProtected()) && !method.isAbstract();
    }

    @SuppressWarnings("unchecked")
    public static boolean implementsOrInheritsZeroArgMethod(ClassNode classNode, String methodName,
            List ignoreClasses) {
        if (implementsZeroArgMethod(classNode, methodName)) {
            return true;
        }

        ClassNode parent = classNode.getSuperClass();
        while (parent != null && !getFullName(parent).equals("java.lang.Object")) {
            if (!ignoreClasses.contains(parent) && implementsZeroArgMethod(parent, methodName)) {
                return true;
            }
            parent = parent.getSuperClass();
        }
        return false;
    }

    /**
     * Gets the full name of a ClassNode.
     *
     * @param classNode The class node
     * @return The full name
     */
    public static String getFullName(ClassNode classNode) {
        return classNode.getName();
    }

    public static ClassNode getFurthestParent(ClassNode classNode) {
        ClassNode parent = classNode.getSuperClass();
        while (parent != null && !getFullName(parent).equals("java.lang.Object")) {
            classNode = parent;
            parent = parent.getSuperClass();
        }
        return classNode;
    }

    public static boolean isEnum(ClassNode classNode) {
        ClassNode parent = classNode.getSuperClass();
        while (parent != null) {
            if (parent.getName().equals("java.lang.Enum"))
                return true;
            parent = parent.getSuperClass();
        }
        return false;
    }

    public static boolean addMethod(ClassNode classNode, MethodNode methodNode) {
        return addMethod(classNode, methodNode, false);
    }

    public static boolean addMethod(ClassNode classNode, MethodNode methodNode, boolean replace) {
        MethodNode oldMethod = classNode.getMethod(methodNode.getName(), methodNode.getParameters());
        if (oldMethod == null) {
            classNode.addMethod(methodNode);
            return true;
        } else if (replace) {
            classNode.getMethods().remove(oldMethod);
            classNode.addMethod(methodNode);
            return true;
        }
        return false;
    }

    /**
     * @return true if the two arrays are of the same size and have the same contents
     */
    public static boolean parametersEqual(Parameter[] a, Parameter[] b) {
        if (a.length == b.length) {
            boolean answer = true;
            for (int i = 0; i < a.length; i++) {
                if (!a[i].getType().equals(b[i].getType())) {
                    answer = false;
                    break;
                }
            }
            return answer;
        }
        return false;
    }

    public static void injectProperty(ClassNode classNode, String propertyName, Class propertyClass) {
        injectProperty(classNode, propertyName, propertyClass, null);
    }

    public static void injectProperty(ClassNode classNode, String propertyName, Class propertyClass, Object value) {
        final boolean hasProperty = hasOrInheritsProperty(classNode, propertyName);

        if (!hasProperty) {
            // inject into furthest relative
            // ClassNode parent = getFurthestParent(classNode);
            Expression initialExpression = null;
            if (value != null)
                initialExpression = new ConstantExpression(value);
            classNode.addProperty(propertyName, Modifier.PUBLIC, new ClassNode(propertyClass), initialExpression,
                    null, null);
        }
    }

    public static void injectConstant(ClassNode classNode, String propertyName, Class propertyClass, Object value) {
        final boolean hasProperty = hasOrInheritsProperty(classNode, propertyName);

        if (!hasProperty) {
            // inject into furthest relative
            // ClassNode parent = getFurthestParent(classNode);
            Expression initialExpression = new ConstantExpression(value);
            classNode.addProperty(propertyName, Modifier.PUBLIC | Modifier.FINAL, new ClassNode(propertyClass),
                    initialExpression, null, null);
        }
    }

    public static void addReadOnlyProperty(ClassNode classNode, String propertyName, ClassNode propertyClass,
            Object value) {
        final boolean hasProperty = hasOrInheritsProperty(classNode, propertyName);

        if (!hasProperty) {
            int visibility = Modifier.PRIVATE | Modifier.FINAL;
            Expression initialValue = value != null && !(value instanceof Expression)
                    ? initialValue = new ConstantExpression(value)
                    : (Expression) value;
            classNode.addField(propertyName, visibility, propertyClass, initialValue);
            addMethod(classNode, new MethodNode("get" + MetaClassHelper.capitalize(propertyName), Modifier.PUBLIC,
                    propertyClass, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, new ReturnStatement(
                            new ExpressionStatement(new FieldExpression(classNode.getField(propertyName))))));
        }
    }

    public static final Expression THIS = VariableExpression.THIS_EXPRESSION;
    public static final Expression SUPER = VariableExpression.SUPER_EXPRESSION;
    public static final ArgumentListExpression NO_ARGS = ArgumentListExpression.EMPTY_ARGUMENTS;
    public static final Token ASSIGN = Token.newSymbol(Types.ASSIGN, -1, -1);
    public static final Token EQ = Token.newSymbol(Types.COMPARE_EQUAL, -1, -1);
    public static final Token NE = Token.newSymbol(Types.COMPARE_NOT_EQUAL, -1, -1);
    public static final Token AND = Token.newSymbol(Types.LOGICAL_AND, -1, -1);
    public static final Token OR = Token.newSymbol(Types.LOGICAL_OR, -1, -1);
    public static final Token CMP = Token.newSymbol(Types.COMPARE_TO, -1, -1);
    public static final Token INSTANCEOF = Token.newSymbol(Types.KEYWORD_INSTANCEOF, -1, -1);

    @Deprecated
    public static Statement returnExpr(Expression expr) {
        return returns(expr);
    }

    public static Statement returns(Expression expr) {
        return new ReturnStatement(new ExpressionStatement(expr));
    }

    public static ArgumentListExpression vars(String... names) {
        List<Expression> vars = new ArrayList<Expression>();
        for (String name : names) {
            vars.add(var(name));
        }
        return new ArgumentListExpression(vars);
    }

    public static ArgumentListExpression args(Expression... expressions) {
        List<Expression> args = new ArrayList<Expression>();
        for (Expression expression : expressions) {
            args.add(expression);
        }
        return new ArgumentListExpression(args);
    }

    public static VariableExpression var(String name) {
        return new VariableExpression(name);
    }

    public static VariableExpression var(String name, ClassNode type) {
        return new VariableExpression(name, type);
    }

    public static Parameter param(ClassNode type, String name) {
        return param(type, name, null);
    }

    public static Parameter param(ClassNode type, String name, Expression initialExpression) {
        Parameter param = new Parameter(type, name);
        if (initialExpression != null) {
            param.setInitialExpression(initialExpression);
        }
        return param;
    }

    public static Parameter[] params(Parameter... params) {
        return params != null ? params : Parameter.EMPTY_ARRAY;
    }

    public static NotExpression not(Expression expr) {
        return new NotExpression(expr);
    }

    public static ConstantExpression constx(Object val) {
        return new ConstantExpression(val);
    }

    public static ClassExpression classx(ClassNode clazz) {
        return new ClassExpression(clazz);
    }

    public static ClassExpression classx(Class clazz) {
        return classx(ClassHelper.makeWithoutCaching(clazz));
    }

    public static BlockStatement block(Statement... stms) {
        BlockStatement block = new BlockStatement();
        for (Statement stm : stms)
            block.addStatement(stm);
        return block;
    }

    public static Statement ifs(Expression cond, Expression trueExpr) {
        return new IfStatement(
                cond instanceof BooleanExpression ? (BooleanExpression) cond : new BooleanExpression(cond),
                new ReturnStatement(trueExpr), new EmptyStatement());
    }

    public static Statement ifs(Expression cond, Expression trueExpr, Expression falseExpr) {
        return new IfStatement(
                cond instanceof BooleanExpression ? (BooleanExpression) cond : new BooleanExpression(cond),
                new ReturnStatement(trueExpr), new ReturnStatement(falseExpr));
    }

    public static Statement ifs_no_return(Expression cond, Expression trueExpr) {
        return new IfStatement(
                cond instanceof BooleanExpression ? (BooleanExpression) cond : new BooleanExpression(cond),
                new ExpressionStatement(trueExpr), new EmptyStatement());
    }

    public static Statement ifs_no_return(Expression cond, Expression trueExpr, Expression falseExpr) {
        return new IfStatement(
                cond instanceof BooleanExpression ? (BooleanExpression) cond : new BooleanExpression(cond),
                new ExpressionStatement(trueExpr), new ExpressionStatement(falseExpr));
    }

    public static Statement ifs_no_return(Expression cond, Statement trueStmnt) {
        return new IfStatement(
                cond instanceof BooleanExpression ? (BooleanExpression) cond : new BooleanExpression(cond),
                trueStmnt, new EmptyStatement());
    }

    public static Statement ifs_no_return(Expression cond, Statement trueStmnt, Statement falseStmnt) {
        return new IfStatement(
                cond instanceof BooleanExpression ? (BooleanExpression) cond : new BooleanExpression(cond),
                trueStmnt, falseStmnt);
    }

    public static Statement decls(Expression lhv, Expression rhv) {
        return new ExpressionStatement(new DeclarationExpression(lhv, ASSIGN, rhv));
    }

    public static Statement assigns(Expression expression, Expression value) {
        return new ExpressionStatement(assign(expression, value));
    }

    public static BinaryExpression assign(Expression lhv, Expression rhv) {
        return new BinaryExpression(lhv, ASSIGN, rhv);
    }

    public static BinaryExpression eq(Expression lhv, Expression rhv) {
        return new BinaryExpression(lhv, EQ, rhv);
    }

    public static BinaryExpression ne(Expression lhv, Expression rhv) {
        return new BinaryExpression(lhv, NE, rhv);
    }

    public static BinaryExpression and(Expression lhv, Expression rhv) {
        return new BinaryExpression(lhv, AND, rhv);
    }

    public static BinaryExpression or(Expression lhv, Expression rhv) {
        return new BinaryExpression(lhv, OR, rhv);
    }

    public static BinaryExpression cmp(Expression lhv, Expression rhv) {
        return new BinaryExpression(lhv, CMP, rhv);
    }

    public static BinaryExpression iof(Expression lhv, Expression rhv) {
        return new BinaryExpression(lhv, INSTANCEOF, rhv);
    }

    public static BinaryExpression iof(Expression lhv, ClassNode rhv) {
        return new BinaryExpression(lhv, INSTANCEOF, new ClassExpression(rhv));
    }

    public static Expression prop(Expression owner, String property) {
        return new PropertyExpression(owner, property);
    }

    public static Expression prop(Expression owner, Expression property) {
        return new PropertyExpression(owner, property);
    }

    public static MethodCallExpression call(Expression receiver, String methodName, ArgumentListExpression args) {
        return new MethodCallExpression(receiver, methodName, args);
    }

    public static StaticMethodCallExpression call(ClassNode receiver, String methodName,
            ArgumentListExpression args) {
        return new StaticMethodCallExpression(receiver, methodName, args);
    }

    public static ExpressionStatement stmnt(Expression expression) {
        return new ExpressionStatement(expression);
    }

    public static FieldExpression field(FieldNode fieldNode) {
        return new FieldExpression(fieldNode);
    }

    public static FieldExpression field(ClassNode owner, String fieldName) {
        return new FieldExpression(owner.getField(fieldName));
    }

    public static ConstructorCallExpression ctor(ClassNode type, Expression args) {
        return new ConstructorCallExpression(type, args);
    }
}