KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > ui > actions > GenerateNewConstructorUsingFieldsAction


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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.ui.actions;
12
13 import java.lang.reflect.InvocationTargetException JavaDoc;
14 import java.util.ArrayList JavaDoc;
15 import java.util.Arrays JavaDoc;
16 import java.util.List JavaDoc;
17
18 import org.eclipse.core.runtime.CoreException;
19
20 import org.eclipse.jface.dialogs.MessageDialog;
21 import org.eclipse.jface.operation.IRunnableContext;
22 import org.eclipse.jface.viewers.IStructuredSelection;
23 import org.eclipse.jface.window.Window;
24
25 import org.eclipse.jface.text.IRewriteTarget;
26 import org.eclipse.jface.text.ITextSelection;
27
28 import org.eclipse.ui.IEditorPart;
29 import org.eclipse.ui.IWorkbenchSite;
30 import org.eclipse.ui.PlatformUI;
31
32 import org.eclipse.jdt.core.Flags;
33 import org.eclipse.jdt.core.ICompilationUnit;
34 import org.eclipse.jdt.core.IField;
35 import org.eclipse.jdt.core.IJavaElement;
36 import org.eclipse.jdt.core.IType;
37 import org.eclipse.jdt.core.JavaModelException;
38 import org.eclipse.jdt.core.ToolFactory;
39 import org.eclipse.jdt.core.compiler.IScanner;
40 import org.eclipse.jdt.core.compiler.ITerminalSymbols;
41 import org.eclipse.jdt.core.dom.CompilationUnit;
42 import org.eclipse.jdt.core.dom.IMethodBinding;
43 import org.eclipse.jdt.core.dom.ITypeBinding;
44 import org.eclipse.jdt.core.dom.IVariableBinding;
45
46 import org.eclipse.jdt.internal.corext.codemanipulation.AddCustomConstructorOperation;
47 import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings;
48 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility2;
49 import org.eclipse.jdt.internal.corext.dom.Bindings;
50 import org.eclipse.jdt.internal.corext.dom.TokenScanner;
51 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
52 import org.eclipse.jdt.internal.corext.util.JdtFlags;
53
54 import org.eclipse.jdt.ui.JavaUI;
55
56 import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
57 import org.eclipse.jdt.internal.ui.JavaPlugin;
58 import org.eclipse.jdt.internal.ui.actions.ActionMessages;
59 import org.eclipse.jdt.internal.ui.actions.ActionUtil;
60 import org.eclipse.jdt.internal.ui.actions.GenerateConstructorUsingFieldsContentProvider;
61 import org.eclipse.jdt.internal.ui.actions.GenerateConstructorUsingFieldsSelectionDialog;
62 import org.eclipse.jdt.internal.ui.actions.GenerateConstructorUsingFieldsValidator;
63 import org.eclipse.jdt.internal.ui.actions.SelectionConverter;
64 import org.eclipse.jdt.internal.ui.actions.WorkbenchRunnableAdapter;
65 import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor;
66 import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings;
67 import org.eclipse.jdt.internal.ui.util.BusyIndicatorRunnableContext;
68 import org.eclipse.jdt.internal.ui.util.ElementValidator;
69 import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
70 import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider;
71
72 /**
73  * Creates constructors for a type based on existing fields.
74  * <p>
75  * Will open the parent compilation unit in a Java editor. Opens a dialog with a list
76  * fields from which a constructor will be generated. User is able to check or uncheck
77  * items before constructors are generated. The result is unsaved, so the user can decide
78  * if the changes are acceptable.
79  * <p>
80  * The action is applicable to structured selections containing elements of type
81  * <code>IType</code>.
82  *
83  * <p>
84  * This class may be instantiated; it is not intended to be subclassed.
85  * </p>
86  *
87  * @since 3.0
88  */

