~ubuntu-branches/ubuntu/quantal/netbeans/quantal

« back to all changes in this revision

Viewing changes to j2ee/utilities/src/org/netbeans/modules/j2ee/common/method/MethodModelSupport.java

  • Committer: Bazaar Package Importer
  • Author(s): Marek Slama
  • Date: 2008-01-29 14:11:22 UTC
  • Revision ID: james.westby@ubuntu.com-20080129141122-fnzjbo11ntghxfu7
Tags: upstream-6.0.1
ImportĀ upstreamĀ versionĀ 6.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 
3
 *
 
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 
5
 *
 
6
 * The contents of this file are subject to the terms of either the GNU
 
7
 * General Public License Version 2 only ("GPL") or the Common
 
8
 * Development and Distribution License("CDDL") (collectively, the
 
9
 * "License"). You may not use this file except in compliance with the
 
10
 * License. You can obtain a copy of the License at
 
11
 * http://www.netbeans.org/cddl-gplv2.html
 
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
 
13
 * specific language governing permissions and limitations under the
 
14
 * License.  When distributing the software, include this License Header
 
15
 * Notice in each file and include the License file at
 
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
 
17
 * particular file as subject to the "Classpath" exception as provided
 
18
 * by Sun in the GPL Version 2 section of the License file that
 
19
 * accompanied this code. If applicable, add the following below the
 
20
 * License Header, with the fields enclosed by brackets [] replaced by
 
21
 * your own identifying information:
 
22
 * "Portions Copyrighted [year] [name of copyright owner]"
 
23
 *
 
24
 * Contributor(s):
 
25
 *
 
26
 * The Original Software is NetBeans. The Initial Developer of the Original
 
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
 
28
 * Microsystems, Inc. All Rights Reserved.
 
29
 *
 
30
 * If you wish your version of this file to be governed by only the CDDL
 
31
 * or only the GPL Version 2, indicate your decision by adding
 
32
 * "[Contributor] elects to include this software in this distribution
 
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
 
34
 * single choice of license, a recipient has the option to distribute
 
35
 * your version of this file under either the CDDL, the GPL Version 2 or
 
36
 * to extend the choice of license to its licensees as provided above.
 
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
 
38
 * Version 2 license, then the option applies only if the new code is
 
39
 * made subject to such option by the copyright holder.
 
40
 */
 
41
 
 
42
package org.netbeans.modules.j2ee.common.method;
 
43
 
 
44
import com.sun.source.tree.BlockTree;
 
45
import javax.lang.model.type.ArrayType;
 
46
import org.netbeans.api.java.source.CompilationController;
 
47
import com.sun.source.tree.ExpressionTree;
 
48
import com.sun.source.tree.MethodTree;
 
49
import com.sun.source.tree.Tree;
 
50
import com.sun.source.tree.TypeParameterTree;
 
51
import com.sun.source.tree.VariableTree;
 
52
import java.util.ArrayList;
 
53
import java.util.Collections;
 
54
import java.util.List;
 
55
import javax.lang.model.element.Element;
 
56
import javax.lang.model.element.ExecutableElement;
 
57
import javax.lang.model.element.Modifier;
 
58
import javax.lang.model.element.TypeElement;
 
59
import javax.lang.model.element.VariableElement;
 
60
import javax.lang.model.type.TypeKind;
 
61
import javax.lang.model.type.TypeMirror;
 
62
import org.netbeans.api.java.source.GeneratorUtilities;
 
63
import org.netbeans.api.java.source.TreeMaker;
 
64
import org.netbeans.api.java.source.WorkingCopy;
 
65
import org.openide.util.Parameters;
 
66
 
 
67
/**
 
68
 * Support class for {@link MethodModel} providing some factory and conversion methods.
 
69
 * 
 
70
 * @author Martin Adamek
 
71
 */
 
