org.jnario.spec.ui.wizards.NewSpecWizardPageOne.java Source code

Java tutorial

Introduction

Here is the source code for org.jnario.spec.ui.wizards.NewSpecWizardPageOne.java

Source

/*******************************************************************************
 * Copyright (c) 2012 BMW Car IT 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
 *******************************************************************************/
package org.jnario.spec.ui.wizards;

import static com.google.common.base.Strings.isNullOrEmpty;

import java.io.ByteArrayInputStream;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
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.JUnitCorePlugin;
import org.eclipse.jdt.internal.junit.Messages;
import org.eclipse.jdt.internal.junit.ui.JUnitPlugin;
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.LayoutUtil;
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.NewTestCaseWizardPageOne;
import org.eclipse.jdt.ui.IJavaElementSearchConstants;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
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.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.dialogs.SelectionDialog;
import org.jnario.ui.wizards.NewJnarioFileWizardPageOne;

/**
 * partially copied from {@link NewTestCaseWizardPageOne}
 */
@SuppressWarnings("restriction")
public class NewSpecWizardPageOne extends NewJnarioFileWizardPageOne {

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

    public final static String CLASS_UNDER_TEST = PAGE_NAME + ".classundertest"; //$NON-NLS-1$

    private NewSpecWizardPageTwo fPage2;

    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;
    private IResource fResource;

    private SpecCreator specUtil;

    public NewSpecWizardPageOne(NewSpecWizardPageTwo page2, SpecCreator specUtil) {
        super(specUtil);
        fPage2 = page2;
        this.specUtil = specUtil;
        setDescription(
                "Select the name of the new Spec file. You have the options to specify\nthe description and/or the class under test.");

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

        fClassUnderTestStatus = new JUnitStatus();

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

    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) {
                            JUnitPlugin.log(e);
                        }
                    }
                }
            }
            if (classToTest != null) {
                try {
                    if (!CoreTestSearchEngine.isTestImplementor(classToTest)) {
                        setClassUnderTest(classToTest.getFullyQualifiedName('.'));
                    }
                } catch (JavaModelException e) {
                    JUnitPlugin.log(e);
                }
            }
        }

        updateStatus(getStatusList());
    }

    /* (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();
        }
        if (fieldName.equals(CLASS_UNDER_TEST)) {
            if (fClassUnderTest != null && isNullOrEmpty(getTypeName())) {
                setTypeName(fClassUnderTest.getElementName(), true);
            }
        }
        updateStatus(getStatusList());
    }

    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);
        createTypeNameControls(composite, nColumns);
        createSeparator(composite, nColumns);
        createDescriptionControls(composite, nColumns);
        createClassUnderTestControls(composite, nColumns);
        //createBuildPathConfigureControls(composite, nColumns);

        setControl(composite);

        //set default and focus
        Dialog.applyDialogFont(composite);

        setFocus();
    }

    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);
    }

    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) {
            JUnitPlugin.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;
    }

    protected IStatus classUnderTestChanged() {
        JUnitStatus status = new JUnitStatus();

        fClassUnderTest = 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);
        } 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);
    }

    /**
     * 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;
                    }
                    if (project.findType(JUnitCorePlugin.JUNIT4_ANNOTATION_NAME) == null) {
                        status.setWarning(WizardMessages.NewTestCaseWizardPageOne__error_junit4NotOnbuildpath);
                        return status;
                    }
                }
            } catch (JavaModelException e) {
            }
        }
        return status;
    }

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

    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;
    }

    public void createType(IProgressMonitor monitor) {
        if (monitor == null) {
            monitor = new NullProgressMonitor();
        }
        if (!getPackageFragment().exists()) {
            try {
                getPackageFragmentRoot().createPackageFragment(getPackageFragment().getElementName(), true,
                        monitor);
            } catch (JavaModelException e) {
                displayError("Could not create package", e.getMessage());
            }
        }
        IResource res = getPackageFragment().getResource();
        IFile specFile = null;
        specFile = ((IFolder) res).getFile(getTypeName() + ".spec"); //$NON-NLS-1$
        try {
            String contents = specUtil.create(getJavaProject(), getDescriptionFieldValue(), getPackageFragment(),
                    getClassUnderTestText(), fPage2.getCheckedMethods(), monitor);
            specFile.create(new ByteArrayInputStream(contents.getBytes()), true, monitor);
            this.fResource = specFile;
        } catch (CoreException e) {
            displayError("Could not create Spec", e.getMessage());
        }
    }

    public IResource getResource() {
        return fResource;
    }

    private void displayError(final String title, final String message) {
        Display.getDefault().syncExec(new Runnable() {
            public void run() {
                MessageDialog.openError(getShell(), title, message);
            }
        });
    }

    @Override
    public void setTypeName(String name, boolean canBeModified) {
        super.setTypeName(name, canBeModified);
        fTypeNameStatus = typeNameChanged();
    }

    @Override
    protected String title() {
        return "Spec";
    }

    @Override
    protected String fileExtension() {
        return "spec";
    }

}