89 public class GenerateNewConstructorUsingFieldsAction extends SelectionDispatchAction {
90
91     private CompilationUnitEditor fEditor;
92
93     /**
94      * Note: This constructor is for internal use only. Clients should not call this
95      * constructor.
96      *
97      * @param editor the compilation unit editor
98      */

99     public GenerateNewConstructorUsingFieldsAction(CompilationUnitEditor editor) {
100         this(editor.getEditorSite());
101         fEditor= editor;
102         setEnabled(checkEnabledEditor());
103     }
104
105     /**
106      * Creates a new <code>GenerateConstructorUsingFieldsAction</code>. The action requires
107      * that the selection provided by the site's selection provider is of type <code>
108      * org.eclipse.jface.viewers.IStructuredSelection</code>.
109      *
110      * @param site the site providing context information for this action
111      */

112     public GenerateNewConstructorUsingFieldsAction(IWorkbenchSite site) {
113         super(site);
114         setText(ActionMessages.GenerateConstructorUsingFieldsAction_label);
115         setDescription(ActionMessages.GenerateConstructorUsingFieldsAction_description);
116         setToolTipText(ActionMessages.GenerateConstructorUsingFieldsAction_tooltip);
117
118         PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IJavaHelpContextIds.CREATE_NEW_CONSTRUCTOR_ACTION);
119     }
120
121     private boolean canEnable(IStructuredSelection selection) throws JavaModelException {
122         if (getSelectedFields(selection) != null)
123             return true;
124
125         if ((selection.size() == 1) && (selection.getFirstElement() instanceof IType)) {
126             IType type= (IType) selection.getFirstElement();
127             return type.getCompilationUnit() != null && !type.isInterface() && !type.isAnnotation();
128         }
129
130         if ((selection.size() == 1) && (selection.getFirstElement() instanceof ICompilationUnit))
131             return true;
132
133         return false;
134     }
135
136     private boolean canRunOn(IField[] fields) throws JavaModelException {
137         if (fields != null && fields.length > 0) {
138             for (int index= 0; index < fields.length; index++) {
139                 if (JdtFlags.isEnum(fields[index])) {
140                     MessageDialog.openInformation(getShell(), ActionMessages.GenerateConstructorUsingFieldsAction_error_title, ActionMessages.GenerateConstructorUsingFieldsAction_enum_not_applicable);
141                     return false;
142                 }
143             }
144             return true;
145         }
146         return false;
147     }
148
149     private boolean checkEnabledEditor() {
150         return fEditor != null && SelectionConverter.canOperateOn(fEditor);
151     }
152
153     /*
154      * Returns fields in the selection or <code>null</code> if the selection is empty or
155      * not valid.
156      */

157     private IField[] getSelectedFields(IStructuredSelection selection) {
158         List JavaDoc elements= selection.toList();
159         if (elements.size() > 0) {
160             IField[] fields= new IField[elements.size()];
161             ICompilationUnit unit= null;
162             for (int index= 0; index < elements.size(); index++) {
163                 if (elements.get(index) instanceof IField) {
164                     IField field= (IField) elements.get(index);
165                     if (index == 0) {
166                         // remember the CU of the first element
167
unit= field.getCompilationUnit();
168                         if (unit == null) {
169                             return null;
170                         }
171                     } else if (!unit.equals(field.getCompilationUnit())) {
172                         // all fields must be in the same CU
173
return null;
174                     }
175                     try {
176                         final IType declaringType= field.getDeclaringType();
177                         if (declaringType.isInterface() || declaringType.isAnnotation())
178                             return null;
179                     } catch (JavaModelException exception) {
180                         JavaPlugin.log(exception);
181                         return null;
182                     }
183                     fields[index]= field;
184                 } else {
185                     return null;
186                 }
187             }
188             return fields;
189         }
190         return null;
191     }
192
193     private IType getSelectedType(IStructuredSelection selection) throws JavaModelException {
194         Object JavaDoc[] elements= selection.toArray();
195         if (elements.length == 1 && (elements[0] instanceof IType)) {
196             IType type= (IType) elements[0];
197             if (type.getCompilationUnit() != null && !type.isInterface() && !type.isAnnotation()) {
198                 return type;
199             }
200         } else if (elements[0] instanceof ICompilationUnit) {
201             ICompilationUnit unit= (ICompilationUnit) elements[0];
202             IType type= unit.findPrimaryType();
203             if (type != null && !type.isInterface() && !type.isAnnotation())
204                 return type;
205         } else if (elements[0] instanceof IField) {
206             return ((IField) elements[0]).getCompilationUnit().findPrimaryType();
207         }
208         return null;
209     }
210
211     /*
212      * (non-Javadoc) Method declared on SelectionDispatchAction
213      */

