KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jac > ide > swing > MethodBodyCompletionEngine


1 /*
2   Copyright (C) 2003 Renaud Pawlak <renaud@aopsys.com>
3   
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU Lesser General Public License as
6   published by the Free Software Foundation; either version 2 of the
7   License, or (at your option) any later version.
8
9   This program is distributed in the hope that it will be useful, but
10   WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12   Lesser General Public License for more details.
13
14   You should have received a copy of the GNU Lesser General Public
15   License along with this program; if not, write to the Free Software
16   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17   USA */

18
19 package org.objectweb.jac.ide.swing;
20
21 import java.util.HashMap JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Vector JavaDoc;
25 import org.apache.log4j.Logger;
26 import org.objectweb.jac.aspects.gui.swing.CompletionEngine;
27 import org.objectweb.jac.aspects.gui.swing.SHEditor;
28 import org.objectweb.jac.core.rtti.AbstractMethodItem;
29 import org.objectweb.jac.core.rtti.ClassItem;
30 import org.objectweb.jac.core.rtti.ClassRepository;
31 import org.objectweb.jac.ide.Class;
32 import org.objectweb.jac.ide.CodeGeneration;
33 import org.objectweb.jac.ide.Field;
34 import org.objectweb.jac.ide.Method;
35 import org.objectweb.jac.ide.Parameter;
36 import org.objectweb.jac.ide.RelationRole;
37 import org.objectweb.jac.ide.Role;
38 import org.objectweb.jac.ide.Type;
39
40 /**
41  * This class implements a completion engine for method bodies Java
42  * editors of the UMLAF IDE. */

