org.jboss.tools.arquillian.ui.internal.wizards.NewArquillianJUnitTestCasePageOne.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.tools.arquillian.ui.internal.wizards.NewArquillianJUnitTestCasePageOne.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Sebastian Davids, sdavids@gmx.de - bug 38507
 *     Sebastian Davids, sdavids@gmx.de - 113998 [JUnit] New Test Case Wizard: Class Under Test Dialog -- allow Enums
 *     Kris De Volder <kris.de.volder@gmail.com> - Allow changing the default superclass in NewTestCaseWizardPageOne - https://bugs.eclipse.org/312204
 *     JBoss by Red Hat
 *******************************************************************************/
package org.jboss.tools.arquillian.ui.internal.wizards;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.compiler.IScanner;
import org.eclipse.jdt.core.compiler.ITerminalSymbols;
import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.internal.corext.util.JavaConventionsUtil;
import org.eclipse.jdt.internal.junit.BasicElementLabels;
import org.eclipse.jdt.internal.junit.Messages;
import org.eclipse.jdt.internal.junit.buildpath.BuildPathSupport;
import org.eclipse.jdt.internal.junit.ui.IJUnitHelpContextIds;
import org.eclipse.jdt.internal.junit.util.CoreTestSearchEngine;
import org.eclipse.jdt.internal.junit.util.JUnitStatus;
import org.eclipse.jdt.internal.junit.util.JUnitStubUtility;
import org.eclipse.jdt.internal.junit.util.JUnitStubUtility.GenStubSettings;
import org.eclipse.jdt.internal.junit.util.LayoutUtil;
import org.eclipse.jdt.internal.junit.wizards.MethodStubsSelectionButtonGroup;
import org.eclipse.jdt.internal.junit.wizards.WizardMessages;
import org.eclipse.jdt.internal.ui.refactoring.contentassist.ControlContentAssistHelper;
import org.eclipse.jdt.internal.ui.refactoring.contentassist.JavaTypeCompletionProcessor;
import org.eclipse.jdt.junit.wizards.NewTestCaseWizardPageTwo;
import org.eclipse.jdt.ui.CodeGeneration;
import org.eclipse.jdt.ui.IJavaElementSearchConstants;
import org.eclipse.jdt.ui.JavaElementLabels;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.ui.wizards.NewTypeWizardPage;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.IWizard;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.dialogs.SelectionDialog;
import org.jboss.tools.arquillian.core.internal.natures.ArquillianNature;
import org.jboss.tools.arquillian.ui.ArquillianUIActivator;
import org.jboss.tools.arquillian.ui.internal.utils.ArquillianUIUtil;

import com.ibm.icu.text.UTF16;

/**
 * The class <code>NewArquillianJunitTestCasePageOne</code> contains controls and validation routines
 * for the first page of the  'New Arquillian JUnit Test Case Wizard'.
 *
 * Based on org.eclipse.jdt.junit.wizards.NewTestCaseWizardPageOne
 *
 */
public class NewArquillianJUnitTestCasePageOne extends NewTypeWizardPage {

    private static final String ORG_JUNIT_RUNNER_RUNWITH = "org.junit.runner.RunWith"; //$NON-NLS-1$

    private final static String JUNIT4_ANNOTATION_NAME = "org.junit.Test"; //$NON-NLS-1$

    private final static String PAGE_NAME = "NewArquillianJUnitTestCasePageOne"; //$NON-NLS-1$

    /** Field ID of the class under test field. */
    public final static String CLASS_UNDER_TEST = PAGE_NAME + ".classundertest"; //$NON-NLS-1$

    private static final String COMPLIANCE_PAGE_ID = "org.eclipse.jdt.ui.propertyPages.CompliancePreferencePage"; //$NON-NLS-1$
    private static final String BUILD_PATH_PAGE_ID = "org.eclipse.jdt.ui.propertyPages.BuildPathsPropertyPage"; //$NON-NLS-1$
    private static final String BUILD_PATH_KEY_ADD_ENTRY = "add_classpath_entry"; //$NON-NLS-1$
    private static final String BUILD_PATH_BLOCK = "block_until_buildpath_applied"; //$NON-NLS-1$

    private static final String KEY_NO_LINK = "PropertyAndPreferencePage.nolink"; //$NON-NLS-1$

    private final static String QUESTION_MARK_TAG = "Q"; //$NON-NLS-1$
    private final static String OF_TAG = "Of"; //$NON-NLS-1$

    private final static String TEST_SUFFIX = "Test"; //$NON-NLS-1$
    private final static String PREFIX = "test"; //$NON-NLS-1$

    private final static String STORE_SETUP = PAGE_NAME + ".USE_SETUP"; //$NON-NLS-1$
    private final static String STORE_TEARDOWN = PAGE_NAME + ".USE_TEARDOWN"; //$NON-NLS-1$
    private final static String STORE_SETUP_CLASS = PAGE_NAME + ".USE_SETUPCLASS"; //$NON-NLS-1$
    private final static String STORE_TEARDOWN_CLASS = PAGE_NAME + ".USE_TEARDOWNCLASS"; //$NON-NLS-1$
    private final static String STORE_DEPLOYMENT = PAGE_NAME + ".USE_DEPLOYMENT"; //$NON-NLS-1$

    private final static int IDX_SETUP_CLASS = 0;
    private final static int IDX_TEARDOWN_CLASS = 1;
    private final static int IDX_SETUP = 2;
    private final static int IDX_TEARDOWN = 3;
    private final static int IDX_DEPLOYMENT = 4;

    private NewTestCaseWizardPageTwo fPage2;
    private NewArquillianJUnitTestCaseDeploymentPage fPage3;
    private MethodStubsSelectionButtonGroup fMethodStubsButtons;