214     public void run(IStructuredSelection selection) {
215         try {
216             IType selectionType= getSelectedType(selection);
217             if (selectionType == null) {
218                 MessageDialog.openInformation(getShell(), ActionMessages.GenerateConstructorUsingFieldsAction_error_title, ActionMessages.GenerateConstructorUsingFieldsAction_not_applicable);
219                 notifyResult(false);
220                 return;
221             }
222
223             IField[] selectedFields= getSelectedFields(selection);
224
225             if (canRunOn(selectedFields)) {
226                 run(selectedFields[0].getDeclaringType(), selectedFields, false);
227                 return;
228             }
229             Object JavaDoc firstElement= selection.getFirstElement();
230
231             if (firstElement instanceof IType) {
232                 run((IType) firstElement, new IField[0], false);
233             } else if (firstElement instanceof ICompilationUnit) {
234                 IType type= ((ICompilationUnit) firstElement).findPrimaryType();
235                 if (type.isAnnotation()) {
236                     MessageDialog.openInformation(getShell(), ActionMessages.GenerateConstructorUsingFieldsAction_error_title, ActionMessages.GenerateConstructorUsingFieldsAction_annotation_not_applicable);
237                     notifyResult(false);
238                     return;
239                 } else if (type.isInterface()) {
240                     MessageDialog.openInformation(getShell(), ActionMessages.GenerateConstructorUsingFieldsAction_error_title, ActionMessages.GenerateConstructorUsingFieldsAction_interface_not_applicable);
241                     notifyResult(false);
242                     return;
243                 } else
244                     run(((ICompilationUnit) firstElement).findPrimaryType(), new IField[0], false);
245             }
246         } catch (CoreException exception) {
247             ExceptionHandler.handle(exception, getShell(), ActionMessages.GenerateConstructorUsingFieldsAction_error_title, ActionMessages.GenerateConstructorUsingFieldsAction_error_actionfailed);
248         }
249     }
250
251     /*
252      * (non-Javadoc) Method declared on SelectionDispatchAction
253      */

254     public void run(ITextSelection selection) {
255         if (!ActionUtil.isProcessable(fEditor)) {
256             notifyResult(false);
257             return;
258         }
259         try {
260             IJavaElement[] elements= SelectionConverter.codeResolveForked(fEditor, true);
261             if (elements.length == 1 && (elements[0] instanceof IField)) {
262                 IField field= (IField) elements[0];
263                 run(field.getDeclaringType(), new IField[] { field}, false);
264                 return;
265             }
266             IJavaElement element= SelectionConverter.getElementAtOffset(fEditor);
267             if (element != null) {
268                 IType type= (IType) element.getAncestor(IJavaElement.TYPE);
269                 if (type != null) {
270                     if (type.getFields().length > 0) {
271                         run(type, new IField[0], true);
272                     } else {
273                         MessageDialog.openInformation(getShell(), ActionMessages.GenerateConstructorUsingFieldsAction_error_title, ActionMessages.GenerateConstructorUsingFieldsAction_typeContainsNoFields_message);
274                     }
275                     return;
276                 }
277             }
278             MessageDialog.openInformation(getShell(), ActionMessages.GenerateConstructorUsingFieldsAction_error_title, ActionMessages.GenerateConstructorUsingFieldsAction_not_applicable);
279         } catch (CoreException exception) {
280             ExceptionHandler.handle(exception, getShell(), ActionMessages.GenerateConstructorUsingFieldsAction_error_title, ActionMessages.GenerateConstructorUsingFieldsAction_error_actionfailed);
281         } catch (InvocationTargetException JavaDoc exception) {
282             ExceptionHandler.handle(exception, getShell(), ActionMessages.GenerateConstructorUsingFieldsAction_error_title, ActionMessages.GenerateConstructorUsingFieldsAction_error_actionfailed);
283         } catch (InterruptedException JavaDoc e) {
284             // cancelled
285
}
286     }
287
288     // ---- Helpers -------------------------------------------------------------------
289

