com.motorola.studio.android.generateviewbylayout.codegenerators.RadioButtonCodeGenerator.java Source code

Java tutorial

Introduction

Here is the source code for com.motorola.studio.android.generateviewbylayout.codegenerators.RadioButtonCodeGenerator.java

Source

/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * 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 com.motorola.studio.android.generateviewbylayout.codegenerators;

import java.util.List;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.ExpressionStatement;
import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.IfStatement;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;
import org.eclipse.jdt.core.dom.PrimitiveType;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SimpleType;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;

import com.motorola.studio.android.codeutils.i18n.CodeUtilsNLS;
import com.motorola.studio.android.generateviewbylayout.JavaViewBasedOnLayoutModifierConstants;
import com.motorola.studio.android.generateviewbylayout.model.CodeGeneratorDataBasedOnLayout;
import com.motorola.studio.android.generateviewbylayout.model.LayoutNode;

/**
 * Responsible to add methods to deal with RadioButtons events
 */
public class RadioButtonCodeGenerator extends AbstractLayoutCodeGenerator {
    /**
     * @param codeGeneratorData
     * @param onCreateDeclaration
     * @param typeDeclaration
     */
    public RadioButtonCodeGenerator(CodeGeneratorDataBasedOnLayout codeGeneratorData,
            MethodDeclaration onCreateDeclaration, TypeDeclaration typeDeclaration) {
        super(codeGeneratorData, onCreateDeclaration, typeDeclaration);
    }

    @Override
    public void generateCode(IProgressMonitor monitor) throws JavaModelException {
        addSetOnClickListener(monitor);
        addMethodToDeclareRadioButtonHandlerNotDeclaredOnLayoutXML(monitor);
    }

    /**
     * Add method handlers for RadioButtons 
     * 
     * <br>
     * GENERATED_CODE_FORMAT:
     * <br>
     * this.$GUI_ID.setOnClickListener(onClickHandler);
     */
    @SuppressWarnings("unchecked")
    private void addSetOnClickListener(IProgressMonitor monitor) throws JavaModelException {
        SubMonitor subMonitor = SubMonitor.convert(monitor);
        subMonitor.beginTask(CodeUtilsNLS.JavaViewBasedOnLayoutModifier_AddingSetOnClickListener,
                codeGeneratorData.getGuiItems().size());
        /* ExpressionStatement
        expression
            MethodInvocation
                arguments handler
                methodName SimpleName(setOnClickListener)
                optionalExpression SimpleName(button1)
         */
        for (LayoutNode node : codeGeneratorData.getGuiItems()) {
            if (node.shouldInsertCode()
                    && node.getNodeType().equals(LayoutNode.LayoutNodeViewType.RadioButton.name())) {
                boolean containMethodDeclared = checkIfInvokeMethodIsDeclared(node,
                        JavaViewBasedOnLayoutModifierConstants.SET_ON_CLICK_LISTENER);
                if (!containMethodDeclared) {
                    SimpleName method = onCreateDeclaration.getAST()
                            .newSimpleName(JavaViewBasedOnLayoutModifierConstants.SET_ON_CLICK_LISTENER);
                    SimpleName bId = onCreateDeclaration.getAST().newSimpleName(node.getNodeId());
                    FieldAccess fieldAccess = onCreateDeclaration.getAST().newFieldAccess();
                    fieldAccess.setExpression(onCreateDeclaration.getAST().newThisExpression());
                    fieldAccess.setName(bId);

                    SimpleName handler = onCreateDeclaration.getAST()
                            .newSimpleName(JavaViewBasedOnLayoutModifierConstants.HANDLER_ONCLICK_LISTENER);

                    MethodInvocation mI = onCreateDeclaration.getAST().newMethodInvocation();
                    mI.arguments().add(handler);
                    mI.setName(method);
                    mI.setExpression(fieldAccess);

                    ExpressionStatement expr = onCreateDeclaration.getAST().newExpressionStatement(mI);
                    if (!onCreateDeclaration.toString().contains(expr.toString())) {
                        //avoid to duplicate statement
                        insertStatementsAtOnCreateDeclaration(expr, false);
                    }
                }
            }
            subMonitor.worked(1);
        }
    }

