001 /* 002 * $Id: MethodKey.java,v 1.2 2004/02/21 08:13:05 jstrachan Exp $ 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: 1.2 $ 047 */ 048 public abstract class MethodKey { 049 050 private int hash; 051 private String name; 052 053 public MethodKey(String name) { 054 this.name = name; 055 } 056 057 /** 058 * Creates an immutable copy that we can cache. 059 */ 060 public MethodKey createCopy() { 061 int size = getParameterCount(); 062 Class[] paramTypes = new Class[size]; 063 for (int i = 0; i < size; i++) { 064 paramTypes[i] = getParameterType(i); 065 } 066 return new DefaultMethodKey(name, paramTypes); 067 } 068 069 public boolean equals(Object that) { 070 if (this == that) { 071 return true; 072 } 073 else if (hashCode() == that.hashCode() && that instanceof MethodKey) { 074 return equals((MethodKey) that); 075 } 076 return false; 077 } 078 079 public boolean equals(MethodKey that) { 080 int size = getParameterCount(); 081 if (name.equals(that.name) && size == that.getParameterCount()) { 082 for (int i = 0; i < size; i++) { 083 if (!getParameterType(i).equals(that.getParameterType(i))) { 084 return false; 085 } 086 } 087 return true; 088 } 089 return false; 090 } 091 092 public int hashCode() { 093 if (hash == 0) { 094 hash = createHashCode(); 095 if (hash == 0) { 096 hash = 0xcafebabe; 097 } 098 } 099 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 }