001: /*
002: * $Id: MethodKey.java 4661 2007-01-02 16:52:26Z 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: 4661 $
047: */
048: public abstract class MethodKey {
049:
050: private int hash;
051: private String name;
052: private Class sender;
053: private boolean isCallToSuper;
054:
055: public MethodKey(Class sender, String name, boolean isCallToSuper) {
056: this .sender = sender;
057: this .name = name;
058: this .isCallToSuper = isCallToSuper;
059: }
060:
061: /**
062: * Creates an immutable copy that we can cache.
063: */
064: public MethodKey createCopy() {
065: int size = getParameterCount();
066: Class[] paramTypes = new Class[size];
067: for (int i = 0; i < size; i++) {
068: paramTypes[i] = getParameterType(i);
069: }
070: return new DefaultMethodKey(sender, name, paramTypes,
071: isCallToSuper);
072: }
073:
074: public boolean equals(Object that) {
075: if (this == that) {
076: return true;
077: } else if (hashCode() == that.hashCode()
078: && that instanceof MethodKey) {
079: return equals((MethodKey) that);
080: }
081: return false;
082: }
083:
084: public boolean equals(MethodKey that) {
085: int size = getParameterCount();
086: if (sender != that.sender)
087: return false;
088: if (isCallToSuper != that.isCallToSuper)
089: return false;
090: if (name.equals(that.name) && size == that.getParameterCount()) {
091: for (int i = 0; i < size; i++) {
092: if (!getParameterType(i).equals(
093: that.getParameterType(i))) {
094: return false;
095: }
096: }
097: return true;
098: }
099: return false;
100: }
101:
102: public int hashCode() {
103: if (hash == 0) {
104: hash = createHashCode();
105: if (hash == 0) {
106: hash = 0xcafebabe;
107: }
108: }
109: return hash;
110: }
111:
112: public String toString() {
113: return super .toString() + "[name:" + name + "; params:"
114: + getParamterTypes();
115: }
116:
117: public String getName() {
118: return name;
119: }
120:
121: public List getParamterTypes() {
122: int size = getParameterCount();
123: if (size <= 0) {
124: return Collections.EMPTY_LIST;
125: }
126: List params = new ArrayList(size);
127: for (int i = 0; i < size; i++) {
128: params.add(getParameterType(i));
129: }
130: return params;
131: }
132:
133: public abstract int getParameterCount();
134:
135: public abstract Class getParameterType(int index);
136:
137: protected int createHashCode() {
138: int answer = name.hashCode();
139: int size = getParameterCount();
140:
141: /** @todo we should use the real Josh Bloch algorithm here */
142:
143: // can't remember the exact Josh Bloch algorithm and I've not got the book handy
144: // but its something like this IIRC
145: for (int i = 0; i < size; i++) {
146: answer *= 37;
147: answer += 1 + getParameterType(i).hashCode();
148: }
149: answer *= 37;
150: answer += isCallToSuper ? 1 : 0;
151: answer *= 37;
152: answer += 1 + sender.hashCode();
153: return answer;
154: }
155: }
|