KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > junit > wizards > NewTestSuiteWizardPage


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.junit.wizards;
12
13 import org.eclipse.core.runtime.Assert;
14 import org.eclipse.core.runtime.CoreException;
15 import org.eclipse.core.runtime.IProgressMonitor;
16 import org.eclipse.core.runtime.IStatus;
17 import org.eclipse.core.runtime.SubProgressMonitor;
18
19 import org.eclipse.swt.SWT;
20 import org.eclipse.swt.events.SelectionAdapter;
21 import org.eclipse.swt.events.SelectionEvent;
22 import org.eclipse.swt.layout.GridData;
23 import org.eclipse.swt.layout.GridLayout;
24 import org.eclipse.swt.widgets.Button;
25 import org.eclipse.swt.widgets.Composite;
26 import org.eclipse.swt.widgets.Label;
27
28 import org.eclipse.jface.dialogs.Dialog;
29 import org.eclipse.jface.dialogs.MessageDialog;
30 import org.eclipse.jface.viewers.CheckStateChangedEvent;
31 import org.eclipse.jface.viewers.CheckboxTableViewer;
32 import org.eclipse.jface.viewers.ICheckStateListener;
33 import org.eclipse.jface.viewers.IStructuredSelection;
34
35 import org.eclipse.jface.text.BadLocationException;
36 import org.eclipse.jface.text.Document;
37 import org.eclipse.jface.text.IDocument;
38
39 import org.eclipse.ui.PlatformUI;
40
41 import org.eclipse.jdt.core.ICompilationUnit;
42 import org.eclipse.jdt.core.IJavaElement;
43 import org.eclipse.jdt.core.IJavaProject;
44 import org.eclipse.jdt.core.IMethod;
45 import org.eclipse.jdt.core.IPackageFragment;
46 import org.eclipse.jdt.core.IPackageFragmentRoot;
47 import org.eclipse.jdt.core.ISourceRange;
48 import org.eclipse.jdt.core.IType;
49 import org.eclipse.jdt.core.JavaConventions;
50 import org.eclipse.jdt.core.JavaCore;
51 import org.eclipse.jdt.core.JavaModelException;
52
53 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
54
55 import org.eclipse.jdt.ui.JavaElementLabelProvider;
56 import org.eclipse.jdt.ui.wizards.NewTypeWizardPage;
57
58 import org.eclipse.jdt.internal.junit.Messages;
59 import org.eclipse.jdt.internal.junit.ui.IJUnitHelpContextIds;
60 import org.eclipse.jdt.internal.junit.util.JUnitStatus;
61 import org.eclipse.jdt.internal.junit.util.JUnitStubUtility;
62 import org.eclipse.jdt.internal.junit.util.LayoutUtil;
63 import org.eclipse.jdt.internal.junit.wizards.SuiteClassesContentProvider;
64 import org.eclipse.jdt.internal.junit.wizards.TestSuiteClassListRange;
65 import org.eclipse.jdt.internal.junit.wizards.UpdateTestSuite;
66 import org.eclipse.jdt.internal.junit.wizards.WizardMessages;
67
68 /**
69  * The class <code>NewTestSuiteWizardPage</code> contains controls and validation routines
70  * for the single page in the 'New JUnit TestSuite Wizard'.
71  *
72  * Clients can use the page as-is and add it to their own wizard, or extend it to modify
73  * validation or add and remove controls.
74  *
75  * @since 3.1
76  */