43
44 public class MethodBodyCompletionEngine extends CompletionEngine {
45     static final Logger logger = Logger.getLogger("completion");
46     static final Logger loggerPerf = Logger.getLogger("perf");
47
48     Method method;
49     SHEditor editor;
50
51     /**
52      * Creates a completion engine for a given method. */

53
54     public MethodBodyCompletionEngine(Method method, SHEditor editor) {
55         this.method = method;
56         addBaseWords(buildThisWords());
57         logger.info("baseWords = "+baseWords);
58         this.editor = editor;
59     }
60
61     /**
62      * Get the contextual possible choices.
63      *
64      * <p>Supported contextual completions are like
65      * <code>class_typed_symbol.{methods}</code>. In the long term, any
66      * typed expression should be supported even if it is not that
67      * important in clean developments (because of the Demeter's
68      * Law!!).
69      *
70      * @param text the editor's full text
71      * @param position the cursor position
72      * @param writtenText the already written text */

73
74     public List JavaDoc getContextualChoices(String JavaDoc text, int position,
75                                      String JavaDoc writtenText) {
76         long start = System.currentTimeMillis();
77       
78         List JavaDoc result;
79         int pos = position-1;
80         if (pos>0 && text.charAt(pos)=='.') {
81             // Here we should be able to guess types of more complex
82
// lines that symbols (see getSymbolType). This would need a
83
// real parser.
84
while (pos>0 && !editor.isDivider(text.charAt(--pos))) {
85             }
86             String JavaDoc symbol = text.substring(pos+1,position-1);
87             logger.info("found parent symbol "+symbol);
88             Type t = getSymbolType(symbol);
89             if (t!=null) {
90                 result = buildTypeWords(t);
91             } else {
92                 result = new Vector JavaDoc();
93             }
94         } else {
95             result = getBaseWords();
96         }
97         loggerPerf.info("getContextualChoices("+writtenText+"): "+
98                         (System.currentTimeMillis()-start)+"ms");
99
100         logger.info( "getContextualChoices("+writtenText+") -> "+result);
101         return result;
102     }
103
104     /**
105      * Builds the list of method and field names that are directly
106      * accessible within the class of the method and the parameters of
107      * the method, as well as the names of the types of those fields.
108      */

109     public List JavaDoc buildThisWords() {
110         List JavaDoc ret = buildClassWords(method.getParent());
111         Iterator JavaDoc it = method.getParameters().iterator();
112         while(it.hasNext()) {
113             Parameter p = (Parameter)it.next();
114             String JavaDoc name = p.getGenerationName();
115             if (!ret.contains(name)) {
116                 ret.add(name);
117             }
118         }
119         return ret;
120     }
121
122     /**
123      * Get all the accessible words in the context of a given type.
124      *
125      * <p>If type is an internal IDE class, all the method plus the
126      * generated methods (getters, setters, adders, removers, clearers)
127      * are returned. If type is an external library class, all the
128      * public methods are returned.
129      *
130      * @see #buildClassWords(Class) */

131
132     public List JavaDoc buildTypeWords(Type type) {
133         logger.debug("buildTypeWords("+type.getFullName()+")");
134         if (type==null) {
135             return new Vector JavaDoc();
136         } else if (type instanceof Class JavaDoc) {
137             return buildClassWords((Class JavaDoc)type);
138         } else {
139             logger.debug("found external type");
140             List JavaDoc ret = new Vector JavaDoc();
141             ClassItem c = ClassRepository.get().getClass(type.getFullName());
142             Iterator JavaDoc it = c.getAllMethods().iterator();
143             while(it.hasNext()) {
144                 String JavaDoc name = ((AbstractMethodItem)it.next()).getName();
145                 logger.debug("external method candidate: "+name);
146                 if (!ret.contains(name)) {
147                     ret.add(name);
148                 }
149             }
150             return ret;
151         }
152     }
153
154     /**
155      * Get all the accessible words in the context of a given IDE
156      * class (fields,methods).
157      *
158      * @param c the class for which to get accessible words
159      */

160     public List JavaDoc buildClassWords(Class JavaDoc c) {
161         if (c==null)
162             return new Vector JavaDoc();
163         if (classWords.containsKey(c)) {
164             return (List JavaDoc)classWords.get(c);
165         }
166         logger.debug("buildClassWords("+c.getFullName()+")");
167         List JavaDoc ret = new Vector JavaDoc();
168         Iterator JavaDoc it = c.getMethods().iterator();
169         while (it.hasNext()) {
170             String JavaDoc name = ((Method)it.next()).getGenerationName();
171             if (!ret.contains(name)) {
172                 ret.add(name);
173             }
174         }
175         it = c.getFields().iterator();
176         while (it.hasNext()) {
177             Field field = (Field)it.next();
178             String JavaDoc name = field.getGenerationName();
179             if (!ret.contains(name)) {
180                 ret.add(name);
181             }
182             Type type = field.getType();
183             if (type instanceof Class JavaDoc) {
184                 name = type.getGenerationName();
185                 if (!ret.contains(name))
186                     ret.add(name);
187             }
188             // add also the setter
189
String JavaDoc tmpName = CodeGeneration.getSetterName(name);
190             if (!ret.contains(tmpName)) {
191                 ret.add(tmpName);
192             }
193             // and the getter
194
tmpName = CodeGeneration.getGetterName(name);
195             if (!ret.contains(tmpName)) {
196                 ret.add(tmpName);
197             }
198          
199         }
200
201         List JavaDoc rs = c.getLinks();
202         for (int i=0; i<rs.size(); i++) {
203             Role role = (Role)rs.get(i);
204             if (role instanceof RelationRole) {
205                 RelationRole end = (RelationRole)role;
206
207                 logger.debug(" role "+end.getGenerationName());
208                 String JavaDoc name = end.getGenerationName();
209                 if (!ret.contains(name)) {
210                     ret.add(name);
211                 }
212                 name = ((Class JavaDoc)end.getEnd()).getGenerationName();
213                 logger.debug(" Classname of "+end.getGenerationName()+": "+name);
214                 if (!ret.contains(name))
215                     ret.add(name);
216
217                 String JavaDoc tmpName = CodeGeneration.getSetterName(name);
218                 if (!ret.contains(tmpName)) {
219                     ret.add(tmpName);
220                 }
221                 tmpName = CodeGeneration.getGetterName(name);
222                 if (!ret.contains(tmpName)) {
223                     ret.add(tmpName);
224                 }
225                 if (end.isMultiple()) {
226                     tmpName = CodeGeneration.getAdderName(name);
227                     if (!ret.contains(tmpName)) {
228                         ret.add(tmpName);
229                     }
230                     tmpName = CodeGeneration.getRemoverName(name);
231                     if (!ret.contains(tmpName)) {
232                         ret.add(tmpName);
233                     }
234                     tmpName = CodeGeneration.getClearerName(name);
235                     if (!ret.contains(tmpName)) {
236                         ret.add(tmpName);
237                     }
238                 }
239             }
240         }
241
242         classWords.put(c,ret);
243         return ret;
244     }
245
246     HashMap JavaDoc classWords = new HashMap JavaDoc();
247
248     /**
249      * Returns the type of a symbol. Any kind of expression should be
250      * supported one day...
251      * @param name the symbol's name
252      */

253     Type getSymbolType(String JavaDoc name) {
254         if (symbolTypes.containsKey(name)) {
255             return (Type)symbolTypes.get(name);
256         }
257         Type type = null;
258         Iterator JavaDoc it = method.getParameters().iterator();
259         while (it.hasNext()) {
260             Parameter p = (Parameter)it.next();
261             if (p.getGenerationName().equals(name)) {
262                 type = p.getType();
263                 symbolTypes.put(name,type);
264                 return type;
265             }
266         }
267         Class JavaDoc c = method.getParent();
268         if (c!=null) {
269             it = c.getFields().iterator();
270             while(it.hasNext()) {
271                 Field f = (Field)it.next();
272                 if (f.getGenerationName().equals(name)) {
273                     type = f.getType();
274                     symbolTypes.put(name,type);
275                     return type;
276                 }
277             }
278         }
279         symbolTypes.put(name,null);
280         return null;
281     }
282
283     HashMap JavaDoc symbolTypes = new HashMap JavaDoc();
284
285     /**
286      * Returns true if <code>c=='('</code>. */

287
288     public boolean isAutomaticCompletionChar(char c) {
289         logger.debug("isAutomaticCompletionChar("+c+")");
290         return c=='(';
291     }
292
293     /**
294      * Help the programmer to write useful control structure such as
295      * <code>for</code> or <code>while</code>. */

296
297     public void runAutomaticCompletion(SHEditor editor,
298                                        String JavaDoc text,
299                                        int position,
300                                        char c) {
301         String JavaDoc word = getPreviousWord(text,position);
302         logger.debug("getAutomaticCompletion("+word+")");
303         if(c=='(') {
304             if(word.equals("for")) {
305                 editor.insertString(position,";;) {");
306                 editor.insertReturn();
307                 editor.insertReturn();
308                 editor.insertCloseCBracket();
309             } else if(word.equals("while")) {
310                 editor.insertString(position,") {");
311                 editor.insertReturn();
312                 editor.insertReturn();
313                 editor.insertCloseCBracket();
314             }
315         }
316     }
317
318     String JavaDoc getPreviousWord(String JavaDoc text, int position) {
319         int pos2 = position-1;
320         int pos1 = pos2;
321         while (pos1>0 && !editor.isDivider(text.charAt(--pos1))) {
322         }
323         return text.substring(pos1,pos2).trim();
324     }
325    
326 }
327
328
Popular Tags