content: /**
   *  @(#)Method.java
   *
   * JReversePro - Java Decompiler / Disassembler.
   * Copyright (C) 2008 Karthik Kumar.
   * 
   * Licensed under the Apache License, Version 2.0 (the "License"); 
   * you may not use this file except in compliance with the License. 
   * You may obtain a copy of the License at 
   *  
   *  	http://www.apache.org/licenses/LICENSE-2.0 
   *  
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS, 
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
   * See the License for the specific language governing permissions and
   * limitations under the License.
   **/
  package org.jreversepro.reflect;
  
  import java.util.ArrayList;
  import java.util.List;
  
  import org.jreversepro.jvm.JVMConstants;
  import org.jreversepro.jvm.TypeInferrer;
  import org.jreversepro.reflect.variabletable.DynamicVariableTable;
  import org.jreversepro.reflect.variabletable.DynamicVariableTableContext;
  import org.jreversepro.reflect.variabletable.VariableTable;
  
  /**
   * <b>Method</b> is the abstract representation of a method in the class
   * method..
   * 
   * @author Karthik Kumar
   * 
   *         Modified by karthikeyan c - added LocalvariableTable an optional
   *         attribute
   */
  public class Method extends Member {
  
    /**
     * Signature of a method.
     * 
     * For example for a method as follows.
     * 
     * public void doSomething( int ,int ) //random method signature the signature
     * will be (II)V .
     */
    private String signature;
  
    /**
     * Throws classes is a List containing String of the java data types that are
     * thrown by this method.
     */
    private List<String> throwsClasses;
  
    /**
     * Maximum size that the JVM stack will occupy on execution of all
     * instructions present in this method.
     */
    private int maxStack;
  
    /**
     * Maximum number of local variables present in the local variable table at
     * any time.
     */
    private int maxLocals;
  
    /**
     * This contains the bytecodes that are present for the method.
     */
    private byte[] bytecodes;
  
    /**
     * List of Exceptions thrown by the given method.
     */
    private final ExceptionList exceptionBlocks; // exception table
  
    /**
     * This contains the LineNumberTable that may be compiled for this method.
     * Nevertheless for decompiling purposes this can't be used since this is
     * optional information in a class file. If debugging is turned off then the
     * compiler wont bother to generate this LineNumberTable.
     */
    private LineNumberTable lineTable;
  
    /**
     * The LocalVariableTable optional variable-length attribute providing debug
     * information and also to provide meaningful names to parameters of a method
     * as well as local variables in a method. This will be populated and used
     * only when debugging is turned on [using -g option]. Else the decompiler
     * will assign its own name.
     * 
     */
    private VariableTable variableTable;
  
    /**
     * 
     */
    public Method() {
      exceptionBlocks = new ExceptionList();
      throwsClasses = new ArrayList<String>(2);
    }
  
    /**
     * Setter method for Signature
     * 
     * @param rhsSign
     *          Signature field value.
     */
    public void setSignature(String rhsSign) {
      signature = rhsSign;
    }
  
    /**
     * Add an exception block.
     * 
     * @param startPc
     *          Start of the try block
     * @param endPc
     *          End of try block
     * @param handlerPc
     *          Beginning of handler block
     * @param datatype
     *          Type of the class that the handler is going to handle.
     */
    public void addExceptionBlock(int startPc, int endPc, int handlerPc,
        String datatype) {
      this.exceptionBlocks.addExceptionBlock(startPc, endPc, handlerPc, datatype);
    }
  
    /**
     * Sets the line number table.
     * 
     * @param rhsLineTable
     *          Line number Table that is created by the compiler if the debugging
     *          option is on.
     */
    public void setLineTable(LineNumberTable rhsLineTable) {
      lineTable = rhsLineTable;
    }
  
    /**
     * Returns the return type of the method.
     * 
     * @return Returns the return type of the method.
     */
    public String getReturnType() {
      return TypeInferrer.getReturnType(signature);
    }
  
    /**
     * Returns the signature of the method.
     * 
     * @return Returns the signature of the method.
     */
    public String getSignature() {
      return signature;
    }
  
    /**
     * Returns the argument list. The members of the list are String.
     * 
     * @return Returns the argument list.
     */
    public List<String> getArgList() {
      return TypeInferrer.getArguments(signature);
    }
  
    /**
     * Returns the .list of classes thrown by this method. The individual members
     * are string.
     * 
     * @return Returns the list of thrown classes
     */
    public List<String> getThrowsClasses() {
      return throwsClasses;
    }
  
    /**
     * Returns the maximum local members of this method.
     * 
     * @return Returns the Max Locals
     */
    public int getMaxLocals() {
      return maxLocals;
    }
  
    /**
     * Returns the max. stack
     * 
     * @return Returns max stack.
     */
    public int getMaxStack() {
      return maxStack;
    }
  
    /**
     * Sets the .list of classes thrown by this method. The individual members are
     * string.
     * 
     * @param throwsClasses
     *          Classes Thrown
     */
    public void setThrowsClasses(List<String> throwsClasses) {
      this.throwsClasses = throwsClasses;
    }
  
    /**
     * Sets the max. local variable field
     * 
     * @param maxLocals
     *          Max Locals
     */
    public void setMaxLocals(int maxLocals) {
      this.maxLocals = maxLocals;
    }
  
    /**
     * Sets the max. stack variable field.
     * 
     * @param maxStack
     *          Max. Stack length
     */
    public void setMaxStack(int maxStack) {
      this.maxStack = maxStack;
    }
  
    /**
     * Returns the bytecode array of the method
     * 
     * @return bytecode array.
     */
    public byte[] getBytes() {
      return bytecodes;
    }
  
    /**
     * Sets the bytecode array.
     * 
     * @param bytecodes
     *          the bytecode array input.
     */
    public void setBytes(byte[] bytecodes) {
      this.bytecodes = bytecodes;
    }
  
    /**
     * 
     * @return the optional local variable table info
     */
    public VariableTable getVariableTable() {
      return variableTable;
    }
  
    public void setVariableTable(VariableTable localVarTable) {
      this.variableTable = localVarTable;
    }
  
    /**
     * Returns the exception table.
     * 
     * @return Returns the exception table.
     */
    public ExceptionList getExceptionBlocks() {
      return exceptionBlocks;
    }
  
    /**
     * Returns the LineNumberTable of the method.
     * 
     * @return Returns the LineNumberTable of the method.
     */
    public LineNumberTable getLineTable() {
      return lineTable;
    }
  
    public void initializeSymbolTable() {
      if (variableTable == null) {
        DynamicVariableTableContext ctx = new DynamicVariableTableContext(this);
        variableTable = new DynamicVariableTable(ctx);
      } else {
        throw new IllegalStateException(
            "VariableTable is already set. We should not be calling this");
      }
    }
  
    /**
     * Returns the initial code / information about the method. It consists of
     * maximum local information maximum stack information and the exception class
     * handler information.
     * 
     * @return Returns the code/information about the method.
     */
    public String getLocalStackInfo() {
      StringBuilder result = new StringBuilder("");
      result.append("\n\t  // Max Locals " + maxLocals);
      result.append("  , Max Stack " + maxStack);
      result.append(exceptionBlocks != null ? exceptionBlocks.toString() : "");
      // TODO: appending the Exception table info. to be done.
      return result.toString();
    }
  
    /**
     * Returns ifthis method is static.
     * 
     * @return Returns true, if this is a static method. false, otherwise.
     */
    @Override
    public boolean isStatic() {
      return (super.isStatic() || name.equals(JVMConstants.CLINIT));
    }
  
  }
  