77 public class NewTestSuiteWizardPage extends NewTypeWizardPage {
78     
79     private static final String JavaDoc ALL_TESTS= "AllTests"; //$NON-NLS-1$
80

81     public static final String JavaDoc NON_COMMENT_END_MARKER = "$JUnit-END$"; //$NON-NLS-1$
82

83     public static final String JavaDoc NON_COMMENT_START_MARKER = "$JUnit-BEGIN$"; //$NON-NLS-1$
84

85     public static final String JavaDoc COMMENT_START = "//"; //$NON-NLS-1$
86

87     /**
88      * The string used to mark the beginning of the generated code
89      */

90     public static final String JavaDoc START_MARKER= COMMENT_START + NON_COMMENT_START_MARKER;
91     
92     /**
93      * The string used to mark the end of the generated code
94      */

95     public static final String JavaDoc END_MARKER= COMMENT_START + NON_COMMENT_END_MARKER;
96
97     private final static String JavaDoc PAGE_NAME= "NewTestSuiteCreationWizardPage"; //$NON-NLS-1$
98

99     /** Field ID of the class in suite field. */
100     public final static String JavaDoc CLASSES_IN_SUITE= PAGE_NAME + ".classesinsuite"; //$NON-NLS-1$
101

102     private CheckboxTableViewer fClassesInSuiteTable;
103     private IStatus fClassesInSuiteStatus;
104
105     private Label fSelectedClassesLabel;
106     
107     private boolean fUpdatedExistingClassButton;
108
109     /**
110      * Creates a new <code>NewTestSuiteWizardPage</code>.
111      */

112     public NewTestSuiteWizardPage() {
113         super(true, PAGE_NAME);
114         setTitle(WizardMessages.NewTestSuiteWizPage_title);
115         setDescription(WizardMessages.NewTestSuiteWizPage_description);
116         
117         fClassesInSuiteStatus= new JUnitStatus();
118     }
119
120     /* (non-Javadoc)
121      * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
122      */

123     public void createControl(Composite parent) {
124         initializeDialogUnits(parent);
125         
126         Composite composite= new Composite(parent, SWT.NONE);
127         int nColumns= 4;
128         
129         GridLayout layout= new GridLayout();
130         layout.numColumns= nColumns;
131         composite.setLayout(layout);
132     
133         createContainerControls(composite, nColumns);
134         createPackageControls(composite, nColumns);
135         //createSeparator(composite, nColumns);
136
createTypeNameControls(composite, nColumns);
137         createClassesInSuiteControl(composite, nColumns);
138         createMethodStubSelectionControls(composite, nColumns);
139         setControl(composite);
140         restoreWidgetValues();
141         Dialog.applyDialogFont(composite);
142         PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IJUnitHelpContextIds.NEW_TESTSUITE_WIZARD_PAGE);
143     }
144
145     /**
146      * Creates the controls for the method stub selection buttons. Expects a <code>GridLayout</code> with
147      * at least 3 columns.
148      *
149      * @param composite the parent composite
150      * @param nColumns number of columns to span
151      */

152     protected void createMethodStubSelectionControls(Composite composite, int nColumns) {
153     }
154
155     /**
156      * Should be called from the wizard with the initial selection.
157      *
158      * @param selection the initial selection
159      */

160     public void init(IStructuredSelection selection) {
161         IJavaElement jelem= getInitialJavaElement(selection);
162         initContainerPage(jelem);
163         initSuitePage(jelem);
164         doStatusUpdate();
165     }
166
167     private void initSuitePage(IJavaElement jelem) {
168         //parts of NewTypeWizardPage#initTypePage(..), see bug 132748
169

170         if (jelem != null) {
171             IPackageFragment pack= (IPackageFragment) jelem.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
172             IJavaProject project= jelem.getJavaProject();
173             
174             setPackageFragment(pack, true);
175             setAddComments(StubUtility.doAddComments(project), true); // from project or workspace
176
}
177         
178         setTypeName(ALL_TESTS, true);
179         fTypeNameStatus= typeNameChanged(); //set status on initialization for this dialog - user must know that suite method will be overridden
180
}
181     
182     /* (non-Javadoc)
183      * @see org.eclipse.jdt.ui.wizards.NewContainerWizardPage#handleFieldChanged(java.lang.String)
184      */

