]> git.uio.no Git - ifi-stolz-refaktor.git/blob - case-study/jdt-after/ui/org/eclipse/jdt/ui/actions/ExternalizeStringsAction.java
Some talks, mostly identical.
[ifi-stolz-refaktor.git] / case-study / jdt-after / ui / org / eclipse / jdt / ui / actions / ExternalizeStringsAction.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2011 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;
14 import java.util.ArrayList;
15 import java.util.Arrays;
16 import java.util.Collections;
17 import java.util.Iterator;
18 import java.util.List;
19
20 import org.eclipse.swt.SWT;
21 import org.eclipse.swt.events.SelectionAdapter;
22 import org.eclipse.swt.events.SelectionEvent;
23 import org.eclipse.swt.graphics.Image;
24 import org.eclipse.swt.graphics.Point;
25 import org.eclipse.swt.widgets.Button;
26 import org.eclipse.swt.widgets.Composite;
27 import org.eclipse.swt.widgets.Control;
28 import org.eclipse.swt.widgets.Shell;
29
30 import org.eclipse.core.runtime.CoreException;
31 import org.eclipse.core.runtime.IAdaptable;
32 import org.eclipse.core.runtime.IProgressMonitor;
33 import org.eclipse.core.runtime.IStatus;
34 import org.eclipse.core.runtime.NullProgressMonitor;
35 import org.eclipse.core.runtime.OperationCanceledException;
36 import org.eclipse.core.runtime.Status;
37 import org.eclipse.core.runtime.SubProgressMonitor;
38
39 import org.eclipse.jface.dialogs.IDialogConstants;
40 import org.eclipse.jface.dialogs.MessageDialog;
41 import org.eclipse.jface.operation.IRunnableWithProgress;
42 import org.eclipse.jface.viewers.ArrayContentProvider;
43 import org.eclipse.jface.viewers.ISelection;
44 import org.eclipse.jface.viewers.ISelectionChangedListener;
45 import org.eclipse.jface.viewers.IStructuredSelection;
46 import org.eclipse.jface.viewers.LabelProvider;
47 import org.eclipse.jface.viewers.SelectionChangedEvent;
48
49 import org.eclipse.jface.text.BadLocationException;
50 import org.eclipse.jface.text.ITextSelection;
51
52 import org.eclipse.ui.IWorkbenchSite;
53 import org.eclipse.ui.IWorkingSet;
54 import org.eclipse.ui.PlatformUI;
55 import org.eclipse.ui.dialogs.ListDialog;
56
57 import org.eclipse.jdt.core.ICompilationUnit;
58 import org.eclipse.jdt.core.IJavaElement;
59 import org.eclipse.jdt.core.IJavaProject;
60 import org.eclipse.jdt.core.IPackageFragment;
61 import org.eclipse.jdt.core.IPackageFragmentRoot;
62 import org.eclipse.jdt.core.IType;
63 import org.eclipse.jdt.core.JavaModelException;
64 import org.eclipse.jdt.core.compiler.InvalidInputException;
65
66 import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester;
67 import org.eclipse.jdt.internal.corext.refactoring.nls.NLSElement;
68 import org.eclipse.jdt.internal.corext.refactoring.nls.NLSLine;
69 import org.eclipse.jdt.internal.corext.refactoring.nls.NLSScanner;
70 import org.eclipse.jdt.internal.corext.refactoring.reorg.ReorgUtils;
71 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
72 import org.eclipse.jdt.internal.corext.util.Messages;
73
74 import org.eclipse.jdt.ui.JavaElementLabelProvider;
75 import org.eclipse.jdt.ui.JavaElementLabels;
76
77 import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
78 import org.eclipse.jdt.internal.ui.JavaPlugin;
79 import org.eclipse.jdt.internal.ui.actions.ActionMessages;
80 import org.eclipse.jdt.internal.ui.actions.ActionUtil;
81 import org.eclipse.jdt.internal.ui.actions.SelectionConverter;
82 import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor;
83 import org.eclipse.jdt.internal.ui.refactoring.nls.ExternalizeWizard;
84 import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
85 import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels;
86
87
88 /**
89  * Externalizes the strings of a compilation unit or find all strings
90  * in a package or project that are not externalized yet. Opens a wizard that
91  * gathers additional information to externalize the strings.
92  * <p>
93  * The action is applicable to structured selections containing elements
94  * of type <code>ICompilationUnit</code>, <code>IType</code>, <code>IJavaProject</code>,
95  * <code>IPackageFragment</code>, and <code>IPackageFragmentRoot</code>
96  *
97  * <p>
98  * This class may be instantiated; it is not intended to be subclassed.
99  * </p>
100  *
101  * @since 2.0
102  *
103  * @noextend This class is not intended to be subclassed by clients.
104  */
105 public class ExternalizeStringsAction extends SelectionDispatchAction {
106
107         private CompilationUnitEditor fEditor;
108
109         private NonNLSElement[] fElements;
110
111         /**
112          * Creates a new <code>ExternalizeStringsAction</code>. The action requires
113          * that the selection provided by the site's selection provider is of type <code>
114          * org.eclipse.jface.viewers.IStructuredSelection</code>.
115          *
116          * @param site the site providing context information for this action
117          */
118         public ExternalizeStringsAction(IWorkbenchSite site) {
119                 super(site);
120                 setText(ActionMessages.ExternalizeStringsAction_label);
121                 PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IJavaHelpContextIds.EXTERNALIZE_STRINGS_ACTION);
122         }
123
124         /**
125          * Note: This constructor is for internal use only. Clients should not call this constructor.
126          * @param editor the compilation unit editor
127          *
128          * @noreference This constructor is not intended to be referenced by clients.
129          */
130         public ExternalizeStringsAction(CompilationUnitEditor editor) {
131                 this(editor.getEditorSite());
132                 fEditor= editor;
133                 setEnabled(fEditor != null && SelectionConverter.canOperateOn(fEditor));
134         }
135
136         /* (non-Javadoc)
137          * Method declared on SelectionDispatchAction.
138          */
139         @Override
140         public void selectionChanged(ITextSelection selection) {
141         }
142
143         /* (non-Javadoc)
144          * Method declared on SelectionDispatchAction.
145          */
146         @Override
147         public void selectionChanged(IStructuredSelection selection) {
148                 try {
149                         setEnabled(RefactoringAvailabilityTester.isExternalizeStringsAvailable(selection));
150                 } catch (JavaModelException e) {
151                         if (JavaModelUtil.isExceptionToBeLogged(e))
152                                 JavaPlugin.log(e);
153                         setEnabled(false);//no UI - happens on selection changes
154                 }
155         }
156
157         /* (non-Javadoc)
158          * Method declared on SelectionDispatchAction.
159          */
160         @Override
161         public void run(ITextSelection selection) {
162                 IJavaElement element= SelectionConverter.getInput(fEditor);
163                 if (!(element instanceof ICompilationUnit))
164                         return;
165                 run((ICompilationUnit)element);
166         }
167
168         /* (non-Javadoc)
169          * Method declared on SelectionDispatchAction.
170          */
171         @Override
172         public void run(IStructuredSelection selection) {
173                 ICompilationUnit unit= getCompilationUnit(selection);
174                 if (unit != null) {//run on cu
175                         run(unit);
176                 } else {
177                         //run on multiple
178                         try {
179                                 PlatformUI.getWorkbench().getProgressService().run(true, true, createRunnable(selection));
180                         } catch(InvocationTargetException e) {
181                                 ExceptionHandler.handle(e, getShell(),
182                                                 ActionMessages.ExternalizeStringsAction_dialog_title,
183                                                 ActionMessages.FindStringsToExternalizeAction_error_message);
184                                 return;
185                         } catch(InterruptedException e) {
186                                 // OK
187                                 return;
188                         }
189                         showResults();
190                 }
191         }
192
193         /**
194          * Note: this method is for internal use only. Clients should not call this method.
195          * @param unit the compilation unit
196          *
197          * @noreference This method is not intended to be referenced by clients.
198          */
199         public void run(ICompilationUnit unit) {
200                 if (!ActionUtil.isEditable(fEditor, getShell(), unit))
201                         return;
202
203                 ExternalizeWizard.open(unit, getShell());
204         }
205
206
207         private static ICompilationUnit getCompilationUnit(IStructuredSelection selection) {
208                 if (selection.isEmpty() || selection.size() != 1)
209                         return null;
210                 Object first= selection.getFirstElement();
211                 if (first instanceof ICompilationUnit)
212                         return (ICompilationUnit) first;
213                 if (first instanceof IType)
214                         return ((IType) first).getCompilationUnit();
215                 return null;
216         }
217
218         private IRunnableWithProgress createRunnable(final IStructuredSelection selection) {
219                 return new IRunnableWithProgress() {
220                         public void run(IProgressMonitor pm) throws InvocationTargetException {
221                                 try {
222                                         fElements= doRun(selection, pm);
223                                 } catch (CoreException e) {
224                                         throw new InvocationTargetException(e);
225                                 }
226                         }
227                 };
228         }
229
230         private NonNLSElement[] doRun(IStructuredSelection selection, IProgressMonitor pm) throws CoreException {
231                 List<?> elements= getSelectedElementList(selection);
232                 if (elements == null || elements.isEmpty())
233                         return new NonNLSElement[0];
234
235                 pm.beginTask(ActionMessages.FindStringsToExternalizeAction_find_strings, elements.size());
236
237                 try{
238                         List<NonNLSElement> result= new ArrayList<NonNLSElement>();
239                         for (Iterator<?> iter= elements.iterator(); iter.hasNext();) {
240                                 Object obj= iter.next();
241                                 result.addAll(analyze(obj, pm));
242                         }
243                         return result.toArray(new NonNLSElement[result.size()]);
244                 } finally{
245                         pm.done();
246                 }
247         }
248
249         private List<NonNLSElement> analyze(Object obj, IProgressMonitor pm) throws CoreException, JavaModelException {
250                 if (obj instanceof IJavaElement) {
251                         IJavaElement element= (IJavaElement) obj;
252                         int elementType= element.getElementType();
253
254                         if (elementType == IJavaElement.PACKAGE_FRAGMENT) {
255                                 return analyze((IPackageFragment) element, new SubProgressMonitor(pm, 1));
256                         } else if (elementType == IJavaElement.PACKAGE_FRAGMENT_ROOT) {
257                                 IPackageFragmentRoot root= (IPackageFragmentRoot)element;
258                                 if (!root.isExternal() && !ReorgUtils.isClassFolder(root)) {
259                                         return analyze((IPackageFragmentRoot) element, new SubProgressMonitor(pm, 1));
260                                 } else {
261                                         pm.worked(1);
262                                 }
263                         } else if (elementType == IJavaElement.JAVA_PROJECT) {
264                                 return analyze((IJavaProject) element, new SubProgressMonitor(pm, 1));
265                         } else if (elementType == IJavaElement.COMPILATION_UNIT) {
266                                 ICompilationUnit cu= (ICompilationUnit)element;
267                                 if (cu.exists()) {
268                                         NonNLSElement nlsElement= analyze(cu);
269                                         if (nlsElement != null) {
270                                                 pm.worked(1);
271                                                 ArrayList<NonNLSElement> result= new ArrayList<NonNLSElement>();
272                                                 result.add(nlsElement);
273                                                 return result;
274                                         }
275                                 }
276                                 pm.worked(1);
277                         } else if (elementType == IJavaElement.TYPE) {
278                                 IType type= (IType)element;
279                                 ICompilationUnit cu= type.getCompilationUnit();
280                                 if (cu != null && cu.exists()) {
281                                         NonNLSElement nlsElement= analyze(cu);
282                                         if (nlsElement != null) {
283                                                 pm.worked(1);
284                                                 ArrayList<NonNLSElement> result= new ArrayList<NonNLSElement>();
285                                                 result.add(nlsElement);
286                                                 return result;
287                                         }
288                                 }
289                                 pm.worked(1);
290                         } else {
291                                 pm.worked(1);
292                         }
293                 } else if (obj instanceof IWorkingSet) {
294                         List<NonNLSElement> result= new ArrayList<NonNLSElement>();
295
296                         IWorkingSet workingSet= (IWorkingSet) obj;
297                         IAdaptable[] elements= workingSet.getElements();
298                         for (int i= 0; i < elements.length; i++) {
299                                 result.addAll(analyze(elements[i], new NullProgressMonitor()));
300                         }
301                         pm.worked(1);
302                         return result;
303                 } else {
304                         pm.worked(1);
305                 }
306
307                 return Collections.emptyList();
308         }
309
310         private void showResults() {
311                 if (noStrings())
312                         MessageDialog.openInformation(getShell(), ActionMessages.ExternalizeStringsAction_dialog_title, ActionMessages.FindStringsToExternalizeAction_noStrings);
313                 else
314                         new NonNLSListDialog(getShell(), fElements, countStrings()).open();
315         }
316
317         private boolean noStrings() {
318                 if (fElements != null) {
319                         for (int i= 0; i < fElements.length; i++) {
320                                 if (fElements[i].count != 0)
321                                         return false;
322                         }
323                 }
324                 return true;
325         }
326
327         /*
328          * returns List of Strings
329          */
330         private List<NonNLSElement> analyze(IPackageFragment pack, IProgressMonitor pm) throws CoreException {
331                 try{
332                         if (pack == null)
333                                 return new ArrayList<NonNLSElement>(0);
334
335                         ICompilationUnit[] cus= pack.getCompilationUnits();
336
337                         pm.beginTask("", cus.length); //$NON-NLS-1$
338                         pm.setTaskName(pack.getElementName());
339
340                         List<NonNLSElement> l= new ArrayList<NonNLSElement>(cus.length);
341                         for (int i= 0; i < cus.length; i++){
342                                 pm.subTask(BasicElementLabels.getFileName(cus[i]));
343                                 NonNLSElement element= analyze(cus[i]);
344                                 if (element != null)
345                                         l.add(element);
346                                 pm.worked(1);
347                                 if (pm.isCanceled())
348                                         throw new OperationCanceledException();
349                         }
350                         return l;
351                 } finally {
352                         pm.done();
353                 }
354         }
355
356         /*
357          * returns List of Strings
358          */
359         private List<NonNLSElement> analyze(IPackageFragmentRoot sourceFolder, IProgressMonitor pm) throws CoreException {
360                 try{
361                         IJavaElement[] children= sourceFolder.getChildren();
362                         pm.beginTask("", children.length); //$NON-NLS-1$
363                         pm.setTaskName(JavaElementLabels.getElementLabel(sourceFolder, JavaElementLabels.ALL_DEFAULT));
364                         List<NonNLSElement> result= new ArrayList<NonNLSElement>();
365                         for (int i= 0; i < children.length; i++) {
366                                 IJavaElement iJavaElement= children[i];
367                                 if (iJavaElement.getElementType() == IJavaElement.PACKAGE_FRAGMENT){
368                                         IPackageFragment pack= (IPackageFragment)iJavaElement;
369                                         if (! pack.isReadOnly())
370                                                 result.addAll(analyze(pack, new SubProgressMonitor(pm, 1)));
371                                         else
372                                                 pm.worked(1);
373                                 } else
374                                         pm.worked(1);
375                         }
376                         return result;
377                 } finally{
378                         pm.done();
379                 }
380         }
381
382         /*
383          * returns List of Strings
384          */
385         private List<NonNLSElement> analyze(IJavaProject project, IProgressMonitor pm) throws CoreException {
386                 try{
387                         IPackageFragment[] packs= project.getPackageFragments();
388                         pm.beginTask("", packs.length); //$NON-NLS-1$
389                         List<NonNLSElement> result= new ArrayList<NonNLSElement>();
390                         for (int i= 0; i < packs.length; i++) {
391                                 if (! packs[i].isReadOnly())
392                                         result.addAll(analyze(packs[i], new SubProgressMonitor(pm, 1)));
393                                 else
394                                         pm.worked(1);
395                         }
396                         return result;
397                 } finally{
398                         pm.done();
399                 }
400         }
401
402         private int countStrings() {
403                 int found= 0;
404                 if (fElements != null) {
405                         for (int i= 0; i < fElements.length; i++)
406                                 found+= fElements[i].count;
407                 }
408                 return found;
409         }
410
411         private NonNLSElement analyze(ICompilationUnit cu) throws CoreException {
412                 int count= countNonExternalizedStrings(cu);
413                 if (count == 0)
414                         return null;
415                 else
416                         return new NonNLSElement(cu, count);
417         }
418
419         private int countNonExternalizedStrings(ICompilationUnit cu) throws CoreException {
420                 try{
421                         NLSLine[] lines= NLSScanner.scan(cu);
422                         int result= 0;
423                         for (int i= 0; i < lines.length; i++) {
424                                 result += countNonExternalizedStrings(lines[i]);
425                         }
426                         return result;
427                 } catch (InvalidInputException e) {
428                         throw new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IStatus.ERROR,
429                                         Messages.format(ActionMessages.FindStringsToExternalizeAction_error_cannotBeParsed, BasicElementLabels.getFileName(cu)), e));
430                 } catch (BadLocationException e) {
431                         throw new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IStatus.ERROR, Messages.format(ActionMessages.FindStringsToExternalizeAction_error_cannotBeParsed,
432                                         BasicElementLabels.getFileName(cu)), e));
433                 }
434         }
435
436         private int countNonExternalizedStrings(NLSLine line){
437                 int result= 0;
438                 NLSElement[] elements= line.getElements();
439                 for (int i= 0; i < elements.length; i++){
440                         if (! elements[i].hasTag())
441                                 result++;
442                 }
443                 return result;
444         }
445
446         /**
447          * returns <code>List</code> of <code>IPackageFragments</code>,  <code>IPackageFragmentRoots</code> or
448          * <code>IJavaProjects</code> (all entries are of the same kind)
449          * @param selection the selection
450          * @return the selected elements
451          */
452         private static List<?> getSelectedElementList(IStructuredSelection selection) {
453                 if (selection == null)
454                         return null;
455
456                 return selection.toList();
457         }
458
459         //-------private classes --------------
460
461         private static class NonNLSListDialog extends ListDialog {
462
463                 private static final int OPEN_BUTTON_ID= IDialogConstants.CLIENT_ID + 1;
464
465                 private Button fOpenButton;
466
467                 NonNLSListDialog(Shell parent, NonNLSElement[] input, int count) {
468                         super(parent);
469                         setAddCancelButton(false);
470                         setInput(Arrays.asList(input));
471                         setTitle(ActionMessages.ExternalizeStringsAction_dialog_title);
472                         String message= count == 1 ? ActionMessages.FindStringsToExternalizeAction_non_externalized_singular : Messages.format(
473                                         ActionMessages.FindStringsToExternalizeAction_non_externalized_plural, new Object[] { new Integer(count) });
474                         setMessage(message);
475                         setContentProvider(new ArrayContentProvider());
476                         setLabelProvider(createLabelProvider());
477                 }
478
479                 @Override
480                 protected Point getInitialSize() {
481                         return getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
482                 }
483
484                 @Override
485                 protected Control createDialogArea(Composite parent) {
486                         Composite result= (Composite)super.createDialogArea(parent);
487                         getTableViewer().addSelectionChangedListener(new ISelectionChangedListener(){
488                                 public void selectionChanged(SelectionChangedEvent event){
489                                         if (fOpenButton != null){
490                                                 fOpenButton.setEnabled(! getTableViewer().getSelection().isEmpty());
491                                         }
492                                 }
493                         });
494                         getTableViewer().getTable().addSelectionListener(new SelectionAdapter(){
495                                 @Override
496                                 public void widgetDefaultSelected(SelectionEvent e) {
497                                         NonNLSElement element= (NonNLSElement)e.item.getData();
498                                         element.generated_8353693410935300812(this);
499                                 }
500                         });
501                         getTableViewer().getTable().setFocus();
502                         applyDialogFont(result);
503                         return result;
504                 }
505
506                 @Override
507                 protected void createButtonsForButtonBar(Composite parent) {
508                         fOpenButton= createButton(parent, OPEN_BUTTON_ID, ActionMessages.FindStringsToExternalizeAction_button_label, true);
509                         fOpenButton.setEnabled(false);
510
511                         //looks like a 'close' but it a 'cancel'
512                         createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CLOSE_LABEL, false);
513                 }
514
515                 @Override
516                 protected void buttonPressed(int buttonId) {
517                         if (buttonId != OPEN_BUTTON_ID){
518                                 super.buttonPressed(buttonId);
519                                 return;
520                         }
521                         ISelection s= getTableViewer().getSelection();
522                         if (s instanceof IStructuredSelection){
523                                 IStructuredSelection ss= (IStructuredSelection)s;
524                                 if (ss.getFirstElement() instanceof NonNLSElement)
525                                         ExternalizeWizard.open(((NonNLSElement) ss.getFirstElement()).cu, getShell());
526                         }
527                 }
528
529                 private static LabelProvider createLabelProvider() {
530                         return new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT){
531                                 @Override
532                                 public String getText(Object element) {
533                                         NonNLSElement nlsel= (NonNLSElement)element;
534                                         String elementName= BasicElementLabels.getPathLabel(nlsel.cu.getResource().getFullPath(), false);
535                                         return Messages.format(
536                                                         ActionMessages.FindStringsToExternalizeAction_foundStrings,
537                                                         new Object[] {new Integer(nlsel.count), elementName} );
538                                 }
539                                 @Override
540                                 public Image getImage(Object element) {
541                                         return super.getImage(((NonNLSElement)element).cu);
542                                 }
543                         };
544                 }
545
546                 /*
547                  * @see org.eclipse.jface.window.Window#configureShell(Shell)
548                  */
549                 @Override
550                 protected void configureShell(Shell newShell) {
551                         super.configureShell(newShell);
552                         PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell, IJavaHelpContextIds.NONNLS_DIALOG);
553                 }
554
555
556         }
557
558         static class NonNLSElement{
559                 ICompilationUnit cu;
560                 int count;
561                 NonNLSElement(ICompilationUnit cu, int count){
562                         this.cu= cu;
563                         this.count= count;
564                 }
565                 public void generated_8353693410935300812(SelectionAdapter arg) {
566                         ExternalizeWizard.open(cu, arg.getShell());
567                 }
568         }
569
570 }