View Javadoc

    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 }