    /**
     * Add method to declare button events handler (not declared on layout XML) 
     * @throws JavaModelException
     * 
     * <br>
     * GENERATED_CODE_FORMAT:
     * <br>
     * private View.OnClickListener onClickHandler = new View.OnClickListener() {
     * <br>
     *   public void onClick(View target) {
     * <br>  
     *       if (target.getId() == $GUI_ID1) {
     * <br>
     *       } else if (target.getId() == $GUI_ID2) {
     * <br>           
     *       }
     * <br>
     *   }
     * <br>
     * };
     * 
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    private void addMethodToDeclareRadioButtonHandlerNotDeclaredOnLayoutXML(IProgressMonitor monitor)
            throws JavaModelException {
        SubMonitor subMonitor = SubMonitor.convert(monitor);
        //need to look at each GUI item and them create 1 method 
        subMonitor.beginTask(CodeUtilsNLS.JavaViewBasedOnLayoutModifier_AddingMethodToHandleButton,
                codeGeneratorData.getGuiItems().size() + 1);
        IfStatement ifStatement = null;
        for (LayoutNode node : codeGeneratorData.getGuiItems()) {
            if (node.getNodeType().equals(LayoutNode.LayoutNodeViewType.RadioButton.name())
                    && node.shouldInsertCode()) {

                if (typeDeclaration.bodyDeclarations() != null) {
                    //check if field already declared                  
                    outer: for (Object bd : typeDeclaration.bodyDeclarations()) {
                        if (bd instanceof FieldDeclaration) {
                            FieldDeclaration fd = (FieldDeclaration) bd;
                            if ((fd.fragments() != null)) {
                                String listenerType = getListenerSimpleType(
                                        JavaViewBasedOnLayoutModifierConstants.VIEW_CLASS,
                                        JavaViewBasedOnLayoutModifierConstants.METHOD_ON_CLICK_LISTENER).toString();
                                for (Object fragment : fd.fragments()) {
                                    if (fragment instanceof VariableDeclarationFragment) {
                                        VariableDeclarationFragment variableFragment = (VariableDeclarationFragment) fragment;
                                        if ((variableFragment.getName() != null)
                                                && variableFragment.getName().toString().equals(
                                                        JavaViewBasedOnLayoutModifierConstants.HANDLER_ONCLICK_LISTENER)
                                                && fd.getType().toString().equals(listenerType)) {
                                            Expression expr = variableFragment.getInitializer();
                                            if (expr instanceof ClassInstanceCreation) {
                                                ClassInstanceCreation classInstanceCreation = (ClassInstanceCreation) expr;
                                                AnonymousClassDeclaration anonymousClassDeclaration = classInstanceCreation
                                                        .getAnonymousClassDeclaration();
                                                for (Object bodyDeclaration : anonymousClassDeclaration
                                                        .bodyDeclarations()) {
                                                    if (bodyDeclaration instanceof MethodDeclaration) {
                                                        MethodDeclaration methodDeclaration = (MethodDeclaration) bodyDeclaration;
                                                        List statementsList = methodDeclaration.getBody()
                                                                .statements();
                                                        for (Object statement : statementsList) {
                                                            if (statement instanceof IfStatement) {
                                                                if (statement.toString().contains(
                                                                        JavaViewBasedOnLayoutModifierConstants.VIEW_VARIABLE_NAME
                                                                                + "." //$NON-NLS-1$
                                                                                + JavaViewBasedOnLayoutModifierConstants.METHOD_NAME_GET_ID)) {
                                                                    //found if statement 
                                                                    ifStatement = (IfStatement) statement;
                                                                    break outer;
                                                                }
                                                            }
                                                        }
                                                        if (ifStatement == null) {
                                                            ifStatement = typeDeclaration.getAST().newIfStatement();
                                                            statementsList.add(ifStatement);
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }

                            }
                        }
                    }
                }
                if (ifStatement == null) {
                    //create field with onClickListener class instance creation
                    //create method in the first time, after that, start to add new items in the same method
                    ifStatement = createOnClickListenerForRadioButtons(node);
                } else {
                    //already have onClickListener field declared => append new item into the "else if" chain
                    addElseIfForEachRadioButtonId(ifStatement, node);
                }
            }
            subMonitor.worked(1);
        }

    }

    /**
     * Creates field with an anonymous class declaration for radio buttons
     */
    @SuppressWarnings("unchecked")
    private IfStatement createOnClickListenerForRadioButtons(LayoutNode node) {
        IfStatement ifSt;
        Modifier privateMod = typeDeclaration.getAST().newModifier(ModifierKeyword.PRIVATE_KEYWORD);
        SimpleType listenerType = getListenerSimpleType(JavaViewBasedOnLayoutModifierConstants.VIEW_CLASS,
                JavaViewBasedOnLayoutModifierConstants.METHOD_ON_CLICK_LISTENER);

        VariableDeclarationFragment variableFragment = typeDeclaration.getAST().newVariableDeclarationFragment();
        SimpleName varName = variableFragment.getAST()
                .newSimpleName(JavaViewBasedOnLayoutModifierConstants.HANDLER_ONCLICK_LISTENER);
        variableFragment.setName(varName);
        FieldDeclaration declaration = typeDeclaration.getAST().newFieldDeclaration(variableFragment);
        declaration.modifiers().add(privateMod);
        declaration.setType(listenerType);

        ClassInstanceCreation classInstanceCreation = typeDeclaration.getAST().newClassInstanceCreation();

        SimpleType listenerType2 = getListenerSimpleType(JavaViewBasedOnLayoutModifierConstants.VIEW_CLASS,
                JavaViewBasedOnLayoutModifierConstants.METHOD_ON_CLICK_LISTENER);

        classInstanceCreation.setType(listenerType2);
        AnonymousClassDeclaration classDeclaration = typeDeclaration.getAST().newAnonymousClassDeclaration();
        MethodDeclaration methodDeclaration = addMethodDeclaration(ModifierKeyword.PUBLIC_KEYWORD,
                JavaViewBasedOnLayoutModifierConstants.METHOD_NAME_ON_CLICK, PrimitiveType.VOID,
                JavaViewBasedOnLayoutModifierConstants.VIEW_CLASS,
                JavaViewBasedOnLayoutModifierConstants.VIEW_VARIABLE_NAME);
        Block block = typeDeclaration.getAST().newBlock();
        ifSt = createElseIfForEachRadioButtonId(node);
        block.statements().add(ifSt);
        methodDeclaration.setBody(block);
        classDeclaration.bodyDeclarations().add(methodDeclaration);
        classInstanceCreation.setAnonymousClassDeclaration(classDeclaration);
        variableFragment.setInitializer(classInstanceCreation);
        typeDeclaration.bodyDeclarations().add(declaration);
        return ifSt;
    }