    private String fClassUnderTestText; // model
    private IType fClassUnderTest; // resolved model, can be null

    private Text fClassUnderTestControl; // control
    private IStatus fClassUnderTestStatus; // status

    private Button fClassUnderTestButton;
    private JavaTypeCompletionProcessor fClassToTestCompletionProcessor;

    private Link fLink;
    private Label fImage;

    /**
     * Creates a new <code>NewTestCaseCreationWizardPage</code>.
     * @param page2 The second page
     *
     * @since 3.1
     */
    public NewArquillianJUnitTestCasePageOne(NewTestCaseWizardPageTwo page2,
            NewArquillianJUnitTestCaseDeploymentPage page3) {
        super(true, PAGE_NAME);
        fPage2 = page2;
        fPage3 = page3;

        setTitle("Arquillian JUnit Test Case");
        setDescription("Select the name of the new Arquillian JUnit test case.");

        String[] buttonNames = new String[] {
                /* IDX_SETUP_CLASS */ WizardMessages.NewTestCaseWizardPageOne_methodStub_setUpBeforeClass,
                /* IDX_TEARDOWN_CLASS */ WizardMessages.NewTestCaseWizardPageOne_methodStub_tearDownAfterClass,
                /* IDX_SETUP */ WizardMessages.NewTestCaseWizardPageOne_methodStub_setUp,
                /* IDX_TEARDOWN */ WizardMessages.NewTestCaseWizardPageOne_methodStub_tearDown,
                /* IDX_DEPLOYMENT */ "createDeployment()" };
        enableCommentControl(true);

        fMethodStubsButtons = new MethodStubsSelectionButtonGroup(SWT.CHECK, buttonNames, 2) {
            /* (non-Javadoc)
             * @see org.eclipse.jdt.internal.junit.wizards.MethodStubsSelectionButtonGroup#doWidgetSelected(org.eclipse.swt.events.SelectionEvent)         
             */
            @Override
            protected void doWidgetSelected(SelectionEvent e) {
                super.doWidgetSelected(e);
                saveWidgetValues();
                getContainer().updateButtons();
            }
        };
        fMethodStubsButtons.setLabelText(WizardMessages.NewTestCaseWizardPageOne_method_Stub_label);

        fClassToTestCompletionProcessor = new JavaTypeCompletionProcessor(false, false, true);

        fClassUnderTestStatus = new JUnitStatus();

        fClassUnderTestText = ""; //$NON-NLS-1$
    }

    /**
     * Initialized the page with the current selection
     * @param selection The selection
     */
    public void init(IStructuredSelection selection) {
        IJavaElement element = getInitialJavaElement(selection);

        initContainerPage(element);
        initTypePage(element);
        // put default class to test
        if (element != null) {
            IType classToTest = null;
            // evaluate the enclosing type
            IType typeInCompUnit = (IType) element.getAncestor(IJavaElement.TYPE);
            if (typeInCompUnit != null) {
                if (typeInCompUnit.getCompilationUnit() != null) {
                    classToTest = typeInCompUnit;
                }
            } else {
                ICompilationUnit cu = (ICompilationUnit) element.getAncestor(IJavaElement.COMPILATION_UNIT);
                if (cu != null)
                    classToTest = cu.findPrimaryType();
                else {
                    if (element instanceof IClassFile) {
                        try {
                            IClassFile cf = (IClassFile) element;
                            if (cf.isStructureKnown())
                                classToTest = cf.getType();
                        } catch (JavaModelException e) {
                            ArquillianUIActivator.log(e);
                        }
                    }
                }
            }
            if (classToTest != null) {
                try {
                    if (!CoreTestSearchEngine.isTestImplementor(classToTest)) {
                        setClassUnderTest(classToTest.getFullyQualifiedName('.'));
                    }
                } catch (JavaModelException e) {
                    ArquillianUIActivator.log(e);
                }
            }
        }

        restoreWidgetValues();
        updateStatus(getStatusList());
    }

    /**
     * Returns whether the super class name is one of the default super class names.
     * 
     * @return <code>true</code> if the super class name is one of the default super class names,
     *         <code>false</code> otherwise
     * @since 3.7
     */
    private boolean isDefaultSuperClass() {
        String superClass = getSuperClass();
        return superClass.equals("java.lang.Object"); //$NON-NLS-1$
    }

    /* (non-Javadoc)
     * @see org.eclipse.jdt.ui.wizards.NewContainerWizardPage#handleFieldChanged(String)
     */
    @Override
    protected void handleFieldChanged(String fieldName) {
        super.handleFieldChanged(fieldName);
        if (fieldName.equals(CONTAINER)) {
            fClassUnderTestStatus = classUnderTestChanged();
            if (fClassUnderTestButton != null && !fClassUnderTestButton.isDisposed()) {
                fClassUnderTestButton.setEnabled(getPackageFragmentRoot() != null);
            }

            updateBuildPathMessage();
        }
        updateStatus(getStatusList());
    }

