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 }