KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > java > editor > codegen > DelegateMethodGenerator


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 package org.netbeans.modules.java.editor.codegen;
20
21 import com.sun.source.tree.BlockTree;
22 import com.sun.source.tree.ClassTree;
23 import com.sun.source.tree.ExpressionTree;
24 import com.sun.source.tree.MethodTree;
25 import com.sun.source.tree.Scope;
26 import com.sun.source.tree.StatementTree;
27 import com.sun.source.tree.Tree;
28 import com.sun.source.tree.TypeParameterTree;
29 import com.sun.source.tree.VariableTree;
30 import com.sun.source.util.SourcePositions;
31 import com.sun.source.util.TreePath;
32 import com.sun.source.util.Trees;
33 import java.awt.Dialog JavaDoc;
34 import java.io.IOException JavaDoc;
35 import java.util.ArrayList JavaDoc;
36 import java.util.Collections JavaDoc;
37 import java.util.EnumSet JavaDoc;
38 import java.util.Iterator JavaDoc;
39 import java.util.LinkedHashMap JavaDoc;
40 import java.util.List JavaDoc;
41 import java.util.Map JavaDoc;
42 import java.util.Set JavaDoc;
43 import javax.lang.model.element.Element;
44 import javax.lang.model.element.ExecutableElement;
45 import javax.lang.model.element.Modifier;
46 import javax.lang.model.element.TypeElement;
47 import javax.lang.model.element.VariableElement;
48 import javax.lang.model.type.DeclaredType;
49 import javax.lang.model.type.ExecutableType;
50 import javax.lang.model.type.TypeKind;
51 import javax.lang.model.type.TypeMirror;
52 import javax.lang.model.util.ElementFilter;
53 import javax.lang.model.util.Elements;
54 import javax.swing.text.JTextComponent JavaDoc;
55 import org.netbeans.api.java.source.CancellableTask;
56 import org.netbeans.api.java.source.CompilationController;
57 import org.netbeans.api.java.source.ElementHandle;
58 import org.netbeans.api.java.source.JavaSource;
59 import org.netbeans.api.java.source.TreeMaker;
60 import org.netbeans.api.java.source.WorkingCopy;
61 import org.netbeans.modules.editor.java.Utilities;
62 import org.netbeans.modules.java.editor.codegen.ui.DelegatePanel;
63 import org.netbeans.modules.java.editor.codegen.ui.ElementNode;
64 import org.openide.DialogDescriptor;
65 import org.openide.DialogDisplayer;
66 import org.openide.util.Exceptions;
67 import org.openide.util.NbBundle;
68
69 /**
70  *
71  * @author Dusan Balek
72  */