    /**
     * Returns all status to be consider for the validation. Clients can override.
     * @return The list of status to consider for the validation.
     */
    protected IStatus[] getStatusList() {
        return new IStatus[] { fContainerStatus, fPackageStatus, fTypeNameStatus, fClassUnderTestStatus,
                fModifierStatus, fSuperClassStatus };
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
     */
    public void createControl(Composite parent) {
        initializeDialogUnits(parent);

        Composite composite = new Composite(parent, SWT.NONE);

        int nColumns = 4;

        GridLayout layout = new GridLayout();
        layout.numColumns = nColumns;
        composite.setLayout(layout);

        createContainerControls(composite, nColumns);
        createPackageControls(composite, nColumns);
        createSeparator(composite, nColumns);
        createTypeNameControls(composite, nColumns);
        createSuperClassControls(composite, nColumns);
        createMethodStubSelectionControls(composite, nColumns);
        createCommentControls(composite, nColumns);
        createSeparator(composite, nColumns);
        createClassUnderTestControls(composite, nColumns);
        createBuildPathConfigureControls(composite, nColumns);

        setControl(composite);

        //set default and focus
        String classUnderTest = getClassUnderTestText();
        if (classUnderTest.length() > 0) {
            setTypeName(Signature.getSimpleName(classUnderTest) + TEST_SUFFIX, true);
        }

        Dialog.applyDialogFont(composite);
        PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IJUnitHelpContextIds.NEW_TESTCASE_WIZARD_PAGE);

        setFocus();
    }

    /**
     * Creates the controls for the method stub selection buttons. Expects a <code>GridLayout</code> with
     * at least 3 columns.
     *
     * @param composite the parent composite
     * @param nColumns number of columns to span
     */
    protected void createMethodStubSelectionControls(Composite composite, int nColumns) {
        LayoutUtil.setHorizontalSpan(fMethodStubsButtons.getLabelControl(composite), nColumns);
        LayoutUtil.createEmptySpace(composite, 1);
        LayoutUtil.setHorizontalSpan(fMethodStubsButtons.getSelectionButtonsGroup(composite), nColumns - 1);
    }

