001 /*
002 * $Id: MethodKey.java 4189 2006-11-02 11:44:45Z blackdrag $
003 *
004 * Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
005 *
006 * Redistribution and use of this software and associated documentation
007 * ("Software"), with or without modification, are permitted provided that the
008 * following conditions are met:
009 * 1. Redistributions of source code must retain copyright statements and
010 * notices. Redistributions must also contain a copy of this document.
011 * 2. Redistributions in binary form must reproduce the above copyright
012 * notice, this list of conditions and the following disclaimer in the
013 * documentation and/or other materials provided with the distribution.
014 * 3. The name "groovy" must not be used to endorse or promote products
015 * derived from this Software without prior written permission of The Codehaus.
016 * For written permission, please contact info@codehaus.org.
017 * 4. Products derived from this Software may not be called "groovy" nor may
018 * "groovy" appear in their names without prior written permission of The
019 * Codehaus. "groovy" is a registered trademark of The Codehaus.
020 * 5. Due credit should be given to The Codehaus - http://groovy.codehaus.org/
021 *
022 * THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS ``AS IS'' AND ANY
023 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
024 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
025 * DISCLAIMED. IN NO EVENT SHALL THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR
026 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
027 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
028 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
029 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
031 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
032 * DAMAGE.
033 *
034 */
035 package org.codehaus.groovy.runtime;
036
037 import java.util.ArrayList;
038 import java.util.Collections;
039 import java.util.List;
040
041 /**
042 * An abstract base class for a key used for comparators and Map keys to lookup a method by
043 * name and parameter types
044 *
045 * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
046 * @version $Revision: 4189 $
047 */
048 public abstract class MethodKey {
049
050 private int hash;
051 private String name;
052 private Class sender;
053
054 public MethodKey(Class sender, String name) {
055 this.sender = sender;
056 this.name = name;
057 }
058
059 /**
060 * Creates an immutable copy that we can cache.
061 */
062 public MethodKey createCopy() {
063 int size = getParameterCount();
064 Class[] paramTypes = new Class[size];
065 for (int i = 0; i < size; i++) {
066 paramTypes[i] = getParameterType(i);
067 }
068 return new DefaultMethodKey(sender, name, paramTypes);
069 }
070
071 public boolean equals(Object that) {
072 if (this == that) {
073 return true;
074 }
075 else if (hashCode() == that.hashCode() && that instanceof MethodKey) {
076 return equals((MethodKey) that);
077 }
078 return false;
079 }
080
081 public boolean equals(MethodKey that) {
082 int size = getParameterCount();
083 if (sender!=that.sender) return false;
084 if (name.equals(that.name) && size == that.getParameterCount()) {
085 for (int i = 0; i < size; i++) {
086 if (!getParameterType(i).equals(that.getParameterType(i))) {
087 return false;
088 }
089 }
090 return true;
091 }
092 return false;
093 }
094
095 public int hashCode() {
096 if (hash == 0) {
097 hash = createHashCode();
098 if (hash == 0) {
099 hash = 0xcafebabe;
100 }
101 }
102 return hash;
103 }
104
105 public String toString() {
106 return super.toString() + "[name:" + name + "; params:" + getParamterTypes();
107 }
108
109 public String getName() {
110 return name;
111 }
112
113 public List getParamterTypes() {
114 int size = getParameterCount();
115 if (size <= 0) {
116 return Collections.EMPTY_LIST;
117 }
118 List params = new ArrayList(size);
119 for (int i = 0; i < size; i++) {
120 params.add(getParameterType(i));
121 }
122 return params;
123 }
124
125 public abstract int getParameterCount();
126 public abstract Class getParameterType(int index);
127
128 protected int createHashCode() {
129 int answer = name.hashCode();
130 int size = getParameterCount();
131
132 /** @todo we should use the real Josh Bloch algorithm here */
133
134 // can't remember the exact Josh Bloch algorithm and I've not got the book handy
135 // but its something like this IIRC
136 for (int i = 0; i < size; i++) {
137 answer *= 37;
138 answer += 1 + getParameterType(i).hashCode();
139 }
140 answer *= 37;
141 answer += 1 + sender.hashCode();
142 return answer;
143 }
144 }