73 public class DelegateMethodGenerator implements CodeGenerator {
74
75     public static class Factory implements CodeGenerator.Factory {
76         
77         Factory() {
78         }
79         
80         public Iterable JavaDoc<? extends CodeGenerator> create(CompilationController controller, TreePath path) throws IOException JavaDoc {
81             path = Utilities.getPathElementOfKind(Tree.Kind.CLASS, path);
82             if (path == null)
83                 return Collections.emptySet();
84             controller.toPhase(JavaSource.Phase.ELEMENTS_RESOLVED);
85             Elements elements = controller.getElements();
86             TypeElement typeElement = (TypeElement)controller.getTrees().getElement(path);
87             if (!typeElement.getKind().isClass())
88                 return Collections.emptySet();
89             Trees trees = controller.getTrees();
90             Scope scope = trees.getScope(path);
91             Map JavaDoc<Element, List JavaDoc<ElementNode.Description>> map = new LinkedHashMap JavaDoc<Element, List JavaDoc<ElementNode.Description>>();
92             TypeElement cls;
93             while(scope != null && (cls = scope.getEnclosingClass()) != null) {
94                 DeclaredType type = (DeclaredType)cls.asType();
95                 for (VariableElement field : ElementFilter.fieldsIn(elements.getAllMembers(cls))) {
96                     if (!field.asType().getKind().isPrimitive() && trees.isAccessible(scope, field, type)) {
97                         List JavaDoc<ElementNode.Description> descriptions = map.get(field.getEnclosingElement());
98                         if (descriptions == null) {
99                             descriptions = new ArrayList JavaDoc<ElementNode.Description>();
100                             map.put(field.getEnclosingElement(), descriptions);
101                         }
102                         descriptions.add(ElementNode.Description.create(field, null, false, false));
103                     }
104                 }
105                 scope = scope.getEnclosingScope();
106             }
107             List JavaDoc<ElementNode.Description> descriptions = new ArrayList JavaDoc<ElementNode.Description>();
108             for (Map.Entry JavaDoc<Element, List JavaDoc<ElementNode.Description>> entry : map.entrySet())
109                 descriptions.add(ElementNode.Description.create(entry.getKey(), entry.getValue(), false, false));
110             if (descriptions.isEmpty())
111                 return Collections.emptySet();
112             Collections.reverse(descriptions);
113             return Collections.singleton(new DelegateMethodGenerator(ElementNode.Description.create(descriptions)));
114         }
115     }
116
117     private ElementNode.Description description;
118     
119     /** Creates a new instance of DelegateMethodGenerator */
120     private DelegateMethodGenerator(ElementNode.Description description) {
121         this.description = description;
122     }
123
124     public String JavaDoc getDisplayName() {
125         return org.openide.util.NbBundle.getMessage(DelegateMethodGenerator.class, "LBL_delegate_method"); //NOI18N
126
}
127
128     public void invoke(JTextComponent JavaDoc component) {
129         final DelegatePanel panel = new DelegatePanel(component, description);
130         DialogDescriptor dialogDescriptor = new DialogDescriptor(panel, NbBundle.getMessage(ConstructorGenerator.class, "LBL_generate_delegate")); //NOI18N
131
Dialog JavaDoc dialog = DialogDisplayer.getDefault().createDialog(dialogDescriptor);
132         dialog.setVisible(true);
133         if (dialogDescriptor.getValue() == DialogDescriptor.OK_OPTION) {
134             JavaSource js = JavaSource.forDocument(component.getDocument());
135             if (js != null) {
136                 try {
137                     final int caretOffset = component.getCaretPosition();
138                     js.runModificationTask(new CancellableTask<WorkingCopy>() {
139                         public void cancel() {
140                         }
141                         public void run(WorkingCopy copy) throws IOException JavaDoc {
142                             copy.toPhase(JavaSource.Phase.ELEMENTS_RESOLVED);
143                             TreePath path = copy.getTreeUtilities().pathFor(caretOffset);
144                             path = Utilities.getPathElementOfKind(Tree.Kind.CLASS, path);
145                             int idx = 0;
146                             SourcePositions sourcePositions = copy.getTrees().getSourcePositions();
147                             for (Tree tree : ((ClassTree)path.getLeaf()).getMembers()) {
148                                 if (sourcePositions.getStartPosition(path.getCompilationUnit(), tree) < caretOffset)
149                                     idx++;
150                                 else
151                                     break;
152                             }
153                             ElementHandle<? extends Element> handle = panel.getDelegateField();
154                             VariableElement delegate = handle != null ? (VariableElement)handle.resolve(copy) : null;
155                             ArrayList JavaDoc<ExecutableElement> methods = new ArrayList JavaDoc<ExecutableElement>();
156                             for (ElementHandle<? extends Element> elementHandle : panel.getDelegateMethods())
157                                 methods.add((ExecutableElement)elementHandle.resolve(copy));
158                             generateDelegatingMethods(copy, path, delegate, methods, idx);
159                         }
160                     }).commit();
161                 } catch (IOException JavaDoc ex) {
162                     Exceptions.printStackTrace(ex);
163                 }
164             }
165         }
166     }
167
168     public static ElementNode.Description getAvailableMethods(final JTextComponent JavaDoc component, final ElementHandle<? extends Element> elementHandle) {
169         if (elementHandle.getKind().isField()) {
170             JavaSource js = JavaSource.forDocument(component.getDocument());
171             if (js != null) {
172                 try {
173                     final int caretOffset = component.getCaretPosition();
174                     final ElementNode.Description[] description = new ElementNode.Description[1];
175                     js.runUserActionTask(new CancellableTask<CompilationController>() {
176                         public void cancel() {
177                         }
178                         public void run(CompilationController controller) throws IOException JavaDoc {
179                             VariableElement field = (VariableElement)elementHandle.resolve(controller);
180                             if (field.asType().getKind() == TypeKind.DECLARED) {
181                                 DeclaredType type = (DeclaredType) field.asType();
182                                 Trees trees = controller.getTrees();
183                                 Scope scope = controller.getTreeUtilities().scopeFor(caretOffset);
184                                 Map JavaDoc<Element, List JavaDoc<ElementNode.Description>> map = new LinkedHashMap JavaDoc<Element, List JavaDoc<ElementNode.Description>>();
185                                 for (ExecutableElement method : ElementFilter.methodsIn(controller.getElements().getAllMembers((TypeElement)type.asElement()))) {
186                                     if (trees.isAccessible(scope, method, type)) {
187                                         List JavaDoc<ElementNode.Description> descriptions = map.get(method.getEnclosingElement());
188                                         if (descriptions == null) {
189                                             descriptions = new ArrayList JavaDoc<ElementNode.Description>();
190                                             map.put(method.getEnclosingElement(), descriptions);
191                                         }
192                                         descriptions.add(ElementNode.Description.create(method, null, true, false));
193                                     }
194                                 }
195                                 List JavaDoc<ElementNode.Description> descriptions = new ArrayList JavaDoc<ElementNode.Description>();
196                                 for (Map.Entry JavaDoc<Element, List JavaDoc<ElementNode.Description>> entry : map.entrySet())
197                                     descriptions.add(ElementNode.Description.create(entry.getKey(), entry.getValue(), false, false));
198                                 if (!descriptions.isEmpty())
199                                     Collections.reverse(descriptions);
200                                     description[0] = ElementNode.Description.create(descriptions);
201                             }
202                         }
203                     }, true);
204                     return description[0];
205                 } catch (IOException JavaDoc ex) {
206                     Exceptions.printStackTrace(ex);
207                 }
208             }
209         }
210         return null;
211     }
212     
213     private static void generateDelegatingMethods(WorkingCopy wc, TreePath path, VariableElement delegate, Iterable JavaDoc<? extends ExecutableElement> methods, int index) {
214         assert path.getLeaf().getKind() == Tree.Kind.CLASS;
215         TypeElement te = (TypeElement)wc.getTrees().getElement(path);
216         if (te != null) {
217             TreeMaker make = wc.getTreeMaker();
218             ClassTree nue = (ClassTree)path.getLeaf();
219             for (ExecutableElement executableElement : methods)
220                 nue = make.insertClassMember(nue, index, createDelegatingMethod(wc, delegate, executableElement, (DeclaredType)te.asType()));
221             wc.rewrite(path.getLeaf(), nue);
222         }
223     }
224     
225     private static MethodTree createDelegatingMethod(WorkingCopy wc, VariableElement delegate, ExecutableElement method, DeclaredType type) {
226         TreeMaker make = wc.getTreeMaker();
227         ExecutableType methodType = (ExecutableType)wc.getTypes().asMemberOf((DeclaredType)delegate.asType(), method);
228         Set JavaDoc<Modifier> mods = EnumSet.copyOf(method.getModifiers());
229         mods.remove(Modifier.ABSTRACT);
230         
231         List JavaDoc<VariableTree> params = new ArrayList JavaDoc<VariableTree>();
232         List JavaDoc<ExpressionTree> args = new ArrayList JavaDoc<ExpressionTree>();
233         
234         Iterator JavaDoc<? extends VariableElement> it = method.getParameters().iterator();
235         Iterator JavaDoc<? extends TypeMirror> tIt = methodType.getParameterTypes().iterator();
236         while(it.hasNext() && tIt.hasNext()) {
237             VariableElement ve = it.next();
238             params.add(make.Variable(make.Modifiers(EnumSet.noneOf(Modifier.class)), ve.getSimpleName(), make.Type(tIt.next()), null));
239             args.add(make.Identifier(ve.getSimpleName()));
240         }
241
242         ExpressionTree exp = make.MethodInvocation(Collections.<ExpressionTree>emptyList(), make.MemberSelect(make.Identifier(delegate.getSimpleName()), method.getSimpleName()), args);
243         StatementTree stmt = method.getReturnType().getKind() == TypeKind.VOID ? make.ExpressionStatement(exp) : make.Return(exp);
244         BlockTree body = make.Block(Collections.singletonList(stmt), false);
245         
246         List JavaDoc<ExpressionTree> throwsClause = new ArrayList JavaDoc<ExpressionTree>();
247         for (TypeMirror tm : methodType.getThrownTypes())
248             throwsClause.add((ExpressionTree)wc.getTreeMaker().Type(tm));
249         
250         return make.Method(make.Modifiers(mods), method.getSimpleName(), make.Type(methodType.getReturnType()), Collections.<TypeParameterTree>emptyList(), params, throwsClause, body, null);
251     }
252 }
253
Popular Tags