    /**
     * Creates the controls for the 'class under test' field. Expects a <code>GridLayout</code> with
     * at least 3 columns.
     *
     * @param composite the parent composite
     * @param nColumns number of columns to span
     */
    protected void createClassUnderTestControls(Composite composite, int nColumns) {
        Label classUnderTestLabel = new Label(composite, SWT.LEFT | SWT.WRAP);
        classUnderTestLabel.setFont(composite.getFont());
        classUnderTestLabel.setText(WizardMessages.NewTestCaseWizardPageOne_class_to_test_label);
        classUnderTestLabel.setLayoutData(new GridData());

        fClassUnderTestControl = new Text(composite, SWT.SINGLE | SWT.BORDER);
        fClassUnderTestControl.setEnabled(true);
        fClassUnderTestControl.setFont(composite.getFont());
        fClassUnderTestControl.setText(fClassUnderTestText);
        fClassUnderTestControl.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent e) {
                internalSetClassUnderText(((Text) e.widget).getText());
            }
        });
        GridData gd = new GridData();
        gd.horizontalAlignment = GridData.FILL;
        gd.grabExcessHorizontalSpace = true;
        gd.horizontalSpan = nColumns - 2;
        fClassUnderTestControl.setLayoutData(gd);

        fClassUnderTestButton = new Button(composite, SWT.PUSH);
        fClassUnderTestButton.setText(WizardMessages.NewTestCaseWizardPageOne_class_to_test_browse);
        fClassUnderTestButton.setEnabled(getPackageFragmentRoot() != null);
        fClassUnderTestButton.addSelectionListener(new SelectionListener() {
            public void widgetDefaultSelected(SelectionEvent e) {
                classToTestButtonPressed();
            }

            public void widgetSelected(SelectionEvent e) {
                classToTestButtonPressed();
            }
        });
        gd = new GridData();
        gd.horizontalAlignment = GridData.FILL;
        gd.grabExcessHorizontalSpace = false;
        gd.horizontalSpan = 1;
        gd.widthHint = LayoutUtil.getButtonWidthHint(fClassUnderTestButton);
        fClassUnderTestButton.setLayoutData(gd);

        ControlContentAssistHelper.createTextContentAssistant(fClassUnderTestControl,
                fClassToTestCompletionProcessor);
    }

    /**
     * Creates the controls for the JUnit 4 toggle control. Expects a <code>GridLayout</code> with
     * at least 3 columns.
     *
     * @param composite the parent composite
     * @param nColumns number of columns to span
     *
     * @since 3.2
     */
    protected void createBuildPathConfigureControls(Composite composite, int nColumns) {
        Composite inner = new Composite(composite, SWT.NONE);
        inner.setLayoutData(new GridData(GridData.FILL, GridData.FILL, false, false, nColumns, 1));
        GridLayout layout = new GridLayout(2, false);
        layout.marginWidth = 0;
        layout.marginHeight = 0;
        inner.setLayout(layout);

        fImage = new Label(inner, SWT.NONE);
        fImage.setImage(JFaceResources.getImage(Dialog.DLG_IMG_MESSAGE_WARNING));
        fImage.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, false, false, 1, 1));

        fLink = new Link(inner, SWT.WRAP);
        fLink.setText("\n\n"); //$NON-NLS-1$
        fLink.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                performBuildpathConfiguration(e.text);
            }
        });
        GridData gd = new GridData(GridData.FILL, GridData.BEGINNING, true, false, 1, 1);
        gd.widthHint = convertWidthInCharsToPixels(60);
        fLink.setLayoutData(gd);
        updateBuildPathMessage();
    }

    private void performBuildpathConfiguration(Object data) {
        IPackageFragmentRoot root = getPackageFragmentRoot();
        if (root == null) {
            return; // should not happen. Link shouldn't be visible
        }
        IJavaProject javaProject = root.getJavaProject();

        if ("a3".equals(data)) { // add and configure JUnit 3 //$NON-NLS-1$
            String id = BUILD_PATH_PAGE_ID;
            Map<String, Object> input = new HashMap<String, Object>();
            IClasspathEntry newEntry = BuildPathSupport.getJUnit3ClasspathEntry();
            input.put(BUILD_PATH_KEY_ADD_ENTRY, newEntry);
            input.put(BUILD_PATH_BLOCK, Boolean.TRUE);
            PreferencesUtil.createPropertyDialogOn(getShell(), javaProject, id, new String[] { id }, input).open();
        } else if ("a4".equals(data)) { // add and configure JUnit 4 //$NON-NLS-1$
            String id = BUILD_PATH_PAGE_ID;
            Map<String, Object> input = new HashMap<String, Object>();
            IClasspathEntry newEntry = BuildPathSupport.getJUnit4ClasspathEntry();
            input.put(BUILD_PATH_KEY_ADD_ENTRY, newEntry);
            input.put(BUILD_PATH_BLOCK, Boolean.TRUE);
            PreferencesUtil.createPropertyDialogOn(getShell(), javaProject, id, new String[] { id }, input).open();
        } else if ("b".equals(data)) { // open build path //$NON-NLS-1$
            String id = BUILD_PATH_PAGE_ID;
            Map<String, Object> input = new HashMap<String, Object>();
            input.put(BUILD_PATH_BLOCK, Boolean.TRUE);
            PreferencesUtil.createPropertyDialogOn(getShell(), javaProject, id, new String[] { id }, input).open();
        } else if ("c".equals(data)) { // open compliance //$NON-NLS-1$
            String buildPath = BUILD_PATH_PAGE_ID;
            String complianceId = COMPLIANCE_PAGE_ID;
            Map<String, Boolean> input = new HashMap<String, Boolean>();
            input.put(BUILD_PATH_BLOCK, Boolean.TRUE);
            input.put(KEY_NO_LINK, Boolean.TRUE);
            PreferencesUtil.createPropertyDialogOn(getShell(), javaProject, complianceId,
                    new String[] { buildPath, complianceId }, data).open();
        }

        updateBuildPathMessage();
    }

    private void updateBuildPathMessage() {
        if (fLink == null || fLink.isDisposed()) {
            return;
        }

        String message = null;
        IPackageFragmentRoot root = getPackageFragmentRoot();
        if (root != null) {
            IJavaProject project = root.getJavaProject();
            if (project.exists()) {
                if (!JUnitStubUtility.is50OrHigher(project)) {
                    message = WizardMessages.NewTestCaseWizardPageOne_linkedtext_java5required;
                }
            }
        }
        fLink.setVisible(message != null);
        fImage.setVisible(message != null);

        if (message != null) {
            fLink.setText(message);
        }
    }

    private void classToTestButtonPressed() {
        IType type = chooseClassToTestType();
        if (type != null) {
            setClassUnderTest(type.getFullyQualifiedName('.'));
        }
    }

    private IType chooseClassToTestType() {
        IPackageFragmentRoot root = getPackageFragmentRoot();
        if (root == null)
            return null;

        IJavaElement[] elements = new IJavaElement[] { root.getJavaProject() };
        IJavaSearchScope scope = SearchEngine.createJavaSearchScope(elements);

        try {
            SelectionDialog dialog = JavaUI.createTypeDialog(getShell(), getWizard().getContainer(), scope,
                    IJavaElementSearchConstants.CONSIDER_CLASSES_AND_ENUMS, false, getClassUnderTestText());
            dialog.setTitle(WizardMessages.NewTestCaseWizardPageOne_class_to_test_dialog_title);
            dialog.setMessage(WizardMessages.NewTestCaseWizardPageOne_class_to_test_dialog_message);
            if (dialog.open() == Window.OK) {
                Object[] resultArray = dialog.getResult();
                if (resultArray != null && resultArray.length > 0)
                    return (IType) resultArray[0];
            }
        } catch (JavaModelException e) {
            ArquillianUIActivator.log(e);
        }
        return null;
    }

    /* (non-Javadoc)
     * @see org.eclipse.jdt.ui.wizards.NewTypeWizardPage#packageChanged()
     */
    @Override
    protected IStatus packageChanged() {
        IStatus status = super.packageChanged();
        fClassToTestCompletionProcessor.setPackageFragment(getPackageFragment());
        return status;
    }

    /**
     * Hook method that gets called when the class under test has changed. The method class under test
     * returns the status of the validation.
     * <p>
     * Subclasses may extend this method to perform their own validation.
     * </p>
     *
     * @return the status of the validation
     */
    protected IStatus classUnderTestChanged() {
        JUnitStatus status = new JUnitStatus();

        fClassUnderTest = null;
        fPage2.setClassUnderTest(null);
        fPage3.setClassUnderTest(null);

        IPackageFragmentRoot root = getPackageFragmentRoot();
        if (root == null) {
            return status;
        }

        String classToTestName = getClassUnderTestText();
        if (classToTestName.length() == 0) {
            return status;
        }

        IStatus val = JavaConventionsUtil.validateJavaTypeName(classToTestName, root);
        if (val.getSeverity() == IStatus.ERROR) {
            status.setError(WizardMessages.NewTestCaseWizardPageOne_error_class_to_test_not_valid);
            return status;
        }

        IPackageFragment pack = getPackageFragment(); // can be null
        try {
            IType type = resolveClassNameToType(root.getJavaProject(), pack, classToTestName);
            if (type == null) {
                status.setError(WizardMessages.NewTestCaseWizardPageOne_error_class_to_test_not_exist);
                return status;
            }
            if (type.isInterface()) {
                status.setWarning(
                        Messages.format(WizardMessages.NewTestCaseWizardPageOne_warning_class_to_test_is_interface,
                                BasicElementLabels.getJavaElementName(classToTestName)));
            }

            if (pack != null && !JUnitStubUtility.isVisible(type, pack)) {
                status.setWarning(
                        Messages.format(WizardMessages.NewTestCaseWizardPageOne_warning_class_to_test_not_visible,
                                BasicElementLabels.getJavaElementName(classToTestName)));
            }
            fClassUnderTest = type;
            fPage2.setClassUnderTest(fClassUnderTest);
            fPage3.setClassUnderTest(fClassUnderTest);
        } catch (JavaModelException e) {
            status.setError(WizardMessages.NewTestCaseWizardPageOne_error_class_to_test_not_valid);
        }
        return status;
    }

    /**
     * Returns the content of the class to test text field.
     *
     * @return the name of the class to test
     */
    public String getClassUnderTestText() {
        return fClassUnderTestText;
    }

    /**
     * Returns the class to be tested.
     *
     *    @return the class under test or <code>null</code> if the entered values are not valid
     */
    public IType getClassUnderTest() {
        return fClassUnderTest;
    }

    /**
     * Sets the name of the class under test.
     *
     * @param name The name to set
     */
    public void setClassUnderTest(String name) {
        if (fClassUnderTestControl != null && !fClassUnderTestControl.isDisposed()) {
            fClassUnderTestControl.setText(name);
        }
        internalSetClassUnderText(name);
    }

    private void internalSetClassUnderText(String name) {
        fClassUnderTestText = name;
        fClassUnderTestStatus = classUnderTestChanged();
        handleFieldChanged(CLASS_UNDER_TEST);
    }

    /* (non-Javadoc)
     * @see org.eclipse.jdt.ui.wizards.NewTypeWizardPage#createTypeMembers(org.eclipse.jdt.core.IType, org.eclipse.jdt.ui.wizards.NewTypeWizardPage.ImportsManager, org.eclipse.core.runtime.IProgressMonitor)
     */
    @Override
    protected void createTypeMembers(IType type, ImportsManager imports, IProgressMonitor monitor)
            throws CoreException {
        if (fMethodStubsButtons.isSelected(IDX_DEPLOYMENT)) {
            String delimiter = getLineDelimiter();
            NewArquillianJUnitTestCaseDeploymentPage deploymentPage = (NewArquillianJUnitTestCaseDeploymentPage) getWizard()
                    .getPage(
                            NewArquillianJUnitTestCaseDeploymentPage.ORG_JBOSS_TOOLS_ARQUILLIAN_UI_DEPLOYMENT_PAGE);
            ArquillianUIUtil.createDeploymentMethod(null, type, imports, isAddComments(), delimiter, deploymentPage,
                    null, false);
        }

        if (fMethodStubsButtons.isSelected(IDX_SETUP_CLASS)) {
            createSetUpClass(type, imports);
        }

        if (fMethodStubsButtons.isSelected(IDX_TEARDOWN_CLASS)) {
            createTearDownClass(type, imports);
        }

        if (fMethodStubsButtons.isSelected(IDX_SETUP)) {
            createSetUp(type, imports);
        }

        if (fMethodStubsButtons.isSelected(IDX_TEARDOWN)) {
            createTearDown(type, imports);
        }

        createTestMethodStubs(type, imports);

        imports.addStaticImport("org.junit.Assert", "*", false); //$NON-NLS-1$ //$NON-NLS-2$

        imports.addImport(ORG_JUNIT_RUNNER_RUNWITH);
        imports.addImport("org.jboss.arquillian.junit.Arquillian");

        ISourceRange range = type.getSourceRange();
        IBuffer buf = type.getCompilationUnit().getBuffer();

        char[] source = buf.getCharacters();
        IScanner scanner = ToolFactory.createScanner(false, false, false, JavaCore.VERSION_1_5);
        scanner.setSource(source);
        int offset = range.getOffset();

        try {
            int token = scanner.getNextToken();
            while (token != ITerminalSymbols.TokenNameEOF) {
                if (token == ITerminalSymbols.TokenNamepublic) {
                    offset = scanner.getCurrentTokenStartPosition();
                    break;
                }
                token = scanner.getNextToken();
            }
        } catch (InvalidInputException e) {
            ArquillianUIActivator.log(e);
        }
        StringBuffer sb = new StringBuffer();

        sb.append("@RunWith(Arquillian.class)").append(getPackageFragment().findRecommendedLineSeparator());

        buf.replace(offset, 0, sb.toString());
    }

    private IMethod findInHierarchy(IType type, String methodName) throws JavaModelException {
        ITypeHierarchy typeHierarchy = null;
        IType[] superTypes = null;
        if (type.exists()) {
            typeHierarchy = type.newSupertypeHierarchy(null);
            superTypes = typeHierarchy.getAllSuperclasses(type);
            for (IType superType : superTypes) {
                if (superType.exists()) {
                    IMethod testMethod = superType.getMethod(methodName, new String[] {});
                    if (testMethod.exists()) {
                        return testMethod;
                    }
                }
            }
        }
        return null;
    }

    private void createSetupStubs(IType type, String methodName, boolean isStatic, String annotationType,
            ImportsManager imports) throws CoreException {
        String content = null;
        IMethod methodTemplate = findInHierarchy(type, methodName);
        String annotation = '@' + imports.addImport(annotationType);

        GenStubSettings settings = JUnitStubUtility.getCodeGenerationSettings(type.getJavaProject());
        settings.createComments = isAddComments();

        if (methodTemplate != null) {
            settings.callSuper = true;
            settings.methodOverwrites = true;
            content = JUnitStubUtility.genStub(type.getCompilationUnit(), getTypeName(), methodTemplate, settings,
                    annotation, imports);
        } else {
            final String delimiter = getLineDelimiter();
            StringBuffer buffer = new StringBuffer();
            if (settings.createComments) {
                String[] excSignature = { Signature.createTypeSignature("java.lang.Exception", true) }; //$NON-NLS-1$
                String comment = CodeGeneration.getMethodComment(type.getCompilationUnit(), type.getElementName(),
                        methodName, new String[0], excSignature, Signature.SIG_VOID, null, delimiter);
                if (comment != null) {
                    buffer.append(comment);
                }
            }
            if (annotation != null) {
                buffer.append(annotation).append(delimiter);
            }

            buffer.append("public "); //$NON-NLS-1$

            if (isStatic) {
                buffer.append("static "); //$NON-NLS-1$
            }
            buffer.append("void "); //$NON-NLS-1$
            buffer.append(methodName);
            buffer.append("() throws "); //$NON-NLS-1$
            buffer.append(imports.addImport("java.lang.Exception")); //$NON-NLS-1$
            buffer.append(" {}"); //$NON-NLS-1$
            buffer.append(delimiter);
            content = buffer.toString();
        }
        type.createMethod(content, null, false, null);
    }

    private void createSetUp(IType type, ImportsManager imports) throws CoreException {
        createSetupStubs(type, "setUp", false, "org.junit.Before", imports); //$NON-NLS-1$ //$NON-NLS-2$
    }

    private void createTearDown(IType type, ImportsManager imports) throws CoreException {
        createSetupStubs(type, "tearDown", false, "org.junit.After", imports); //$NON-NLS-1$ //$NON-NLS-2$
    }

    private void createSetUpClass(IType type, ImportsManager imports) throws CoreException {
        createSetupStubs(type, "setUpBeforeClass", true, "org.junit.BeforeClass", imports); //$NON-NLS-1$ //$NON-NLS-2$
    }

    private void createTearDownClass(IType type, ImportsManager imports) throws CoreException {
        createSetupStubs(type, "tearDownAfterClass", true, "org.junit.AfterClass", imports); //$NON-NLS-1$ //$NON-NLS-2$
    }

    private void createTestMethodStubs(IType type, ImportsManager imports) throws CoreException {
        IMethod[] methods = fPage2.getCheckedMethods();
        if (methods.length == 0) {
            List<String> names = new ArrayList<String>();
            createTestMethod(type, imports, null, null, names);

            return;
        }
        /* find overloaded methods */
        IMethod[] allMethodsArray = fPage2.getAllMethods();
        List<IMethod> allMethods = new ArrayList<IMethod>();
        allMethods.addAll(Arrays.asList(allMethodsArray));
        List<IMethod> overloadedMethods = getOverloadedMethods(allMethods);

        /* used when for example both sum and Sum methods are present. Then
         * sum -> testSum
         * Sum -> testSum1
         */
        List<String> names = new ArrayList<String>();
        for (IMethod method : methods) {
            createTestMethod(type, imports, method, overloadedMethods, names);
        }
    }

    /**
     * Creates a test method.
     * 
     * @param type the type to create the method
     * @param imports the imports manager
     * @param method the method or <code>null</code>
     * @param overloadedMethods the list of overloaded methods or <code>null</code>
     * @param names the list of method names
     * @throws CoreException if the element could not be created
     * @since 3.7
     */
    private void createTestMethod(IType type, ImportsManager imports, IMethod method,
            List<IMethod> overloadedMethods, List<String> names) throws CoreException {
        StringBuffer buffer = new StringBuffer();
        StringBuffer name;
        if (method != null) {
            String elementName = method.getElementName();
            name = new StringBuffer(PREFIX).append(Character.toUpperCase(elementName.charAt(0)))
                    .append(elementName.substring(1));
            final boolean contains = overloadedMethods.contains(method);
            if (contains)
                appendParameterNamesToMethodName(name, method.getParameterTypes());
        } else {
            name = new StringBuffer(PREFIX);
        }

        replaceIllegalCharacters(name);
        /* void foo(java.lang.StringBuffer sb) {}
         *  void foo(mypackage1.StringBuffer sb) {}
         *  void foo(mypackage2.StringBuffer sb) {}
         * ->
         *  testFooStringBuffer()
         *  testFooStringBuffer1()
         *  testFooStringBuffer2()
         */
        String testName = name.toString();
        if (names.contains(testName)) {
            int suffix = 1;
            while (names.contains(testName + Integer.toString(suffix)))
                suffix++;
            name.append(Integer.toString(suffix));
        }
        testName = name.toString();
        names.add(testName);

        if (isAddComments() && method != null) {
            appendMethodComment(buffer, method);
        }

        ISourceRange typeSourceRange = type.getSourceRange();
        int pos = typeSourceRange.getOffset() + typeSourceRange.getLength() - 1;
        if ("Test".equals(type.getElementName())) {
            buffer.append('@').append(JUNIT4_ANNOTATION_NAME).append(getLineDelimiter());
        } else {
            buffer.append('@').append(imports.addImport(JUNIT4_ANNOTATION_NAME, pos)).append(getLineDelimiter());
        }

        buffer.append("public ");//$NON-NLS-1$
        if (fPage2.getCreateFinalMethodStubsButtonSelection())
            buffer.append("final "); //$NON-NLS-1$
        buffer.append("void ");//$NON-NLS-1$
        buffer.append(testName);
        buffer.append("()");//$NON-NLS-1$
        appendTestMethodBody(buffer, type.getCompilationUnit());
        type.createMethod(buffer.toString(), null, false, null);
    }

    private void replaceIllegalCharacters(StringBuffer buffer) {
        char character = 0;
        for (int index = buffer.length() - 1; index >= 0; index--) {
            character = buffer.charAt(index);
            if (Character.isWhitespace(character))
                buffer.deleteCharAt(index);
            else if (character == '<')
                buffer.replace(index, index + 1, OF_TAG);
            else if (character == '?')
                buffer.replace(index, index + 1, QUESTION_MARK_TAG);
            else if (!Character.isJavaIdentifierPart(character)) {
                // Check for surrogates
                if (!UTF16.isSurrogate(character)) {
                    /*
                     * XXX: Here we should create the code point and test whether
                     * it is a Java identifier part. Currently this is not possible
                     * because java.lang.Character in 1.4 does not support surrogates
                     * and because com.ibm.icu.lang.UCharacter.isJavaIdentifierPart(int)
                     * is not correctly implemented.
                     */
                    buffer.deleteCharAt(index);
                }

            }
        }
    }

    private String getLineDelimiter() throws JavaModelException {
        IType classToTest = getClassUnderTest();

        if (classToTest != null && classToTest.exists() && classToTest.getCompilationUnit() != null)
            return classToTest.getCompilationUnit().findRecommendedLineSeparator();

        return getPackageFragment().findRecommendedLineSeparator();
    }

    private void appendTestMethodBody(StringBuffer buffer, ICompilationUnit targetCu) throws CoreException {
        final String delimiter = getLineDelimiter();
        buffer.append('{').append(delimiter);
        String todoTask = ""; //$NON-NLS-1$
        if (fPage2.isCreateTasks()) {
            String todoTaskTag = JUnitStubUtility.getTodoTaskTag(targetCu.getJavaProject());
            if (todoTaskTag != null) {
                todoTask = " // " + todoTaskTag; //$NON-NLS-1$
            }
        }
        String message = WizardMessages.NewTestCaseWizardPageOne_not_yet_implemented_string;
        buffer.append(Messages.format("fail(\"{0}\");", message)).append(todoTask).append(delimiter); //$NON-NLS-1$

        buffer.append('}').append(delimiter);
    }

    private void appendParameterNamesToMethodName(StringBuffer buffer, String[] parameters) {
        for (String parameter : parameters) {
            final StringBuffer buf = new StringBuffer(
                    Signature.getSimpleName(Signature.toString(Signature.getElementType(parameter))));
            final char character = buf.charAt(0);
            if (buf.length() > 0 && !Character.isUpperCase(character))
                buf.setCharAt(0, Character.toUpperCase(character));
            buffer.append(buf.toString());
            for (int j = 0, arrayCount = Signature.getArrayCount(parameter); j < arrayCount; j++) {
                buffer.append("Array"); //$NON-NLS-1$
            }
        }
    }

    private void appendMethodComment(StringBuffer buffer, IMethod method) throws JavaModelException {
        final String delimiter = getLineDelimiter();
        final StringBuffer buf = new StringBuffer("{@link "); //$NON-NLS-1$
        JavaElementLabels.getTypeLabel(method.getDeclaringType(), JavaElementLabels.T_FULLY_QUALIFIED, buf);
        buf.append('#');
        buf.append(method.getElementName());
        buf.append('(');
        String[] paramTypes = JUnitStubUtility.getParameterTypeNamesForSeeTag(method);
        for (int i = 0; i < paramTypes.length; i++) {
            if (i != 0) {
                buf.append(", "); //$NON-NLS-1$
            }
            buf.append(paramTypes[i]);

        }
        buf.append(')');
        buf.append('}');

        buffer.append("/**");//$NON-NLS-1$
        buffer.append(delimiter);
        buffer.append(" * ");//$NON-NLS-1$
        buffer.append(
                Messages.format(WizardMessages.NewTestCaseWizardPageOne_comment_class_to_test, buf.toString()));
        buffer.append(delimiter);
        buffer.append(" */");//$NON-NLS-1$
        buffer.append(delimiter);
    }

    private List<IMethod> getOverloadedMethods(List<IMethod> allMethods) {
        List<IMethod> overloadedMethods = new ArrayList<IMethod>();
        for (int i = 0; i < allMethods.size(); i++) {
            IMethod current = allMethods.get(i);
            String currentName = current.getElementName();
            boolean currentAdded = false;
            for (ListIterator<IMethod> iter = allMethods.listIterator(i + 1); iter.hasNext();) {
                IMethod iterMethod = iter.next();
                if (iterMethod.getElementName().equals(currentName)) {
                    //method is overloaded
                    if (!currentAdded) {
                        overloadedMethods.add(current);
                        currentAdded = true;
                    }
                    overloadedMethods.add(iterMethod);
                    iter.remove();
                }
            }
        }
        return overloadedMethods;
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.IDialogPage#setVisible(boolean)
     */
    @Override
    public void setVisible(boolean visible) {
        super.setVisible(visible);
        if (!visible) {
            saveWidgetValues();
        }

        //if (visible) setFocus();
    }

    /**
     * The method is called when the container has changed to validate if the project
     * is suited for the JUnit test class. Clients can override to modify or remove that validation.
     *
     * @return the status of the validation
     */
    protected IStatus validateIfJUnitProject() {
        JUnitStatus status = new JUnitStatus();
        IPackageFragmentRoot root = getPackageFragmentRoot();
        if (root != null) {
            try {
                IJavaProject project = root.getJavaProject();
                if (project.exists()) {
                    if (!JUnitStubUtility.is50OrHigher(project)) {
                        status.setError(WizardMessages.NewTestCaseWizardPageOne_error_java5required);
                        return status;
                    }
                    try {
                        if (!project.getProject().hasNature(ArquillianNature.ARQUILLIAN_NATURE_ID)) {
                            status.setWarning("The project doesn't have the Arquillian nature");
                            return status;
                        }
                    } catch (CoreException e) {
                        ArquillianUIActivator.log(e);
                    }
                    if (project.findType(JUNIT4_ANNOTATION_NAME) == null) {
                        status.setWarning(WizardMessages.NewTestCaseWizardPageOne__error_junit4NotOnbuildpath);
                        return status;
                    }
                }
            } catch (JavaModelException e) {
            }
        }
        return status;
    }

    /* (non-Javadoc)
     * @see org.eclipse.jdt.ui.wizards.NewTypeWizardPage#superClassChanged()
     */
    @Override
    protected IStatus superClassChanged() {
        IStatus stat = super.superClassChanged();
        if (stat.getSeverity() != IStatus.OK)
            return stat;
        String superClassName = getSuperClass();
        JUnitStatus status = new JUnitStatus();
        if (superClassName == null || superClassName.trim().equals("")) { //$NON-NLS-1$
            status.setError(WizardMessages.NewTestCaseWizardPageOne_error_superclass_empty);
            return status;
        }
        if (superClassName.equals("java.lang.Object")) //$NON-NLS-1$
            return status;
        if (getPackageFragmentRoot() != null) {
            try {
                IType type = resolveClassNameToType(getPackageFragmentRoot().getJavaProject(), getPackageFragment(),
                        superClassName);
                if (type == null) {
                    status.setWarning(WizardMessages.NewTestCaseWizardPageOne_error_superclass_not_exist);
                    return status;
                }
                if (type.isInterface()) {
                    status.setError(WizardMessages.NewTestCaseWizardPageOne_error_superclass_is_interface);
                    return status;
                }

            } catch (JavaModelException e) {
                ArquillianUIActivator.log(e);
            }
        }
        return status;
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.wizard.IWizardPage#canFlipToNextPage()
     */
    @Override
    public boolean canFlipToNextPage() {
        return super.canFlipToNextPage()
                && (getClassUnderTest() != null || fMethodStubsButtons.isSelected(IDX_DEPLOYMENT));
    }

    @Override
    public IWizardPage getNextPage() {
        if (getClassUnderTest() != null) {
            super.getNextPage();
        } else if (fMethodStubsButtons.isSelected(IDX_DEPLOYMENT)) {
            IWizard wizard = getWizard();
            if (wizard instanceof NewArquillianJUnitTestWizard) {
                return ((NewArquillianJUnitTestWizard) wizard).getNewArquillianJUnitTestCaseDeploymentPage();
            }
        }
        return super.getNextPage();
    }

    private IType resolveClassNameToType(IJavaProject jproject, IPackageFragment pack, String classToTestName)
            throws JavaModelException {
        if (!jproject.exists()) {
            return null;
        }

        IType type = jproject.findType(classToTestName);

        // search in current package
        if (type == null && pack != null && !pack.isDefaultPackage()) {
            type = jproject.findType(pack.getElementName(), classToTestName);
        }

        // search in java.lang
        if (type == null) {
            type = jproject.findType("java.lang", classToTestName); //$NON-NLS-1$
        }
        return type;
    }

    /**
     *   Use the dialog store to restore widget values to the values that they held
     *   last time this wizard was used to completion
     */
    private void restoreWidgetValues() {
        IDialogSettings settings = getDialogSettings();
        if (settings != null) {
            fMethodStubsButtons.setSelection(IDX_SETUP, settings.getBoolean(STORE_SETUP));
            fMethodStubsButtons.setSelection(IDX_TEARDOWN, settings.getBoolean(STORE_TEARDOWN));
            fMethodStubsButtons.setSelection(IDX_SETUP_CLASS, settings.getBoolean(STORE_SETUP_CLASS));
            fMethodStubsButtons.setSelection(IDX_TEARDOWN_CLASS, settings.getBoolean(STORE_TEARDOWN_CLASS));
            if (settings.get(STORE_DEPLOYMENT) == null) {
                fMethodStubsButtons.setSelection(IDX_DEPLOYMENT, true);
            } else {
                fMethodStubsButtons.setSelection(IDX_DEPLOYMENT, settings.getBoolean(STORE_DEPLOYMENT));
            }
        } else {
            fMethodStubsButtons.setSelection(IDX_SETUP, false); //setUp
            fMethodStubsButtons.setSelection(IDX_TEARDOWN, false); //tearDown
            fMethodStubsButtons.setSelection(IDX_SETUP_CLASS, false); //setUpBeforeClass
            fMethodStubsButtons.setSelection(IDX_TEARDOWN_CLASS, false); //setUpAfterClass
            fMethodStubsButtons.setSelection(IDX_DEPLOYMENT, true); //constructor
        }
    }

    /**
     *    Since Finish was pressed, write widget values to the dialog store so that they
     *   will persist into the next invocation of this wizard page
     */
    private void saveWidgetValues() {
        IDialogSettings settings = getDialogSettings();
        if (settings != null) {
            settings.put(STORE_SETUP, fMethodStubsButtons.isSelected(IDX_SETUP));
            settings.put(STORE_TEARDOWN, fMethodStubsButtons.isSelected(IDX_TEARDOWN));
            settings.put(STORE_SETUP_CLASS, fMethodStubsButtons.isSelected(IDX_SETUP_CLASS));
            settings.put(STORE_TEARDOWN_CLASS, fMethodStubsButtons.isSelected(IDX_TEARDOWN_CLASS));
            settings.put(STORE_DEPLOYMENT, fMethodStubsButtons.isSelected(IDX_DEPLOYMENT));
        }
    }

    /**
     * Returns the default value for the super class field.
     * 
     * @return the default value for the super class field
     * @since 3.7
     */
    private String getDefaultSuperClassName() {
        return "java.lang.Object"; //$NON-NLS-1$
    }

    public boolean isGenerateDeploymentMethod() {
        return fMethodStubsButtons.isSelected(IDX_DEPLOYMENT);
    }
}