72
public final class MethodModelSupport {
 
73
    
 
74
    private MethodModelSupport() {}
 
75
    
 
76
    /**
 
77
     * Creates new instance of method model. None of the parameters can be null.
 
78
     * This method must be called from within javac context.
 
79
     * 
 
80
     * @param workingCopy controller from javac context
 
81
     * @param method method for which the model is to be created
 
82
     * @throws NullPointerException if any of the parameters is <code>null</code>.
 
83
     * @return immutable model of method
 
84
     */
 
85
    public static MethodModel createMethodModel(CompilationController controller, ExecutableElement method) {
 
86
        Parameters.notNull("controller", controller); // NOI18N
 
87
        Parameters.notNull("method", method); // NOI18N
 
88
        List<MethodModel.Variable> parameters = new ArrayList<MethodModel.Variable>();
 
89
        for (VariableElement variableElement : method.getParameters()) {
 
90
            String type = getTypeName(controller, variableElement.asType());
 
91
            String name = variableElement.getSimpleName().toString();
 
92
            parameters.add(MethodModel.Variable.create(type, name));
 
93
        }
 
94
        List<String> exceptions = new ArrayList<String>();
 
95
        for (TypeMirror typeMirror : method.getThrownTypes()) {
 
96
            exceptions.add(getTypeName(controller, typeMirror));
 
97
        }
 
98
        return MethodModel.create(
 
99
                method.getSimpleName().toString(),
 
100
                getTypeName(controller, method.getReturnType()),
 
101
                //TODO: RETOUCHE get body of method
 
102
                "",
 
103
                parameters,
 
104
                exceptions,
 
105
                method.getModifiers()
 
106
                );
 
107
    }
 
108
    
 
109
    /**
 
110
     * Creates new instance of model of class variable or method parameter
 
111
     * This method must be called from within javac context.
 
112
     * 
 
113
     * @param workingCopy controller from javac context
 
114
     * @param variableElement variable or method parameter for which the model is to be created
 
115
     * @throws NullPointerException if any of the parameters is <code>null</code>.
 
116
     * @return immutable model of variable or method parameter
 
117
     */
 
118
    public static MethodModel.Variable createVariable(CompilationController controller, VariableElement variableElement) {
 
119
        Parameters.notNull("controller", controller); //NOI18N
 
120
        Parameters.notNull("variableElement", variableElement); //NOI18N
 
121
        return MethodModel.Variable.create(
 
122
                getTypeName(controller, variableElement.asType()),
 
123
                variableElement.getSimpleName().toString(),
 
124
                variableElement.getModifiers().contains(Modifier.FINAL)
 
125
                );
 
126
    }
 
127
    
 
128
    /**
 
129
     * Creates {@link MethodTree} represented by methodModel in given javac context.
 
130
     * 
 
131
     * @param workingCopy controller from javac context
 
132
     * @param methodModel model of method
 
133
     * @throws NullPointerException if any of the parameters is <code>null</code>.
 
134
     * @return tree representing methodModel
 
135
     */
 
136
    public static MethodTree createMethodTree(WorkingCopy workingCopy, MethodModel methodModel) {
 
137
        return createMethodTree(workingCopy, methodModel, false);
 
138
    }
 
139
    
 
140
    /**
 
141
     * Creates {@link MethodTree} represented by methodModel in given javac context.
 
142
     * 
 
143
     * @param workingCopy controller from javac context
 
144
     * @param methodModel model of method
 
145
     * @param generateDefaultBody if true and body on methodModel is null or empty string, default return statement will be generated
 
146
     * @throws NullPointerException if any of the parameters is <code>null</code>.
 
147
     * @return tree representing methodModel
 
148
     */
 
149
    public static MethodTree createMethodTree(WorkingCopy workingCopy, MethodModel methodModel, boolean generateDefaultBody) {
 
150
        Parameters.notNull("workingCopy", workingCopy); //NOI18N
 
151
        Parameters.notNull("methodModel", methodModel); //NOI18N
 
152
        TreeMaker treeMaker = workingCopy.getTreeMaker();
 
153
        List<VariableTree> paramsList = new ArrayList<VariableTree>();
 
154
        if (methodModel.getParameters() != null) {
 
155
            for (MethodModel.Variable parameter : methodModel.getParameters()) {
 
156
                VariableTree variableTree = treeMaker.Variable(
 
157
                        treeMaker.Modifiers(parameter.getFinalModifier() ? Collections.<Modifier>singleton(Modifier.FINAL) : Collections.<Modifier>emptySet()),
 
158
                        parameter.getName(),
 
159
                        getTypeTree(workingCopy, parameter.getType()),
 
160
                        null
 
161
                        );
 
162
                paramsList.add(variableTree);
 
163
            }
 
164
        }
 
165
        List<ExpressionTree> throwsList = new ArrayList<ExpressionTree>();
 
166
        for (String exceptionName : methodModel.getExceptions()) {
 
167
            throwsList.add(createQualIdent(workingCopy, exceptionName));
 
168
        }
 
169
        MethodTree result;
 
170
        String body = methodModel.getBody();
 
171
        // if passed body is null, generate default return statement (if return type is not void)
 
172
        if (generateDefaultBody && (body == null || "".equals(body.trim()))) {
 
173
            String generatedBody = getDefaultReturnValue(workingCopy, methodModel.getReturnType());
 
174
            body = generatedBody == null ? "" : "return " + generatedBody + ";";
 
175
        }
 
176
        if (body == null) {
 
177
            result = treeMaker.Method(
 
178
                    treeMaker.Modifiers(methodModel.getModifiers()),
 
179
                    methodModel.getName(),
 
180
                    getTypeTree(workingCopy, methodModel.getReturnType()),
 
181
                    Collections.<TypeParameterTree>emptyList(),
 
182
                    paramsList,
 
183
                    throwsList,
 
184
                    (BlockTree) null,
 
185
                    null
 
186
                    );
 
187
        } else {
 
188
            result = treeMaker.Method(
 
189
                    treeMaker.Modifiers(methodModel.getModifiers()),
 
190
                    methodModel.getName(),
 
191
                    getTypeTree(workingCopy, methodModel.getReturnType()),
 
192
                    Collections.<TypeParameterTree>emptyList(),
 
193
                    paramsList,
 
194
                    throwsList,
 
195
                    "{" + body + "}",
 
196
                    null
 
197
                    );
 
198
        }
 
199
        return (MethodTree) GeneratorUtilities.get(workingCopy).importFQNs(result);
 
200
    }
 
201
    
 
202
    /**
 
203
     * Checks if signature of {@link ExecutableElement} is represented by {@link MethodModel} methodModel
 
204
     * in given javac context.
 
205
     * 
 
206
     * @param compilationInfo controller from javac context
 
207
     * @param method method existing in given javac context
 
208
     * @param methodModel model of method
 
209
     * @throws NullPointerException if any of the parameters is <code>null</code>.
 
210
     * @return true if method and methodModel have same signature, false otherwise
 
211
     */
 
212
    public static boolean isSameMethod(CompilationController controller, ExecutableElement method, MethodModel methodModel) {
 
213
        //TODO: RETOUCHE fix this method, see #90505
 
214
        Parameters.notNull("compilationInfo", controller); // NOI18N
 
215
        Parameters.notNull("method", method); // NOI18N
 
216
        Parameters.notNull("methodModel", methodModel); // NOI18N
 
217
        if (!method.getSimpleName().contentEquals(methodModel.getName())) {
 
218
            return false;
 
219
        }
 
220
        List<? extends VariableElement> methodParams = method.getParameters();
 
221
        if (methodParams.size() != methodModel.getParameters().size()) {
 
222
            return false;
 
223
        }
 
224
        for (int i = 0; i < methodParams.size(); i++) {
 
225
            VariableElement variableElement = methodParams.get(i);
 
226
            String variableElementType = getTypeName(controller, variableElement.asType());
 
227
            MethodModel.Variable variable = methodModel.getParameters().get(i);
 
228
            if (!variableElementType.equals(variable.getType())) {
 
229
                return false;
 
230
            }
 
231
        }
 
232
        return true;
 
233
    }
 
234
    
 
235
    /**
 
236
     * Generates default value for provided type
 
237
     * 
 
238
     * @param workingCopy workingCopy
 
239
     * @param typeName fully-qualified type name or primitive type name or "void"
 
240
     * @return values according to JLS '4.5.5 Initial Values of Variables'
 
241
     * with exception for "char" where it returns "c"
 
242
     */
 
243
    public static String getDefaultReturnValue(WorkingCopy workingCopy, String typeName) {
 
244
        if ("boolean".equals(typeName)) {           // NOI18N
 
245
            return "false";                         // NOI18N
 
246
        } else if ("byte".equals(typeName)) {       // NOI18N
 
247
            return "0";                             // NOI18N
 
248
        } else if ("short".equals(typeName)) {      // NOI18N
 
249
            return "0";                             // NOI18N
 
250
        } else if ("int".equals(typeName)) {        // NOI18N
 
251
            return "0";                             // NOI18N
 
252
        } else if ("long".equals(typeName)) {       // NOI18N
 
253
            return "0L";                            // NOI18N
 
254
        } else if ("char".equals(typeName)) {       // NOI18N
 
255
            // should be '\u0000' which is null character, but we cannot return that
 
256
            return "'c'";                           // NOI18N
 
257
        } else if ("float".equals(typeName)) {      // NOI18N
 
258
            return "0.0f";                          // NOI18N
 
259
        } else if ("double".equals(typeName)) {     // NOI18N
 
260
            return "0.0d";                          // NOI18N
 
261
        } else if ("void".equals(typeName)) {       // NOI18N
 
262
            return null;
 
263
        } else {
 
264
            return "null";                          // NOI18N
 
265
        }
 
266
    }
 
267
    
 
268
    //TODO: RETOUCHE move/reuse to GenerationUtil, this one has also void type
 
269
    private static Tree getTypeTree(WorkingCopy workingCopy, String typeName) {
 
270
        TreeMaker make = workingCopy.getTreeMaker();
 
271
        TypeKind primitiveTypeKind = null;
 
272
        if ("boolean".equals(typeName)) {           // NOI18N
 
273
            primitiveTypeKind = TypeKind.BOOLEAN;
 
274
        } else if ("byte".equals(typeName)) {       // NOI18N
 
275
            primitiveTypeKind = TypeKind.BYTE;
 
276
        } else if ("short".equals(typeName)) {      // NOI18N
 
277
            primitiveTypeKind = TypeKind.SHORT;
 
278
        } else if ("int".equals(typeName)) {        // NOI18N
 
279
            primitiveTypeKind = TypeKind.INT;
 
280
        } else if ("long".equals(typeName)) {       // NOI18N
 
281
            primitiveTypeKind = TypeKind.LONG;
 
282
        } else if ("char".equals(typeName)) {       // NOI18N
 
283
            primitiveTypeKind = TypeKind.CHAR;
 
284
        } else if ("float".equals(typeName)) {      // NOI18N
 
285
            primitiveTypeKind = TypeKind.FLOAT;
 
286
        } else if ("double".equals(typeName)) {     // NOI18N
 
287
            primitiveTypeKind = TypeKind.DOUBLE;
 
288
        } else if ("void".equals(typeName)) {     // NOI18N
 
289
            primitiveTypeKind = TypeKind.VOID;
 
290
        }
 
291
        if (primitiveTypeKind != null) {
 
292
            return make.PrimitiveType(primitiveTypeKind);
 
293
        } else {
 
294
            return createQualIdent(workingCopy, typeName);
 
295
        }
 
296
    }
 
297
    
 
298
    //TODO: RETOUCHE move/reuse to GenerationUtil
 
299
    private static ExpressionTree createQualIdent(WorkingCopy workingCopy, String typeName) {
 
300
        TypeElement typeElement = workingCopy.getElements().getTypeElement(typeName);
 
301
        if (typeElement == null) {
 
302
            typeElement = workingCopy.getElements().getTypeElement("java.lang." + typeName);
 
303
            if (typeElement == null) {
 
304
                return workingCopy.getTreeMaker().Identifier(typeName);
 
305
            }
 
306
        }
 
307
        return workingCopy.getTreeMaker().QualIdent(typeElement);
 
308
    }
 
309
    
 
310
    //TODO: RETOUCHE move/reuse in SourceUtil, or best - get from java/source!
 
311
    // package private only for unit test
 
312
    // see #90968
 
313
    static String getTypeName(CompilationController controller, TypeMirror typeMirror) {
 
314
        TypeKind typeKind = typeMirror.getKind();
 
315
        switch (typeKind) {
 
316
            case BOOLEAN : return "boolean"; // NOI18N
 
317
            case BYTE : return "byte"; // NOI18N
 
318
            case CHAR : return "char"; // NOI18N
 
319
            case DOUBLE : return "double"; // NOI18N
 
320
            case FLOAT : return "float"; // NOI18N
 
321
            case INT : return "int"; // NOI18N
 
322
            case LONG : return "long"; // NOI18N
 
323
            case SHORT : return "short"; // NOI18N
 
324
            case VOID : return "void"; // NOI18N
 
325
            case DECLARED : 
 
326
                Element element = controller.getTypes().asElement(typeMirror);
 
327
                return ((TypeElement) element).getQualifiedName().toString();
 
328
            case ARRAY : 
 
329
                ArrayType arrayType = (ArrayType) typeMirror;
 
330
                TypeMirror componentType = arrayType.getComponentType();
 
331
                return getTypeName(controller, componentType) + "[]";
 
332
            case ERROR :
 
333
            case EXECUTABLE :
 
334
            case NONE :
 
335
            case NULL :
 
336
            case OTHER :
 
337
            case PACKAGE :
 
338
            case TYPEVAR :
 
339
            case WILDCARD :
 
340
            default:break;
 
341
        }
 
342
        return null;
 
343
    }
 
344
    
 
345
}