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     */
021    package org.biojava.utils.bytecode;
022    
023    import 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     */
036    public 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    }