/* * Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Business Objects nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * JavaMethod.java * Creation date: Oct 8, 2003. * By: Edward Lam */ package org.openquark.cal.internal.javamodel; import java.util.ArrayList; import java.util.List; import org.openquark.cal.internal.javamodel.JavaStatement.Block; import org.openquark.cal.services.Assert; /** * A representation of a Java method. * * @author Edward Lam */ public class JavaMethod { private static final String[] EMPTY_STRING_ARRAY = new String[0]; /** The modifiers for the method, as defined by the constants in java.lang.reflect.Modifier. */ private final int modifiers; /** The return type of the method. */ private final JavaTypeName returnType; /** The names of the method params. */ private final String[] paramNames; /** The types of the method params. */ private final JavaTypeName[] paramTypes; /** * Whether the parameter is final or not. null means that all parameters are not final. The final parameter on method arguments does * not affect byte code generation, but can detect some errors in the generated Java source. */ private final boolean[] paramFinal; /** The name of the method. */ private final String methodName; /** The code for the body of the method. */ private final Block bodyCode = new Block(); /** (List of JavaTypeName) Names of exceptions declared as thrown by this method. */ private final List<JavaTypeName> thrownExceptionList = new ArrayList<JavaTypeName>(); /** The JavaDoc for this class. */ private JavaStatement.JavaDocComment javaDocComment = null; /** * Constructor for a zero-argument java method. * @param modifiers for the method, as defined by the constants in java.lang.reflect.Modifier. * @param returnType * @param methodName */ public JavaMethod(int modifiers, JavaTypeName returnType, String methodName) { this(modifiers, returnType, EMPTY_STRING_ARRAY, new JavaTypeName[] {}, null, methodName); } /** * Constructor for a single-argument java method. * @param modifiers for the method, as defined by the constants in java.lang.reflect.Modifier. * @param returnType * @param paramName * @param paramType * @param paramFinal * @param methodName */ public JavaMethod(int modifiers, JavaTypeName returnType, String paramName, JavaTypeName paramType, boolean paramFinal, String methodName) { this(modifiers, returnType, new String[] {paramName}, new JavaTypeName[] {paramType}, new boolean[] {paramFinal}, methodName); } /** * Constructor for a java method. * @param modifiers for the method, as defined by the constants in java.lang.reflect.Modifier. * @param returnType * @param paramNames * @param paramTypes * @param paramFinal may be null, indicating that all params are not final * @param methodName */ public JavaMethod(int modifiers, JavaTypeName returnType, String[] paramNames, JavaTypeName[] paramTypes, boolean[] paramFinal, String methodName) { Assert.isNotNull(returnType); Assert.isNotNull(paramNames); Assert.isNotNull(paramTypes); Assert.isNotNull(methodName); if (paramNames.length != paramTypes.length) { throw new IllegalArgumentException("paramNames and paramTypes must have the same length."); } if (paramFinal == null) { this.paramFinal = new boolean[paramNames.length]; } else if (paramNames.length != paramFinal.length) { throw new IllegalArgumentException("paramNames and paramFinal must have the same length."); } else { this.paramFinal = paramFinal.clone(); } this.modifiers = modifiers; this.returnType = returnType; this.paramNames = paramNames.clone(); this.paramTypes = paramTypes.clone(); this.methodName = methodName; } /** * Add a statement to the body of the method. * @param statement */ public void addStatement(JavaStatement statement) { Assert.isNotNull(statement); bodyCode.addStatement(statement); } /** * Add a thrown exception to the method declaration. * @param thrownExceptionName */ public void addThrows(JavaTypeName thrownExceptionName) { thrownExceptionList.add(thrownExceptionName); } /** * Get the modifiers for the method. * @return int modifiers for the method, as defined by the constants in java.lang.reflect.Modifier. */ public int getModifiers() { return modifiers; } /** * Get the code for the body of the method. * @return Block */ public Block getBodyCode() { return bodyCode; } /** * Get the method name. * @return String */ public String getMethodName() { return methodName; } public int getNParams() { return paramNames.length; } public String getParamName(int n) { return paramNames[n]; } public JavaTypeName getParamType(int n) { return paramTypes[n]; } public boolean isParamFinal(int n) { return paramFinal[n]; } /** * Get the return type. * @return JavaTypeName */ public JavaTypeName getReturnType() { return returnType; } /** * @return int the number of exceptions thrown by this constructor. */ public int getNThrownExceptions() { return thrownExceptionList.size(); } public JavaTypeName getThrownException(int n) { return thrownExceptionList.get(n); } /** * @return the method descriptor, as specified in the Java Virtual Machine Specification section 4.3. */ public String getJVMMethodDescriptor() { StringBuilder sb = new StringBuilder("("); for (int i = 0, nParams = paramNames.length; i < nParams; ++i) { sb.append(paramTypes[i].getJVMDescriptor()); } sb.append(')').append(returnType.getJVMDescriptor()); return sb.toString(); } /** * @return representation of this JavaMethod for debug purposes only. */ @Override public String toString() { return JavaSourceGenerator.toDebugString(this); } /** * Accepts the visitation of a visitor, which implements the * JavaModelVisitor interface. This abstract method is to be overridden * by each concrete subclass so that the correct visit method on the * visitor may be called based upon the type of the element being * visited. Each concrete subclass of JavaExpression should correspond * one-to-one with a visit method declaration in the SourceModelVisitor * interface. * <p> * * As the JavaModelVisitor follows a more general visitor pattern * where arguments can be passed into the visit methods and return * values obtained from them, this method passes through the argument * into the visit method, and returns as its return value the return * value of the visit method. * <p> * * Nonetheless, for a significant portion of the common cases, the state of the * visitation can simply be kept as member variables within the visitor itself, * thereby eliminating the need to use the argument and return value of the * visit methods. In these scenarios, the recommended approach is to use * {@link Void} as the type argument for both <code>T</code> and <code>R</code>, and * pass in null as the argument, and return null as the return value. * <p> * * @see JavaModelVisitor * * @param <T> the argument type. If the visitation argument is not used, specify {@link Void}. * @param <R> the return type. If the return value is not used, specify {@link Void}. * * @param visitor * the visitor * @param arg * the argument to be passed to the visitor's visitXXX method * @return the return value of the visitor's visitXXX method */ public <T, R> R accept(JavaModelVisitor<T, R> visitor, T arg) { return visitor.visitJavaMethod(this, arg); } public JavaStatement.JavaDocComment getJavaDocComment() { return javaDocComment; } public void setJavaDocComment(JavaStatement.JavaDocComment javaDocComment) { this.javaDocComment = javaDocComment; } }