/* * 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. */ /* * JavaConstructor.java * Creation date: Oct 9, 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 constructor. * @author Edward Lam */ public class JavaConstructor { private static final String[] EMPTY_STRING_ARRAY = new String[0]; /** The modifiers for the constructor, as defined by the constants in java.lang.reflect.Modifier. */ private final int modifiers; /** The name of the constructor. */ private final String constructorName; /** The constructor's param names. */ private final String[] paramNames; /** The constructor's param types. */ private final JavaTypeName[] paramTypes; /** The body of the constructor. */ 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>(); /** Parameter types for call to superclass constructor. */ private final JavaTypeName[] superConstructorParamTypes; /** Parameter values for call to superclass constructor. */ private final JavaExpression[] superConstructorParamValues; /** * Constructor for a zero-argument java constructor. * @param modifiers modifiers for the constructor, as defined by the constants in java.lang.reflect.Modifier. * @param constructorName */ public JavaConstructor(int modifiers, String constructorName) { this(modifiers, EMPTY_STRING_ARRAY, new JavaTypeName[] {}, constructorName, new JavaExpression[]{}, new JavaTypeName[]{}); } /** * Constructor for a java constructor. * @param modifiers modifiers for the constructor, as defined by the constants in java.lang.reflect.Modifier. * @param paramNames * @param paramTypes * @param constructorName */ public JavaConstructor(int modifiers, String[] paramNames, JavaTypeName[] paramTypes, String constructorName) { this (modifiers, paramNames, paramTypes, constructorName, new JavaExpression[]{}, new JavaTypeName[]{}); } /** * Constructor for a java constructor. Includes argument values for a call to the superclass * constructor. * @param modifiers * @param paramNames - parameter names for this constructor * @param paramTypes - parameter types for this constructor * @param constructorName * @param superConstructorParamValues - parameter values for call to superclass constructor * @param superConstructorParamTypes - parameter types for call to superclass constructor */ public JavaConstructor(int modifiers, String[] paramNames, JavaTypeName[] paramTypes, String constructorName, JavaExpression[] superConstructorParamValues, JavaTypeName[] superConstructorParamTypes) { Assert.isNotNull(paramNames); Assert.isNotNull(paramTypes); Assert.isNotNull(constructorName); Assert.isNotNull(superConstructorParamValues); Assert.isNotNull(superConstructorParamTypes); if (paramNames.length != paramTypes.length) { throw new IllegalArgumentException("paramNames and paramTypes must have the same length."); } if (superConstructorParamValues.length != superConstructorParamTypes.length) { throw new IllegalArgumentException("superConstructorParamNames and superConstructorParamTypes must have the same length."); } this.modifiers = modifiers; this.paramNames = paramNames.clone(); this.paramTypes = paramTypes.clone(); this.constructorName = constructorName; this.superConstructorParamTypes = superConstructorParamTypes; this.superConstructorParamValues = superConstructorParamValues; } /** * Get the constructor name * @return String */ public String getConstructorName() { return constructorName; } /** * Add a statement to the body of the constructor. * @param statement */ public void addStatement(JavaStatement statement) { Assert.isNotNull(statement); bodyCode.addStatement(statement); } /** * Add a thrown exception to the constructor. * @param thrownExceptionName */ public void addThrows(JavaTypeName thrownExceptionName) { thrownExceptionList.add(thrownExceptionName); } /** * @return int modifiers for the constructor, as defined by the constants in java.lang.reflect.Modifier. */ public int getModifiers() { return modifiers; } /** * Get the body code. * @return Block */ public Block getBodyCode() { return bodyCode; } public int getNParams() { return paramNames.length; } public String getParamName(int n) { return paramNames[n]; } /** * Get the parameter names. Note using getNParams and getParamName is more efficient if just traversing this array. * @return String[] */ public String[] getParamNames() { return paramNames.clone(); } public JavaTypeName getParamType(int n) { return paramTypes[n]; } /** * @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); } /** * Note that the method descriptor of the constuctor always treats the returned value as void (V). * @return the method descriptor of the constructor, 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(")V"); return sb.toString(); } /** * @return representation of this JavaConstructor 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 overriden * by each concrete subclass so that the corrent 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.visitJavaConstructor(this, arg); } public JavaTypeName[] getSuperConstructorParamTypes() { return superConstructorParamTypes; } public JavaExpression[] getSuperConstructorParamValues() { return superConstructorParamValues; } }