Package grails.plugin.multitenant.core.ast

Source Code of grails.plugin.multitenant.core.ast.MultiTenantAST

package grails.plugin.multitenant.core.ast;

import grails.plugin.multitenant.core.MultiTenantDomainClass;

import java.lang.reflect.Modifier;

import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.ast.stmt.Statement;
import org.codehaus.groovy.control.CompilePhase;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.grails.compiler.injection.GrailsASTUtils;
import org.codehaus.groovy.transform.ASTTransformation;
import org.codehaus.groovy.transform.GroovyASTTransformation;

/**
* Adds a tenantId property to domain classes annotated MultiTenant.
*/
@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
public class MultiTenantAST implements ASTTransformation {

    public final static String TENANT_ID_FIELD_NAME = "tenantId";

    // TODO: ConstantExpression.NULL would be better, but that leads to all sorts of crazy problems
    // with default GORM constraints. It looks like it will become easier to hook into this in Grails 1.4:
    // https://github.com/grails/grails-core/blob/master/grails-core/src/main/groovy/org/codehaus/groovy/grails/validation/ConstraintsEvaluatorFactoryBean.java
    public final static Integer NO_TENANT_VALUE = Integer.MIN_VALUE;

    @Override
    public void visit(ASTNode[] astNodes, SourceUnit sourceUnit) {
        ClassNode annotatedClassNode = (ClassNode) astNodes[1];
        addTenantPropertyIfNecessary(annotatedClassNode);
        implementInterface(annotatedClassNode, MultiTenantDomainClass.class);
    }

    private void addTenantPropertyIfNecessary(ClassNode classNode) {
        if (!hasTenantIdProperty(classNode)) {
            addTenantProperty(classNode);
        }
    }

    private boolean hasTenantIdProperty(ClassNode node) {
        return GrailsASTUtils.hasOrInheritsProperty(node, "tenantId");
    }

    private void addTenantProperty(ClassNode node) {
        ClassNode integerType = new ClassNode(Integer.class);
        ConstantExpression defaultValue = new ConstantExpression(NO_TENANT_VALUE);
        Statement getterBlock = null;
        Statement setterBlock = null;
        node.addProperty(TENANT_ID_FIELD_NAME, Modifier.PUBLIC,
                integerType, defaultValue, getterBlock, setterBlock);
    }

    private void implementInterface(ClassNode node, Class<?> interf) {
        ClassNode interfaceClassNode = new ClassNode(interf);
        if (!node.implementsInterface(interfaceClassNode)) {
            node.addInterface(interfaceClassNode);
        }
    }

}
TOP

Related Classes of grails.plugin.multitenant.core.ast.MultiTenantAST

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.