185     protected void handleFieldChanged(String JavaDoc fieldName) {
186         super.handleFieldChanged(fieldName);
187         if (fieldName.equals(PACKAGE) || fieldName.equals(CONTAINER)) {
188             updateClassesInSuiteTable();
189         } else if (fieldName.equals(CLASSES_IN_SUITE)) {
190             fClassesInSuiteStatus= classesInSuiteChanged();
191             fTypeNameStatus= typeNameChanged(); //must check this one too
192
updateSelectedClassesLabel();
193         }
194
195         doStatusUpdate();
196     }
197
198     // ------ validation --------
199
private void doStatusUpdate() {
200         // status of all used components
201
IStatus[] status= new IStatus[] {
202             fContainerStatus,
203             fPackageStatus,
204             fTypeNameStatus,
205             fClassesInSuiteStatus
206         };
207         
208         // the most severe status will be displayed and the OK button enabled/disabled.
209
updateStatus(status);
210     }
211
212     /* (non-Javadoc)
213      * @see org.eclipse.jface.dialogs.IDialogPage#setVisible(boolean)
214      */

215     public void setVisible(boolean visible) {
216         if (visible) {
217             setFocus();
218             updateClassesInSuiteTable();
219             handleAllFieldsChanged();
220         } else {
221             saveWidgetValues();
222         }
223         super.setVisible(visible);
224     }
225
226     private void handleAllFieldsChanged() {
227         handleFieldChanged(PACKAGE);
228         handleFieldChanged(CONTAINER);
229         handleFieldChanged(CLASSES_IN_SUITE);
230         handleFieldChanged(TYPENAME);
231     }
232
233     /**
234      * Updates the classes in the suite table.
235      */

236     protected void updateClassesInSuiteTable() {
237         if (fClassesInSuiteTable != null) {
238             IPackageFragment pack= getPackageFragment();
239             if (pack == null) {
240                 IPackageFragmentRoot root= getPackageFragmentRoot();
241                 if (root != null)
242                     pack= root.getPackageFragment(""); //$NON-NLS-1$
243
else
244                     return;
245             }
246             fClassesInSuiteTable.setInput(pack);
247             fClassesInSuiteTable.setAllChecked(true);
248             updateSelectedClassesLabel();
249         }
250     }
251     
252     /**
253      * Creates the controls for the list of classes in the suite. Expects a <code>GridLayout</code> with
254      * at least 3 columns.
255      *
256      * @param parent the parent composite
257      * @param nColumns number of columns to span
258      */

