KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > tasklist > suggestions > FixAction


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.tasklist.suggestions;
21
22 import java.awt.Component JavaDoc;
23 import java.awt.Dialog JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.Collection JavaDoc;
27 import java.util.Set JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import javax.swing.JButton JavaDoc;
30 import javax.swing.JEditorPane JavaDoc;
31 import org.netbeans.modules.tasklist.client.SuggestionPerformer;
32 import org.netbeans.modules.tasklist.client.SuggestionManager;
33 import org.openide.cookies.EditorCookie;
34 import org.openide.ErrorManager;
35 import org.openide.DialogDescriptor;
36 import org.openide.DialogDisplayer;
37 import org.openide.loaders.DataObject;
38 import org.openide.NotifyDescriptor;
39 import org.openide.awt.Actions;
40 import org.openide.nodes.Node;
41 import org.openide.util.HelpCtx;
42 import org.openide.util.NbBundle;
43 import org.openide.util.actions.NodeAction;
44 import org.netbeans.modules.tasklist.core.*;
45 import org.openide.awt.Mnemonics;
46
47 /**
48  * Automatically fix a task for which a fix-method has been registered
49  *
50  * @todo Performance enhancement: when fixing many suggestions, reuse
51  * the DialogDescriptor and button objects; just replace the main pane
52  * contents.
53  *
54  * @author Tor Norbye
55  */

