001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.refactoring.java.ui;
043:
044: import com.sun.source.tree.Tree;
045: import com.sun.source.util.TreePath;
046: import java.util.Collection;
047: import java.util.HashSet;
048: import java.util.List;
049: import javax.lang.model.element.Element;
050: import javax.lang.model.element.ElementKind;
051: import org.netbeans.api.java.source.CompilationInfo;
052: import org.netbeans.api.java.source.TreePathHandle;
053: import org.netbeans.modules.refactoring.java.RetoucheUtils;
054: import org.netbeans.modules.refactoring.java.api.ui.JavaRefactoringActionsFactory;
055: import org.netbeans.modules.refactoring.java.spi.ui.JavaActionsImplementationProvider;
056: import org.netbeans.modules.refactoring.java.ui.RefactoringActionsProvider.NodeToFileObjectTask;
057: import org.netbeans.modules.refactoring.java.ui.RefactoringActionsProvider.TreePathHandleTask;
058: import org.netbeans.modules.refactoring.spi.ui.RefactoringUI;
059: import org.openide.cookies.EditorCookie;
060: import org.openide.filesystems.FileObject;
061: import org.openide.loaders.DataObject;
062: import org.openide.nodes.Node;
063: import org.openide.util.Lookup;
064:
065: /**
066: *
067: * @author Jan Becicka
068: */
069: public class JavaRefactoringActionsProvider extends
070: JavaActionsImplementationProvider {
071:
072: public JavaRefactoringActionsProvider() {
073: }
074:
075: @Override
076: public void doExtractInterface(final Lookup lookup) {
077: Runnable task;
078: EditorCookie ec = lookup.lookup(EditorCookie.class);
079: if (RefactoringActionsProvider.isFromEditor(ec)) {
080: task = new RefactoringActionsProvider.TextComponentTask(ec) {
081: @Override
082: protected RefactoringUI createRefactoringUI(
083: TreePathHandle selectedElement,
084: int startOffset, int endOffset,
085: CompilationInfo info) {
086: return new ExtractInterfaceRefactoringUI(
087: selectedElement, info);
088: }
089: };
090: } else if (RefactoringActionsProvider.nodeHandle(lookup)) {
091: task = new TreePathHandleTask(new HashSet(lookup
092: .lookupAll(Node.class))) {
093: @Override
094: protected RefactoringUI createRefactoringUI(
095: Collection<TreePathHandle> handles,
096: CompilationInfo cinfo) {
097: return new ExtractInterfaceRefactoringUI(handles
098: .iterator().next(), cinfo);
099: }
100: };
101: } else {
102: task = new NodeToFileObjectTask(new HashSet(lookup
103: .lookupAll(Node.class))) {
104: @Override
105: protected RefactoringUI createRefactoringUI(
106: FileObject[] selectedElements,
107: Collection<TreePathHandle> handles) {
108: TreePathHandle tph = handles.iterator().next();
109: return new ExtractInterfaceRefactoringUI(tph, cinfo
110: .get());
111: }
112: };
113: }
114: RetoucheUtils.invokeAfterScanFinished(task,
115: RefactoringActionsProvider
116: .getActionName(JavaRefactoringActionsFactory
117: .extractInterfaceAction()));
118: }
119:
120: @Override
121: public boolean canExtractInterface(Lookup lookup) {
122: Collection<? extends Node> nodes = new HashSet(lookup
123: .lookupAll(Node.class));
124: if (nodes.size() != 1) {
125: return false;
126: }
127: Node n = nodes.iterator().next();
128: if (n.getLookup().lookup(TreePathHandle.class) != null) {
129: return true;
130: }
131: DataObject dob = n.getCookie(DataObject.class);
132: if (dob == null) {
133: return false;
134: }
135: FileObject fo = dob.getPrimaryFile();
136: if (RetoucheUtils.isRefactorable(fo)) { //NOI18N
137: return true;
138: }
139: return false;
140: }
141:
142: @Override
143: public void doExtractSuperclass(Lookup lookup) {
144: Runnable task;
145: EditorCookie ec = lookup.lookup(EditorCookie.class);
146: if (RefactoringActionsProvider.isFromEditor(ec)) {
147: task = new RefactoringActionsProvider.TextComponentTask(ec) {
148: @Override
149: protected RefactoringUI createRefactoringUI(
150: TreePathHandle selectedElement,
151: int startOffset, int endOffset,
152: CompilationInfo info) {
153: return new ExtractSuperclassRefactoringUI(
154: selectedElement, info);
155: }
156: };
157: } else if (RefactoringActionsProvider.nodeHandle(lookup)) {
158: task = new TreePathHandleTask(new HashSet(lookup
159: .lookupAll(Node.class))) {
160: @Override
161: protected RefactoringUI createRefactoringUI(
162: Collection<TreePathHandle> handles,
163: CompilationInfo cinfo) {
164: return new ExtractSuperclassRefactoringUI(handles
165: .iterator().next(), cinfo);
166: }
167: };
168: } else {
169: task = new NodeToFileObjectTask(new HashSet(lookup
170: .lookupAll(Node.class))) {
171: @Override
172: protected RefactoringUI createRefactoringUI(
173: FileObject[] selectedElements,
174: Collection<TreePathHandle> handles) {
175: TreePathHandle tph = handles.iterator().next();
176: return new ExtractSuperclassRefactoringUI(tph,
177: cinfo.get());
178: }
179: };
180: }
181: RetoucheUtils.invokeAfterScanFinished(task,
182: RefactoringActionsProvider
183: .getActionName(JavaRefactoringActionsFactory
184: .extractSuperclassAction()));
185: }
186:
187: @Override
188: public boolean canExtractSuperclass(Lookup lookup) {
189: Collection<? extends Node> nodes = new HashSet(lookup
190: .lookupAll(Node.class));
191: if (nodes.size() != 1) {
192: return false;
193: }
194: Node n = nodes.iterator().next();
195: if (n.getLookup().lookup(TreePathHandle.class) != null) {
196: return true;
197: }
198: DataObject dob = n.getCookie(DataObject.class);
199: if (dob == null) {
200: return false;
201: }
202: FileObject fo = dob.getPrimaryFile();
203: if (RetoucheUtils.isRefactorable(fo)) { //NOI18N
204: return true;
205: }
206: return false;
207: }
208:
209: @Override
210: public void doPushDown(final Lookup lookup) {
211: Runnable task;
212: EditorCookie ec = lookup.lookup(EditorCookie.class);
213: if (RefactoringActionsProvider.isFromEditor(ec)) {
214: task = new RefactoringActionsProvider.TextComponentTask(ec) {
215: @Override
216: protected RefactoringUI createRefactoringUI(
217: TreePathHandle selectedElement,
218: int startOffset, int endOffset,
219: CompilationInfo info) {
220: Element selected = selectedElement
221: .resolveElement(info);
222: if (selected.getKind() == ElementKind.PACKAGE) {
223: List<? extends Tree> typeDecls = info
224: .getCompilationUnit().getTypeDecls();
225: if (typeDecls == null || typeDecls.isEmpty()) {
226: return null;
227: }
228: selectedElement = TreePathHandle.create(info
229: .getTrees().getPath(
230: info.getCompilationUnit(),
231: typeDecls.get(0)), info);
232: } else if (selected.getKind() == ElementKind.LOCAL_VARIABLE
233: || selected.getKind() == ElementKind.PARAMETER
234: || selected.getKind() == ElementKind.TYPE_PARAMETER) {
235: TreePath path = info.getTrees().getPath(
236: info.getTypes().asElement(
237: selected.asType()));
238: if (path == null)
239: return null;
240: selectedElement = TreePathHandle.create(path,
241: info);
242: }
243: return new PushDownRefactoringUI(
244: new TreePathHandle[] { selectedElement },
245: info);
246: }
247: };
248: } else if (RefactoringActionsProvider.nodeHandle(lookup)) {
249: task = new TreePathHandleTask(new HashSet(lookup
250: .lookupAll(Node.class))) {
251: @Override
252: protected RefactoringUI createRefactoringUI(
253: Collection<TreePathHandle> handles,
254: CompilationInfo cinfo) {
255: return new PushDownRefactoringUI(
256: handles.toArray(new TreePathHandle[handles
257: .size()]), cinfo);
258: }
259:
260: };
261: } else {
262: task = new NodeToFileObjectTask(new HashSet(lookup
263: .lookupAll(Node.class))) {
264: @Override
265: protected RefactoringUI createRefactoringUI(
266: FileObject[] selectedElements,
267: Collection<TreePathHandle> handles) {
268: return new PushDownRefactoringUI(
269: new TreePathHandle[] { handles.iterator()
270: .next() }, cinfo.get());
271: }
272: };
273: }
274: RetoucheUtils.invokeAfterScanFinished(task,
275: RefactoringActionsProvider
276: .getActionName(JavaRefactoringActionsFactory
277: .pushDownAction()));
278: }
279:
280: @Override
281: public boolean canPushDown(Lookup lookup) {
282: Collection<? extends Node> nodes = new HashSet(lookup
283: .lookupAll(Node.class));
284: if (nodes.size() != 1) {
285: return false;
286: }
287: Node n = nodes.iterator().next();
288: if (n.getLookup().lookup(TreePathHandle.class) != null) {
289: return true;
290: }
291: DataObject dob = n.getCookie(DataObject.class);
292: if (dob == null) {
293: return false;
294: }
295: FileObject fo = dob.getPrimaryFile();
296: if (RetoucheUtils.isRefactorable(fo)) { //NOI18N
297: return true;
298: }
299: return false;
300: }
301:
302: @Override
303: public void doPullUp(final Lookup lookup) {
304: Runnable task;
305: EditorCookie ec = lookup.lookup(EditorCookie.class);
306: if (RefactoringActionsProvider.isFromEditor(ec)) {
307: task = new RefactoringActionsProvider.TextComponentTask(ec) {
308: @Override
309: protected RefactoringUI createRefactoringUI(
310: TreePathHandle selectedElement,
311: int startOffset, int endOffset,
312: CompilationInfo info) {
313: Element selected = selectedElement
314: .resolveElement(info);
315:
316: if (selected.getKind() == ElementKind.PACKAGE) {
317: List<? extends Tree> typeDecls = info
318: .getCompilationUnit().getTypeDecls();
319: if (typeDecls == null || typeDecls.isEmpty()) {
320: return null;
321: }
322: selectedElement = TreePathHandle.create(info
323: .getTrees().getPath(
324: info.getCompilationUnit(),
325: typeDecls.get(0)), info);
326: } else if (selected.getKind() == ElementKind.LOCAL_VARIABLE
327: || selected.getKind() == ElementKind.PARAMETER
328: || selected.getKind() == ElementKind.TYPE_PARAMETER) {
329: TreePath path = info.getTrees().getPath(
330: info.getTypes().asElement(
331: selected.asType()));
332: if (path == null)
333: return null;
334: selectedElement = TreePathHandle.create(path,
335: info);
336: }
337: return new PullUpRefactoringUI(
338: new TreePathHandle[] { selectedElement },
339: info);
340: }
341: };
342: } else if (RefactoringActionsProvider.nodeHandle(lookup)) {
343: task = new TreePathHandleTask(new HashSet(lookup
344: .lookupAll(Node.class))) {
345:
346: @Override
347: protected RefactoringUI createRefactoringUI(
348: Collection<TreePathHandle> handles,
349: CompilationInfo cinfo) {
350: return new PullUpRefactoringUI(
351: handles.toArray(new TreePathHandle[handles
352: .size()]), cinfo);
353: }
354:
355: };
356: } else {
357: task = new NodeToFileObjectTask(new HashSet(lookup
358: .lookupAll(Node.class))) {
359: @Override
360: protected RefactoringUI createRefactoringUI(
361: FileObject[] selectedElements,
362: Collection<TreePathHandle> handles) {
363: return new PullUpRefactoringUI(
364: new TreePathHandle[] { handles.iterator()
365: .next() }, cinfo.get());
366: }
367: };
368: }
369: RetoucheUtils.invokeAfterScanFinished(task,
370: RefactoringActionsProvider
371: .getActionName(JavaRefactoringActionsFactory
372: .pullUpAction()));
373: }
374:
375: @Override
376: public boolean canPullUp(Lookup lookup) {
377: Collection<? extends Node> nodes = new HashSet(lookup
378: .lookupAll(Node.class));
379: if (nodes.size() != 1) {
380: return false;
381: }
382: Node n = nodes.iterator().next();
383: if (n.getLookup().lookup(TreePathHandle.class) != null) {
384: return true;
385: }
386: DataObject dob = n.getCookie(DataObject.class);
387: if (dob == null) {
388: return false;
389: }
390: FileObject fo = dob.getPrimaryFile();
391: if (RetoucheUtils.isRefactorable(fo)) { //NOI18N
392: return true;
393: }
394: return false;
395: }
396:
397: @Override
398: public boolean canUseSuperType(Lookup lookup) {
399: Collection<? extends Node> nodes = new HashSet(lookup
400: .lookupAll(Node.class));
401: if (nodes.size() != 1)
402: return false;
403: Node node = nodes.iterator().next();
404: if (node.getLookup().lookup(TreePathHandle.class) != null) {
405: return true;
406: }
407: DataObject dObj = node.getCookie(DataObject.class);
408: if (null == dObj)
409: return false;
410: FileObject fileObj = dObj.getPrimaryFile();
411: if (null == fileObj || !RetoucheUtils.isRefactorable(fileObj))
412: return false;
413:
414: return true;
415: }
416:
417: @Override
418: public void doUseSuperType(Lookup lookup) {
419: Runnable task;
420: EditorCookie ec = lookup.lookup(EditorCookie.class);
421: if (RefactoringActionsProvider.isFromEditor(ec)) {
422: task = new RefactoringActionsProvider.TextComponentTask(ec) {
423: protected RefactoringUI createRefactoringUI(
424: TreePathHandle selectedElement,
425: int startOffset, int endOffset,
426: CompilationInfo info) {
427: Element selected = selectedElement
428: .resolveElement(info);
429: TreePathHandle s = selectedElement;
430: if (!(selected.getKind().isClass() || selected
431: .getKind().isInterface())) {
432: s = TreePathHandle.create(RetoucheUtils
433: .findEnclosingClass(info,
434: selectedElement.resolve(info),
435: true, true, true, true, true),
436: info);
437: }
438: return new UseSuperTypeRefactoringUI(s);
439: }
440: };
441: RetoucheUtils
442: .invokeAfterScanFinished(
443: task,
444: RefactoringActionsProvider
445: .getActionName(JavaRefactoringActionsFactory
446: .useSuperTypeAction()));
447: }
448: }
449:
450: @Override
451: public boolean canChangeParameters(Lookup lookup) {
452: Collection<? extends Node> nodes = new HashSet(lookup
453: .lookupAll(Node.class));
454: if (nodes.size() != 1)
455: return false;
456: Node node = nodes.iterator().next();
457: if (node.getLookup().lookup(TreePathHandle.class) != null) {
458: return true;
459: }
460: DataObject dObj = node.getCookie(DataObject.class);
461: if (null == dObj)
462: return false;
463: FileObject fileObj = dObj.getPrimaryFile();
464: if (null == fileObj || !RetoucheUtils.isRefactorable(fileObj))
465: return false;
466:
467: EditorCookie ec = lookup.lookup(EditorCookie.class);
468: if (RefactoringActionsProvider.isFromEditor(ec)) {
469: return true;
470: }
471: return false;
472: }
473:
474: @Override
475: public void doChangeParameters(Lookup lookup) {
476: Runnable task;
477: EditorCookie ec = lookup.lookup(EditorCookie.class);
478: if (ec != null) {
479: task = new RefactoringActionsProvider.TextComponentTask(ec) {
480: protected RefactoringUI createRefactoringUI(
481: TreePathHandle selectedElement,
482: int startOffset, int endOffset,
483: CompilationInfo info) {
484: Element selected = selectedElement
485: .resolveElement(info);
486: return new ChangeParametersUI(selectedElement, info);
487: }
488: };
489: } else {
490: task = new TreePathHandleTask(new HashSet(lookup
491: .lookupAll(Node.class))) {
492: @Override
493: protected RefactoringUI createRefactoringUI(
494: Collection<TreePathHandle> handles,
495: CompilationInfo cinfo) {
496: return new ChangeParametersUI(handles.iterator()
497: .next(), cinfo);
498: }
499: };
500: }
501: RetoucheUtils.invokeAfterScanFinished(task,
502: RefactoringActionsProvider
503: .getActionName(JavaRefactoringActionsFactory
504: .changeParametersAction()));
505: }
506:
507: @Override
508: public boolean canInnerToOuter(Lookup lookup) {
509: Collection<? extends Node> nodes = new HashSet(lookup
510: .lookupAll(Node.class));
511: if (nodes.size() != 1)
512: return false;
513: Node node = nodes.iterator().next();
514: if (node.getLookup().lookup(TreePathHandle.class) != null) {
515: return true;
516: }
517: DataObject dObj = node.getCookie(DataObject.class);
518: if (null == dObj)
519: return false;
520: FileObject fileObj = dObj.getPrimaryFile();
521: if (null == fileObj || !RetoucheUtils.isRefactorable(fileObj))
522: return false;
523:
524: EditorCookie ec = lookup.lookup(EditorCookie.class);
525: if (RefactoringActionsProvider.isFromEditor(ec)) {
526: return true;
527: }
528: return false;
529: }
530:
531: @Override
532: public void doInnerToOuter(Lookup lookup) {
533: Runnable task;
534: EditorCookie ec = lookup.lookup(EditorCookie.class);
535: if (ec != null) {
536: task = new RefactoringActionsProvider.TextComponentTask(ec) {
537:
538: protected RefactoringUI createRefactoringUI(
539: TreePathHandle selectedElement,
540: int startOffset, int endOffset,
541: CompilationInfo info) {
542: Element selected = selectedElement
543: .resolveElement(info);
544: return new InnerToOuterRefactoringUI(
545: selectedElement, info);
546: }
547: };
548: } else {
549: task = new TreePathHandleTask(new HashSet(lookup
550: .lookupAll(Node.class))) {
551:
552: @Override
553: protected RefactoringUI createRefactoringUI(
554: Collection<TreePathHandle> handles,
555: CompilationInfo cinfo) {
556: return new InnerToOuterRefactoringUI(handles
557: .iterator().next(), cinfo);
558: }
559:
560: };
561: }
562: RetoucheUtils.invokeAfterScanFinished(task,
563: RefactoringActionsProvider
564: .getActionName(JavaRefactoringActionsFactory
565: .innerToOuterAction()));
566: }
567:
568: @Override
569: public boolean canEncapsulateFields(Lookup lookup) {
570: Collection<? extends Node> nodes = new HashSet(lookup
571: .lookupAll(Node.class));
572: if (nodes.size() != 1) {
573: return false;
574: }
575: Node n = nodes.iterator().next();
576: if (n.getLookup().lookup(TreePathHandle.class) != null) {
577: return true;
578: }
579: DataObject dob = n.getCookie(DataObject.class);
580: if (dob == null) {
581: return false;
582: }
583: FileObject fo = dob.getPrimaryFile();
584: if (RetoucheUtils.isRefactorable(fo)) { //NOI18N
585: return true;
586: }
587: return false;
588: }
589:
590: @Override
591: public void doEncapsulateFields(Lookup lookup) {
592: Runnable task;
593: EditorCookie ec = lookup.lookup(EditorCookie.class);
594: if (RefactoringActionsProvider.isFromEditor(ec)) {
595: task = new RefactoringActionsProvider.TextComponentTask(ec) {
596: @Override
597: protected RefactoringUI createRefactoringUI(
598: TreePathHandle selectedElement,
599: int startOffset, int endOffset,
600: CompilationInfo info) {
601: return new EncapsulateFieldUI(selectedElement, info);
602: }
603: };
604: } else if (RefactoringActionsProvider.nodeHandle(lookup)) {
605: task = new TreePathHandleTask(new HashSet(lookup
606: .lookupAll(Node.class))) {
607:
608: @Override
609: protected RefactoringUI createRefactoringUI(
610: Collection<TreePathHandle> handles,
611: CompilationInfo cinfo) {
612: return new EncapsulateFieldUI(handles.iterator()
613: .next(), cinfo);
614: }
615:
616: };
617: } else {
618: task = new NodeToFileObjectTask(new HashSet(lookup
619: .lookupAll(Node.class))) {
620: @Override
621: protected RefactoringUI createRefactoringUI(
622: FileObject[] selectedElements,
623: Collection<TreePathHandle> handles) {
624: TreePathHandle tph = handles.iterator().next();
625: return new EncapsulateFieldUI(tph, cinfo.get());
626: }
627: };
628: }
629: RetoucheUtils.invokeAfterScanFinished(task,
630: RefactoringActionsProvider
631: .getActionName(JavaRefactoringActionsFactory
632: .encapsulateFieldsAction()));
633: }
634: }
|