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 }