290     void run(IType type, IField[] selected, boolean activated) throws CoreException {
291         if (!ElementValidator.check(type, getShell(), ActionMessages.GenerateConstructorUsingFieldsAction_error_title, activated)) {
292             notifyResult(false);
293             return;
294         }
295         if (!ActionUtil.isEditable(fEditor, getShell(), type)) {
296             notifyResult(false);
297             return;
298         }
299         if (type.getCompilationUnit() == null) {
300             MessageDialog.openInformation(getShell(), ActionMessages.GenerateConstructorUsingFieldsAction_error_title, ActionMessages.GenerateNewConstructorUsingFieldsAction_error_not_a_source_file);
301             notifyResult(false);
302             return;
303             
304         }
305         
306         IField[] candidates= type.getFields();
307         ArrayList JavaDoc fields= new ArrayList JavaDoc();
308         for (int index= 0; index < candidates.length; index++) {
309             boolean isStatic= Flags.isStatic(candidates[index].getFlags());
310             boolean isFinal= Flags.isFinal(candidates[index].getFlags());
311             if (!isStatic) {
312                 if (isFinal) {
313                     try {
314                         // Do not add final fields which have been set in the <clinit>
315
IScanner scanner= ToolFactory.createScanner(true, false, false, false);
316                         scanner.setSource(candidates[index].getSource().toCharArray());
317                         TokenScanner tokenScanner= new TokenScanner(scanner);
318                         tokenScanner.getTokenStartOffset(ITerminalSymbols.TokenNameEQUAL, 0);
319                     } catch (JavaModelException e) {
320                     } catch (CoreException e) {
321                         fields.add(candidates[index]);
322                     }
323                 } else
324                     fields.add(candidates[index]);
325             }
326         }
327         if (fields.isEmpty()) {
328             MessageDialog.openInformation(getShell(), ActionMessages.GenerateConstructorUsingFieldsAction_error_title, ActionMessages.GenerateConstructorUsingFieldsAction_typeContainsNoFields_message);
329             notifyResult(false);
330             return;
331         }
332         final GenerateConstructorUsingFieldsContentProvider provider= new GenerateConstructorUsingFieldsContentProvider(type, fields, Arrays.asList(selected));
333         IMethodBinding[] bindings= null;
334         final ITypeBinding provided= provider.getType();
335         if (provided.isAnonymous()) {
336             MessageDialog.openInformation(getShell(), ActionMessages.GenerateConstructorUsingFieldsAction_error_title, ActionMessages.GenerateConstructorUsingFieldsAction_error_anonymous_class);
337             notifyResult(false);
338             return;
339         }
340         if (provided.isEnum()) {
341             bindings= new IMethodBinding[] {getObjectConstructor(provider.getCompilationUnit())};
342         } else {
343             bindings= StubUtility2.getVisibleConstructors(provided, false, true);
344             if (bindings.length == 0) {
345                 MessageDialog.openInformation(getShell(), ActionMessages.GenerateConstructorUsingFieldsAction_error_title, ActionMessages.GenerateConstructorUsingFieldsAction_error_nothing_found);
346                 notifyResult(false);
347                 return;
348             }
349         }
350
351         GenerateConstructorUsingFieldsSelectionDialog dialog= new GenerateConstructorUsingFieldsSelectionDialog(getShell(), new BindingLabelProvider(), provider, fEditor, type, bindings);
352         dialog.setCommentString(ActionMessages.SourceActionDialog_createConstructorComment);
353         dialog.setTitle(ActionMessages.GenerateConstructorUsingFieldsAction_dialog_title);
354         dialog.setInitialSelections(provider.getInitiallySelectedElements());
355         dialog.setContainerMode(true);
356         dialog.setSize(60, 18);
357         dialog.setInput(new Object JavaDoc());
358         dialog.setMessage(ActionMessages.GenerateConstructorUsingFieldsAction_dialog_label);
359         dialog.setValidator(new GenerateConstructorUsingFieldsValidator(dialog, provided, fields.size()));
360
361         final int dialogResult= dialog.open();
362         if (dialogResult == Window.OK) {
363             Object JavaDoc[] elements= dialog.getResult();
364             if (elements == null) {
365                 notifyResult(false);
366                 return;
367             }
368             ArrayList JavaDoc result= new ArrayList JavaDoc(elements.length);
369             for (int index= 0; index < elements.length; index++) {
370                 if (elements[index] instanceof IVariableBinding)
371                     result.add(elements[index]);
372             }
373             IVariableBinding[] variables= new IVariableBinding[result.size()];
374             result.toArray(variables);
375             IEditorPart editor= JavaUI.openInEditor(type.getCompilationUnit());
376             CodeGenerationSettings settings= JavaPreferencesSettings.getCodeGenerationSettings(type.getJavaProject());
377             settings.createComments= dialog.getGenerateComment();
378             IMethodBinding constructor= dialog.getSuperConstructorChoice();
379             IRewriteTarget target= editor != null ? (IRewriteTarget) editor.getAdapter(IRewriteTarget.class) : null;
380             if (target != null)
381                 target.beginCompoundChange();
382             try {
383                 AddCustomConstructorOperation operation= new AddCustomConstructorOperation(type, dialog.getElementPosition(), provider.getCompilationUnit(), variables, constructor, settings, true, false);
384                 operation.setVisibility(dialog.getVisibilityModifier());
385                 if (constructor.getParameterTypes().length == 0)
386                     operation.setOmitSuper(dialog.isOmitSuper());
387                 IRunnableContext context= JavaPlugin.getActiveWorkbenchWindow();
388                 if (context == null)
389                     context= new BusyIndicatorRunnableContext();
390                 PlatformUI.getWorkbench().getProgressService().runInUI(context, new WorkbenchRunnableAdapter(operation, operation.getSchedulingRule()), operation.getSchedulingRule());
391             } catch (InvocationTargetException JavaDoc exception) {
392                 ExceptionHandler.handle(exception, getShell(), ActionMessages.GenerateConstructorUsingFieldsAction_error_title, ActionMessages.GenerateConstructorUsingFieldsAction_error_actionfailed);
393             } catch (InterruptedException JavaDoc exception) {
394                 // Do nothing. Operation has been canceled by user.
395
} finally {
396                 if (target != null) {
397                     target.endCompoundChange();
398                 }
399             }
400         }
401         notifyResult(dialogResult == Window.OK);
402     }
403
404     private IMethodBinding getObjectConstructor(CompilationUnit compilationUnit) {
405         final ITypeBinding binding= compilationUnit.getAST().resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
406
return Bindings.findMethodInType(binding, "Object", new ITypeBinding[0]); //$NON-NLS-1$
407
}
408
409     /*
410      * (non-Javadoc) Method declared on SelectionDispatchAction
411      */

412     public void selectionChanged(IStructuredSelection selection) {
413         try {
414             setEnabled(canEnable(selection));
415         } catch (JavaModelException e) {
416             // http://bugs.eclipse.org/bugs/show_bug.cgi?id=19253
417
if (JavaModelUtil.isExceptionToBeLogged(e))
418                 JavaPlugin.log(e);
419             setEnabled(false);
420         }
421     }
422
423     // ---- Java Editor --------------------------------------------------------------
424

425     /*
426      * (non-Javadoc) Method declared on SelectionDispatchAction
427      */

428     public void selectionChanged(ITextSelection selection) {
429     }
430 }
431
Popular Tags