View Javadoc

1   /*
2    * $Id: MethodKey.java,v 1.2 2004/02/21 08:13:05 jstrachan Exp $
3    *
4    * Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
5    *
6    * Redistribution and use of this software and associated documentation
7    * ("Software"), with or without modification, are permitted provided that the
8    * following conditions are met:
9    *  1. Redistributions of source code must retain copyright statements and
10   * notices. Redistributions must also contain a copy of this document.
11   *  2. Redistributions in binary form must reproduce the above copyright
12   * notice, this list of conditions and the following disclaimer in the
13   * documentation and/or other materials provided with the distribution.
14   *  3. The name "groovy" must not be used to endorse or promote products
15   * derived from this Software without prior written permission of The Codehaus.
16   * For written permission, please contact info@codehaus.org.
17   *  4. Products derived from this Software may not be called "groovy" nor may
18   * "groovy" appear in their names without prior written permission of The
19   * Codehaus. "groovy" is a registered trademark of The Codehaus.
20   *  5. Due credit should be given to The Codehaus - http://groovy.codehaus.org/
21   *
22   * THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS ``AS IS'' AND ANY
23   * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25   * DISCLAIMED. IN NO EVENT SHALL THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR
26   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32   * DAMAGE.
33   *
34   */
35  package org.codehaus.groovy.runtime;
36  
37  import java.util.ArrayList;
38  import java.util.Collections;
39  import java.util.List;
40  
41  /***
42   * An abstract base class for a key used for comparators and Map keys to lookup a method by
43   * name and parameter types
44   * 
45   * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
46   * @version $Revision: 1.2 $
47   */
48  public abstract class MethodKey {
49  
50      private int hash;
51      private String name;
52  
53      public MethodKey(String name) {
54          this.name = name;
55      }
56  
57      /***
58       * Creates an immutable copy that we can cache. 
59       */
60      public MethodKey createCopy() {
61          int size = getParameterCount();
62          Class[] paramTypes = new Class[size];
63          for (int i = 0; i < size; i++) {
64              paramTypes[i] = getParameterType(i);
65          }
66          return new DefaultMethodKey(name, paramTypes);
67      }
68  
69      public boolean equals(Object that) {
70          if (this == that) {
71              return true;
72          }
73          else if (hashCode() == that.hashCode() && that instanceof MethodKey) {
74              return equals((MethodKey) that);
75          }
76          return false;
77      }
78  
79      public boolean equals(MethodKey that) {
80          int size = getParameterCount();
81          if (name.equals(that.name) && size == that.getParameterCount()) {
82              for (int i = 0; i < size; i++) {
83                  if (!getParameterType(i).equals(that.getParameterType(i))) {
84                      return false;
85                  }
86              }
87              return true;
88          }
89          return false;
90      }
91  
92      public int hashCode() {
93          if (hash == 0) {
94              hash = createHashCode();
95              if (hash == 0) {
96                  hash = 0xcafebabe;
97              }
98          }
99          return hash;
100     }
101 
102     public String toString() {
103         return super.toString() + "[name:" + name + "; params:" + getParamterTypes();
104     }
105 
106     public String getName() {
107         return name;
108     }
109 
110     public List getParamterTypes() {
111         int size = getParameterCount();
112         if (size <= 0) {
113             return Collections.EMPTY_LIST;
114         }
115         List params = new ArrayList(size);
116         for (int i = 0; i < size; i++) {
117             params.add(getParameterType(i));
118         }
119         return params;
120     }
121 
122     public abstract int getParameterCount();
123     public abstract Class getParameterType(int index);
124 
125     protected int createHashCode() {
126         int answer = name.hashCode();
127         int size = getParameterCount();
128 
129         /*** @todo we should use the real Josh Bloch algorithm here */
130 
131         // can't remember the exact Josh Bloch algorithm and I've not got the book handy
132         // but its something like this IIRC
133         for (int i = 0; i < size; i++) {
134             answer *= 37;
135             answer = 1 + getParameterType(i).hashCode();
136         }
137         return answer;
138     }
139 }