259     protected void createClassesInSuiteControl(Composite parent, int nColumns) {
260         if (fClassesInSuiteTable == null) {
261
262             Label label = new Label(parent, SWT.LEFT);
263             label.setText(WizardMessages.NewTestSuiteWizPage_classes_in_suite_label);
264             GridData gd= new GridData();
265             gd.horizontalAlignment = GridData.FILL;
266             gd.horizontalSpan= nColumns;
267             label.setLayoutData(gd);
268
269             fClassesInSuiteTable= CheckboxTableViewer.newCheckList(parent, SWT.BORDER);
270             gd= new GridData(GridData.FILL_BOTH);
271             gd.heightHint= 80;
272             gd.horizontalSpan= nColumns-1;
273
274             fClassesInSuiteTable.getTable().setLayoutData(gd);
275             fClassesInSuiteTable.setContentProvider(new SuiteClassesContentProvider());
276             fClassesInSuiteTable.setLabelProvider(new JavaElementLabelProvider());
277             fClassesInSuiteTable.addCheckStateListener(new ICheckStateListener() {
278                 public void checkStateChanged(CheckStateChangedEvent event) {
279                     handleFieldChanged(CLASSES_IN_SUITE);
280                 }
281             });
282
283             Composite buttonContainer= new Composite(parent, SWT.NONE);
284             gd= new GridData(GridData.FILL_VERTICAL);
285             buttonContainer.setLayoutData(gd);
286             GridLayout buttonLayout= new GridLayout();
287             buttonLayout.marginWidth= 0;
288             buttonLayout.marginHeight= 0;
289             buttonContainer.setLayout(buttonLayout);
290     
291             Button selectAllButton= new Button(buttonContainer, SWT.PUSH);
292             selectAllButton.setText(WizardMessages.NewTestSuiteWizPage_selectAll);
293             GridData bgd= new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_BEGINNING);
294             bgd.widthHint = LayoutUtil.getButtonWidthHint(selectAllButton);
295             selectAllButton.setLayoutData(bgd);
296             selectAllButton.addSelectionListener(new SelectionAdapter() {
297                 public void widgetSelected(SelectionEvent e) {
298                     fClassesInSuiteTable.setAllChecked(true);
299                     handleFieldChanged(CLASSES_IN_SUITE);
300                 }
301             });
302     
303             Button deselectAllButton= new Button(buttonContainer, SWT.PUSH);
304             deselectAllButton.setText(WizardMessages.NewTestSuiteWizPage_deselectAll);
305             bgd= new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_BEGINNING);
306             bgd.widthHint = LayoutUtil.getButtonWidthHint(deselectAllButton);
307             deselectAllButton.setLayoutData(bgd);
308             deselectAllButton.addSelectionListener(new SelectionAdapter() {
309                 public void widgetSelected(SelectionEvent e) {
310                     fClassesInSuiteTable.setAllChecked(false);
311                     handleFieldChanged(CLASSES_IN_SUITE);
312                 }
313             });
314
315             // No of selected classes label
316
fSelectedClassesLabel= new Label(parent, SWT.LEFT | SWT.WRAP);
317             fSelectedClassesLabel.setFont(parent.getFont());
318             updateSelectedClassesLabel();
319             gd = new GridData();
320             gd.horizontalSpan = 2;
321             fSelectedClassesLabel.setLayoutData(gd);
322         }
323     }
324     
325
326     /* (non-Javadoc)
327      * @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)
328      */

329     protected void createTypeMembers(IType type, ImportsManager imports, IProgressMonitor monitor) throws CoreException {
330         writeImports(imports);
331         type.createMethod(getSuiteMethodString(), null, false, null);
332     }
333
334     /*
335      * Returns the string content for creating a new suite() method.
336      */