56
57 public final class FixAction extends NodeAction {
58
59     private static final long serialVersionUID = 1;
60
61     protected boolean asynchronous() {
62         return false;
63     }
64     
65     protected boolean enable(Node[] node) {
66         if ((node == null) || (node.length < 1)) {
67             return false;
68         }
69         boolean enabled = false;
70         for (int i = 0; i < node.length; i++) {
71             Task task = TaskNode.getTask(node[i]);
72             if ((task != null) && (task.getAction() != null)) {
73                 enabled = true;
74             }
75         }
76         return enabled;
77     }
78
79     protected void performAction(Node[] node) {
80         SuggestionManagerImpl manager =
81              (SuggestionManagerImpl)SuggestionManager.getDefault();
82
83         boolean skipConfirm = false;
84
85         assert node[0] instanceof SuggestionNode : "Need to be softened later on";
86         TaskListView tlv = TaskListView.getCurrent();
87         // todo this line causes NPE ((SuggestionNode)node[0]).getView();
88

89         Collection JavaDoc originalModified =
90             new ArrayList JavaDoc(DataObject.getRegistry().getModifiedSet());
91         boolean fixingStarted = false;
92         try {
93
94         for (int i = 0; i < node.length; i++) {
95             SuggestionImpl item = (SuggestionImpl)TaskNode.getTask(node[i]);
96             if (item == null) {
97                 continue;
98             }
99
100             SuggestionPerformer performer = item.getAction();
101             if (performer == null) {
102                 continue;
103             }
104             
105             boolean doConfirm = manager.isConfirm(item.getSType());
106             Object JavaDoc confirmation = null;
107             if (doConfirm && !skipConfirm && performer.hasConfirmation()) {
108                 confirmation = performer.getConfirmation(item);
109             }
110             if (confirmation != null) {
111                 // Show in source editor as well, if possible
112
if (tlv != null) {
113                     tlv.showTaskInEditor(item, new SuggestionAnno(item));
114                     tlv.select(item);
115                 }
116
117                 JButton JavaDoc fixButton = new JButton JavaDoc();
118                 Mnemonics.setLocalizedText(fixButton, NbBundle.getMessage(FixAction.class, "FixIt"));
119                 
120                 JButton JavaDoc fixAllButton = null;
121                 JButton JavaDoc skipButton = null;
122                 if (node.length > 1) {
123                     fixAllButton = new JButton JavaDoc();
124                     Mnemonics.setLocalizedText(fixAllButton,
125                                         NbBundle.getMessage(FixAction.class,
126                                                        "FixAll"));
127                     skipButton = new JButton JavaDoc();
128                     Mnemonics.setLocalizedText(skipButton,
129                                         NbBundle.getMessage(FixAction.class,
130                                                        "Skip"));
131                     fixAllButton.getAccessibleContext().setAccessibleDescription(
132                         NbBundle.getMessage(FixAction.class,
133                                           "ACSD_FixAll")); // NOI18N
134
skipButton.getAccessibleContext().setAccessibleDescription(
135                         NbBundle.getMessage(FixAction.class,
136                                           "ACSD_Skip")); // NOI18N
137
}
138                 JButton JavaDoc cancelButton = new JButton JavaDoc();
139                 Mnemonics.setLocalizedText(cancelButton,
140                    NbBundle.getMessage(FixAction.class, "Cancel"));
141
142                 if (confirmation instanceof Component JavaDoc) {
143                     ((Component JavaDoc)confirmation).getAccessibleContext().
144                         setAccessibleDescription(
145                                    NbBundle.getMessage(FixAction.class,
146                                          "ACSD_Confirmation")); // NOI18N
147
}
148                 fixButton.getAccessibleContext().setAccessibleDescription(
149                       NbBundle.getMessage(FixAction.class,
150                                           "ACSD_Fix")); // NOI18N
151
cancelButton.getAccessibleContext().setAccessibleDescription(
152                       NbBundle.getMessage(FixAction.class,
153                                           "ACSD_Cancel")); // NOI18N
154

155                 String JavaDoc title = NbBundle.getMessage(FixAction.class, "TITLE_fixconfirm");
156                 DialogDescriptor dlg = new DialogDescriptor(
157                        confirmation,
158                        title,
159                        true,
160                        (node.length > 1) ?
161                        new JButton JavaDoc [] {
162                           fixButton,
163                           skipButton,
164                           fixAllButton,
165                           cancelButton
166                        }
167                        :
168                        new JButton JavaDoc [] {
169                           fixButton,
170                           cancelButton
171                        },
172                     
173                        fixButton,
174                        DialogDescriptor.DEFAULT_ALIGN,
175                        null,
176                        null);
177                 dlg.setMessageType(NotifyDescriptor.PLAIN_MESSAGE);
178                 /* Don't include a confirmation-suppression toggle on
179                    the dialog itself - users may think they have fine
180                    control over confirmations (e.g. that they can skip
181                    confirmations for only the unused-imports removal
182                    in PMD).
183
184                    Instead, they can turn off confirmations in the
185                    Edit Types... dialog - and once they know how to do
186                    that, they also know how to get it back - and they
187                    will also see the granularity of the types they
188                    are manipulating.
189                 JCheckBox noConfirmButton = new JCheckBox();
190                 Actions.setMenuText(noConfirmButton,
191                    NbBundle.getMessage(FixAction.class, "NoConfirm"), true); // NOI18N
192                 
193         dlg.setAdditionalOptions(new Object[] {
194                                            noConfirmButton
195                                          });
196                 */

197
198                 dlg.setModal(true);
199                 final Dialog JavaDoc dialog = DialogDisplayer.getDefault().createDialog(dlg);
200                 dialog.pack();
201                 dialog.setVisible(true);
202                 Object JavaDoc pressedButton = dlg.getValue();
203
204                 if (tlv != null) {
205                     tlv.showTaskInEditor(null, null);
206                 }
207                 
208                 if (pressedButton == cancelButton) {
209                     break; // CANCELLED
210
} else if (pressedButton == fixAllButton) {
211                     skipConfirm = true;
212                 } else if (pressedButton == skipButton) {
213                     // [PENDING] Remove the item, but don't actually perform it
214
//manager.register(itemType, null, itemList);
215

216                     continue;
217                 } else if (pressedButton != fixButton) {
218                     // For example if you Escape or close the window.
219
// See issue 32149.
220
continue;
221                 }
222                 
223                 /* Removed - see comment above declaration
224                 if (noConfirmButton.isSelected()) {
225                     manager.setConfirm(((SuggestionImpl)item).getSType(), false, true);
226                 }
227                 */

228             }
229             if (!fixingStarted) {
230                 fixingStarted = true;
231                 manager.setFixing(true);
232             }
233             if (item.isZombie()) {
234                 // It looks like this item has already been removed. This
235
// is due to a race condition, where you double click on
236
// a task (to fix it) just as the list is getting rescanned,
237
// so the task you selected gets removed and is gone by
238
// time time the user reaches the confirmation dialog and
239
// selects OK.
240

241                 // In this case, try to identify a "replacement" suggestion:
242
// the same suggestion in the newly updated list.
243
// And how do we know if two tasks are identical?
244
// They should
245
// - have the same stype
246
// - have the same description
247
// - have the same line? (well, the task may have moved.
248
// This one is tricky because on the other hand,
249
// it's not uncommon to have the same task listed
250
// repeatedly just varying in line numbers
251
// (e.g. the AvoidDuplicateLiterals rule violation)
252
// so it seems like a good criterion to be sure.
253
// The best solution might be to count the number
254
// of matches and if just one, but with a different
255
// line number, use it.
256
// - have the same priority
257
// We don't scan for the following since it's unlikely that
258
// the the above will match and not the following
259
// (and searching for icon equality for example
260
// is a bit harder.)
261
// - have the same icon
262
// - have the same details
263
//
264
int matches = 0;
265                 Iterator JavaDoc it = item.getParent().subtasksIterator();
266                 SuggestionImpl match = null;
267                 boolean exact = false;
268                 while (it.hasNext()) {
269                     SuggestionImpl sm = (SuggestionImpl)it.next();
270                     if (sm.hasSubtasks()) {
271                         // It's a category node
272
Iterator JavaDoc it2 = sm.subtasksIterator();
273                         while (it2.hasNext()) {
274                             SuggestionImpl sm2 = (SuggestionImpl)it2.next();
275                             if ((item.getSType() == sm2.getSType()) &&
276                                 item.getSummary().equals(sm2.getSummary()) &&
277                                 (item.getPriority() == sm2.getPriority()) &&
278                                 (item.getPriority() == sm2.getPriority())) {
279                                 match = sm2;
280                                 matches++;
281                                 if (item.getLine().equals(sm2.getLine())) {
282                                     exact = true;
283                                     break;
284                                 }
285                             }
286                         }
287                         if (exact) {
288                             break;
289                         }
290                     } else {
291                         if ((item.getSType() == sm.getSType()) &&
292                             item.getSummary().equals(sm.getSummary()) &&
293                             (item.getPriority() == sm.getPriority()) &&
294                             (item.getPriority() == sm.getPriority())) {
295                             match = sm;
296                             matches++;
297                             if (item.getLine().equals(sm.getLine())) {
298                                 exact = true;
299                                 break;
300                             }
301                         }
302                     }
303                 }
304                 if ((match != null) && (exact || (matches == 1))) {
305                     //System.err.println("Replaced task " + item + " with task " + match + " (they are equal=" + (item == match));
306
item = match;
307                 } else {
308                     // We haven't found a match. It's probably best to
309
// stick with the old item, since the Action will
310
// probably still work (even though the item won't
311
// get removed from the list by the register call
312
// below.
313

314                     //System.err.println("No match. matches=" + matches + " match=" + match + " exact=" + exact + " item=" + item);
315
}
316             }
317             performer.perform(item);
318             
319             // XXX Remove suggestion when we've performed it
320
// INSTED action is reponsible for marking suggestion as invalid
321
// List itemList = new ArrayList(1);
322
// itemList.add(item);
323
// manager.register(item.getSType().getName(), null, itemList, sList, true);
324
}
325         } finally {
326             if (fixingStarted) {
327                 manager.setFixing(false);
328             }
329         }
330         
331         // Handle files that have been modified by the fix operation.
332
// It's not as simple as looking at the Line objects for the
333
// tasks that we've fixed but not done a line.show() on since
334
// actions are allowed to modify ANY files. For example, the
335
// javaparser module can create a new method in a different
336
// class. So instead we diff the modified files list before
337
// and after fix, and for the newly modified files, check if
338
// they are open. (Hm, how the heck do we do that? They have
339
// open documents.... how can I check if they have an actual
340
// editor? Will the EditorCookie help?)
341

342         // See if the set of modified files have changed
343
Set JavaDoc modifiedRO = DataObject.getRegistry().getModifiedSet();
344         Set JavaDoc modified = new java.util.HashSet JavaDoc(modifiedRO);
345         modified.removeAll(originalModified);
346         
347         boolean haveModified = false;
348         Iterator JavaDoc it = modified.iterator();
349         while (it.hasNext()) {
350             DataObject dao = (DataObject)it.next();
351             EditorCookie cookie =
352                 (EditorCookie)dao.getCookie(EditorCookie.class);
353             if (cookie != null) {
354                 JEditorPane JavaDoc[] panes = cookie.getOpenedPanes();
355                 if ((panes == null) || (panes.length == 0)) {
356                     haveModified = true;
357                 }
358             }
359         }
360         if (haveModified) {
361                 JButton JavaDoc openFiles = new JButton JavaDoc();
362                 Mnemonics.setLocalizedText(openFiles,
363                    NbBundle.getMessage(FixAction.class,
364                                        "ShowFiles"));
365                 
366                 JButton JavaDoc selectFiles = new JButton JavaDoc();
367                 Mnemonics.setLocalizedText(selectFiles,
368                    NbBundle.getMessage(FixAction.class,
369                                        "SelectFiles"));
370                 
371                 JButton JavaDoc saveFiles = new JButton JavaDoc();
372                 Mnemonics.setLocalizedText(saveFiles,
373                    NbBundle.getMessage(FixAction.class,
374                                        "SaveAllFiles"));
375                 
376                 JButton JavaDoc cancelButton = new JButton JavaDoc();
377                 Mnemonics.setLocalizedText(cancelButton,
378                    NbBundle.getMessage(FixAction.class,
379                                        "Cancel"));
380                 
381                 String JavaDoc title = NbBundle.getMessage(FixAction.class,
382                                                    "FixSavesTitle");
383                 DialogDescriptor dlg = new DialogDescriptor(
384                        NbBundle.getMessage(FixAction.class,
385                                            "FixFileSaves"), // NOI18N
386
title,
387                        true,
388                        (node.length > 1) ?
389                        new JButton JavaDoc [] {
390                           openFiles,
391                           // NOT YET IMPLEMENTED: selectFiles,
392
saveFiles,
393                           cancelButton
394                        }
395                        :
396                        new JButton JavaDoc [] {
397                           openFiles,
398                           // NOT YET IMPLEMENTED: selectFiles,
399
saveFiles,
400                           cancelButton
401                        },
402                     
403                        openFiles,
404                        DialogDescriptor.DEFAULT_ALIGN,
405                        null,
406                        null);
407                 dlg.setMessageType(NotifyDescriptor.PLAIN_MESSAGE);
408                 dlg.setModal(true);
409                 final Dialog JavaDoc dialog =
410                     DialogDisplayer.getDefault().createDialog(dlg);
411                 dialog.pack();
412                 dialog.setVisible(true);
413                 Object JavaDoc pressedButton = dlg.getValue();
414
415                 if (pressedButton == openFiles) {
416                     it = modified.iterator();
417                     while (it.hasNext()) {
418                         DataObject dao = (DataObject)it.next();
419                         EditorCookie cookie =
420                             (EditorCookie)dao.getCookie(EditorCookie.class);
421                         if (cookie != null) {
422                             cookie.open();
423                         }
424                     }
425                 } else if (pressedButton == saveFiles) {
426                     it = modified.iterator();
427                     while (it.hasNext()) {
428                         DataObject dao = (DataObject)it.next();
429                         EditorCookie cookie =
430                             (EditorCookie)dao.getCookie(EditorCookie.class);
431                         if (cookie != null) {
432                             try {
433                                 cookie.saveDocument();
434                             } catch (Exception JavaDoc e) {
435                                 ErrorManager.getDefault().notify(
436                                                ErrorManager.WARNING, e);
437                             }
438                         }
439                     }
440                 } else if (pressedButton == selectFiles) {
441                     //XXX TODO!
442
}
443         }
444     }
445     
446     public String JavaDoc getName() {
447         return NbBundle.getMessage(FixAction.class, "LBL_FixConfirm"); // NOI18N
448
}
449
450     protected String JavaDoc iconResource() {
451         return "org/netbeans/modules/tasklist/suggestions/fix.gif"; // NOI18N
452
}
453     
454     public HelpCtx getHelpCtx() {
455         return HelpCtx.DEFAULT_HELP;
456         // If you will provide context help then use:
457
// return new HelpCtx (NewTodoItemAction.class);
458
}
459     
460 }
461
Popular Tags