    /**
     * @return "else if" chain for each radio button id 
     */
    private IfStatement createElseIfForEachRadioButtonId(LayoutNode node) {
        IfStatement ifStatement = typeDeclaration.getAST().newIfStatement();
        addElseIfForEachRadioButtonId(ifStatement, node);
        return ifStatement;
    }

    /**
     * Creates else if and else statements for each radio button
     * @param ifSt If statement where the next "else if" will be appended
     * @param node Layout node
     */
    private void addElseIfForEachRadioButtonId(IfStatement ifSt, LayoutNode node) {
        if (node.getNodeType().equals(LayoutNode.LayoutNodeViewType.RadioButton.name())
                && node.shouldInsertCode()) {
            MethodInvocation invocation = typeDeclaration.getAST().newMethodInvocation();
            invocation.setExpression(getVariableName(JavaViewBasedOnLayoutModifierConstants.VIEW_VARIABLE_NAME));
            SimpleName getIdName = typeDeclaration.getAST()
                    .newSimpleName(JavaViewBasedOnLayoutModifierConstants.METHOD_NAME_GET_ID);
            invocation.setName(getIdName);

            SimpleName r = typeDeclaration.getAST().newSimpleName(JavaViewBasedOnLayoutModifierConstants.R);
            SimpleName id = typeDeclaration.getAST().newSimpleName(JavaViewBasedOnLayoutModifierConstants.ID);
            QualifiedName rid = typeDeclaration.getAST().newQualifiedName(r, id);
            SimpleName guiId = typeDeclaration.getAST().newSimpleName(node.getNodeId());
            QualifiedName guiQN = typeDeclaration.getAST().newQualifiedName(rid, guiId);
            createElseIfAndElseStatements(ifSt, invocation, guiQN);
        }
    }
}