337     private String JavaDoc getSuiteMethodString() {
338         IPackageFragment pack= getPackageFragment();
339         String JavaDoc packName= pack.getElementName();
340         StringBuffer JavaDoc suite= new StringBuffer JavaDoc("public static Test suite () {TestSuite suite= new TestSuite(\"Test for "+((packName.equals(""))?"default package":packName)+"\");\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
341
suite.append(getUpdatableString());
342         suite.append("\nreturn suite;}"); //$NON-NLS-1$
343
return suite.toString();
344     }
345     
346     private String JavaDoc getUpdatableString() {
347         return UpdateTestSuite.getUpdatableString(fClassesInSuiteTable.getCheckedElements());
348     }
349     
350     /* (non-Javadoc)
351      * @see org.eclipse.jdt.ui.wizards.NewTypeWizardPage#createType(org.eclipse.core.runtime.IProgressMonitor)
352      */

353     public void createType(IProgressMonitor monitor) throws CoreException, InterruptedException JavaDoc {
354         IPackageFragment pack= getPackageFragment();
355         ICompilationUnit cu= pack.getCompilationUnit(getTypeName() + ".java"); //$NON-NLS-1$
356

357         if (!cu.exists()) {
358             super.createType(monitor);
359             fUpdatedExistingClassButton= false;
360         } else {
361             updateExistingType(cu, monitor);
362             fUpdatedExistingClassButton= true;
363         }
364     }
365
366     private void updateExistingType(ICompilationUnit cu, IProgressMonitor monitor) throws JavaModelException {
367         if (! UpdateTestSuite.checkValidateEditStatus(cu, getShell()))
368             return;
369         IType suiteType= cu.getType(getTypeName());
370         monitor.beginTask(WizardMessages.NewTestSuiteWizPage_createType_beginTask, 10);
371         IMethod suiteMethod= suiteType.getMethod("suite", new String JavaDoc[] {}); //$NON-NLS-1$
372
monitor.worked(1);
373         String JavaDoc lineDelimiter= cu.findRecommendedLineSeparator();
374         if (suiteMethod.exists()) {
375             ISourceRange range= suiteMethod.getSourceRange();
376             if (range != null) {
377                 try {
378                     IDocument fullSource= new Document(cu.getBuffer().getContents());
379                     String JavaDoc originalContent= fullSource.get(range.getOffset(), range.getLength());
380                     StringBuffer JavaDoc source= new StringBuffer JavaDoc(originalContent);
381                     TestSuiteClassListRange classListRange = UpdateTestSuite.getTestSuiteClassListRange(originalContent);
382                     if (classListRange != null) {
383                         // TODO: copied
384
monitor.subTask(WizardMessages.NewTestSuiteWizPage_createType_updating_suite_method);
385                         monitor.worked(1);
386                         source.replace(classListRange.getStart(), classListRange.getEnd(), getUpdatableString());
387                         fullSource.replace(range.getOffset(), range.getLength(), source.toString());
388                         monitor.worked(1);
389                         String JavaDoc formattedContent= JUnitStubUtility.formatCompilationUnit(cu.getJavaProject(), fullSource.get(), lineDelimiter);
390                         cu.getBuffer().setContents(formattedContent);
391                         monitor.worked(1);
392                         cu.save(new SubProgressMonitor(monitor, 1), false);
393                     } else {
394                         cannotUpdateSuiteError();
395                     }
396                 } catch (BadLocationException e) {
397                     Assert.isTrue(false, "Should never happen"); //$NON-NLS-1$
398
}
399             } else {
400                 MessageDialog.openError(getShell(), WizardMessages.NewTestSuiteWizPage_createType_updateErrorDialog_title, WizardMessages.NewTestSuiteWizPage_createType_updateErrorDialog_message);
401             }
402         } else {
403             suiteType.createMethod(getSuiteMethodString(), null, true, monitor);
404             String JavaDoc originalContent= cu.getSource();
405             monitor.worked(2);
406             String JavaDoc formattedContent= JUnitStubUtility.formatCompilationUnit(cu.getJavaProject(), originalContent, lineDelimiter);
407             cu.getBuffer().setContents(formattedContent);
408             monitor.worked(1);
409             cu.save(new SubProgressMonitor(monitor, 1), false);
410         }
411         monitor.done();
412     }
413
414     /**
415      * Returns true iff an existing suite() method has been replaced.
416      *
417      * @return <code>true</code> is returned if an existing test suite has been replaced
418      */

419     public boolean hasUpdatedExistingClass() {
420         return fUpdatedExistingClassButton;
421     }
422     
423     private IStatus classesInSuiteChanged() {
424         JUnitStatus status= new JUnitStatus();
425         if (fClassesInSuiteTable.getCheckedElements().length <= 0)
426             status.setWarning(WizardMessages.NewTestSuiteWizPage_classes_in_suite_error_no_testclasses_selected);
427         return status;
428     }
429     
430     private void updateSelectedClassesLabel() {
431         int noOfClassesChecked= fClassesInSuiteTable.getCheckedElements().length;
432         String JavaDoc key= (noOfClassesChecked==1) ? WizardMessages.NewTestClassWizPage_treeCaption_classSelected : WizardMessages.NewTestClassWizPage_treeCaption_classesSelected;
433         fSelectedClassesLabel.setText(Messages.format(key, new Integer JavaDoc(noOfClassesChecked)));
434     }
435
436
437     /* (non-Javadoc)
438      * @see org.eclipse.jdt.ui.wizards.NewTypeWizardPage#typeNameChanged()
439      */

440     protected IStatus typeNameChanged() {
441         super.typeNameChanged();
442         
443         JUnitStatus status= new JUnitStatus();
444         String JavaDoc typeName= getTypeName();
445         // must not be empty
446
if (typeName.length() == 0) {
447             status.setError(WizardMessages.NewTestSuiteWizPage_typeName_error_name_empty);
448             return status;
449         }
450         if (typeName.indexOf('.') != -1) {
451             status.setError(WizardMessages.NewTestSuiteWizPage_typeName_error_name_qualified);
452             return status;
453         }
454         
455         IJavaProject javaProject= getJavaProject();
456         String JavaDoc sourceLevel= javaProject != null ? javaProject.getOption(JavaCore.COMPILER_SOURCE, true) : JavaCore.VERSION_1_3;
457         String JavaDoc compliance= javaProject != null ? javaProject.getOption(JavaCore.COMPILER_COMPLIANCE, true) : JavaCore.VERSION_1_3;
458         
459         IStatus val= JavaConventions.validateJavaTypeName(typeName, sourceLevel, compliance);
460         if (val.getSeverity() == IStatus.ERROR) {
461             status.setError(WizardMessages.NewTestSuiteWizPage_typeName_error_name_not_valid+val.getMessage());
462             return status;
463         } else if (val.getSeverity() == IStatus.WARNING) {
464             status.setWarning(WizardMessages.NewTestSuiteWizPage_typeName_error_name_name_discouraged+val.getMessage());
465             // continue checking
466
}
467
468         IStatus recursiveSuiteInclusionStatus= checkRecursiveTestSuiteInclusion();
469         if (! recursiveSuiteInclusionStatus.isOK())
470             return recursiveSuiteInclusionStatus;
471             
472         IPackageFragment pack= getPackageFragment();
473         if (pack != null) {
474             ICompilationUnit cu= pack.getCompilationUnit(typeName + ".java"); //$NON-NLS-1$
475
if (cu.exists()) {
476                 status.setWarning(WizardMessages.NewTestSuiteWizPage_typeName_warning_already_exists);
477                 return status;
478             }
479         }
480         return status;
481     }
482
483     private IStatus checkRecursiveTestSuiteInclusion(){
484         if (fClassesInSuiteTable == null)
485             return new JUnitStatus();
486         String JavaDoc typeName= getTypeName();
487         JUnitStatus status= new JUnitStatus();
488         Object JavaDoc[] checkedClasses= fClassesInSuiteTable.getCheckedElements();
489         for (int i= 0; i < checkedClasses.length; i++) {
490             IType checkedClass= (IType)checkedClasses[i];
491             if (checkedClass.getElementName().equals(typeName)){
492                 status.setWarning(WizardMessages.NewTestSuiteCreationWizardPage_infinite_recursion);
493                 return status;
494             }
495         }
496         return new JUnitStatus();
497     }
498
499     
500     private void cannotUpdateSuiteError() {
501         MessageDialog.openError(getShell(), WizardMessages.NewTestSuiteWizPage_cannotUpdateDialog_title,
502             Messages.format(WizardMessages.NewTestSuiteWizPage_cannotUpdateDialog_message, new String JavaDoc[] { NewTestSuiteWizardPage.START_MARKER, NewTestSuiteWizardPage.END_MARKER}));
503
504     }
505
506     private void writeImports(ImportsManager imports) {
507         imports.addImport("junit.framework.Test"); //$NON-NLS-1$
508
imports.addImport("junit.framework.TestSuite"); //$NON-NLS-1$
509
}
510
511     /**
512      * Use the dialog store to restore widget values to the values that they held
513      * last time this wizard was used to completion
514      */

515     private void restoreWidgetValues() {
516     }
517
518     /**
519      * Since Finish was pressed, write widget values to the dialog store so that they
520      * will persist into the next invocation of this wizard page
521      */

522     private void saveWidgetValues() {
523     }
524 }
525
Popular Tags