001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021package org.biojava.utils.bytecode;
022
023import java.util.*;
024
025/**
026 * A method that will be generated.
027 *
028 * <p>
029 * These are instantiated by factory methods on {@link GeneratedCodeClass}, and
030 * can not be instantiated directly.
031 * </p>
032 *
033 * @author Thomas Down
034 * @author Matthew Pocock
035 */
036public final class GeneratedCodeMethod implements CodeMethod {
037  private final String name;
038  private List args;
039  private List localvars;
040  private LocalVariable thisV;
041  private int modifiers;
042  private CodeClass type;
043  private CodeClass container;
044  private Set thrownExceptions;
045  private Map nameToLocals;
046
047  GeneratedCodeMethod(
048    CodeClass container, 
049    String name, 
050    CodeClass type, 
051    CodeClass[] args, 
052    String[] names,
053    int modifiers
054  ) {
055    this.container = container;
056    this.name = name;
057    this.args = new ArrayList(Arrays.asList(args));
058    this.modifiers = modifiers;
059    this.type = type;
060    nameToLocals = new HashMap();
061    localvars = new ArrayList();
062    for(int i = 0; i < this.args.size(); ++i) {
063      if(i < names.length) {
064        LocalVariable arg = new LocalVariable(args[i], names[i]);
065        localvars.add(arg);
066        nameToLocals.put(names[i], arg);
067      } else {
068        localvars.add(new LocalVariable(args[i]));
069      }
070    }
071
072    if((modifiers & CodeUtils.ACC_STATIC) == 0) {
073      thisV = new LocalVariable(container, "this");
074      nameToLocals.put("this", thisV);
075    }
076  }
077
078  public String getName() {
079    return name;
080  }
081
082  public String getFullName() {
083    return container.getName() + "." + name;
084  }
085
086  public CodeClass getContainingClass() {
087    return container;
088  }
089
090  public String getDescriptor() {
091    StringBuffer sb = new StringBuffer();
092    sb.append('(');
093    for(Iterator i = args.iterator(); i.hasNext(); ) {
094      CodeClass cc = (CodeClass) i.next();
095      sb.append(cc.getDescriptor());
096    }
097    sb.append(')');
098    sb.append(type.getDescriptor());
099    return sb.toString();
100  }
101
102  public int getModifiers() {
103    return modifiers;
104  }
105
106  public CodeClass getReturnType() {
107    return type;
108  }
109
110  public int numParameters() {
111    return args.size();
112  }
113
114  public CodeClass getParameterType(int pos) {
115    return (CodeClass) args.get(pos);
116  }
117
118  /**
119   *  Gets the Variable attribute of the GeneratedCodeMethod object.
120   *
121   * <p>
122   * There is one local variable for each of the arguments of the method,
123   * indexed from 0.
124   * </p>
125   *
126   * @param  pos  the index of the local variable
127   * @return      the local variable
128   */
129  public LocalVariable getVariable(int pos) {
130    return (LocalVariable) localvars.get(pos);
131  }
132  
133  /**
134   * Gets the Variable attribute of the GenerateCodeMethod object by name.
135   *
136   * <P>
137   * All methods have a variable under the string "this". If it was constructed
138   * with a String [] naming the args, the locals for each local can be
139   * retrieved by name.
140   * </p>
141   *
142   * @param argName a String naming the local
143   * @return        the LocalVariable for that argName
144   * @throws        NoSuchElementException if there is no local with that name
145   */
146  public LocalVariable getVariable(String argName)
147  throws NoSuchElementException {
148    LocalVariable lv = (LocalVariable) nameToLocals.get(argName);
149    if(lv == null) {
150      throw new NoSuchElementException(
151        "Can't find local for argName " + argName
152      );
153    }
154    return lv;
155  }
156
157  /**
158   *  Gets the This attribute of the GeneratedCodeMethod object 
159   *
160   * @return    The This value 
161   */
162  public LocalVariable getThis() {
163    return thisV;
164  }
165
166  /**
167   *  Gets the ThrownExceptions attribute of the GeneratedCodeMethod object 
168   *
169   * @return    The ThrownExceptions value 
170   */
171  public Set getThrownExceptions() {
172    return Collections.unmodifiableSet(thrownExceptions);
173  }
174
175  /**
176   *  Adds a feature to the ThrownException attribute of the GeneratedCodeMethod object 
177   *
178   * @param  cc  The feature to be added to the ThrownException attribute 
179   */
180  public void addThrownException(CodeClass cc) {
181    thrownExceptions.add(cc);
182  }
183  
184  {
185    thrownExceptions = new HashSet();
186  }
187}