001    package org.shiftone.jrat.core;
002    
003    
004    import org.shiftone.jrat.util.Assert;
005    import org.shiftone.jrat.util.log.Logger;
006    
007    import java.io.Serializable;
008    import java.util.Map;
009    import java.util.WeakHashMap;
010    
011    
012    /**
013     * Immutable object that can be used to uniquely identify a method - suitable
014     * for use as a Map key.
015     *
016     * @author jeff@shiftone.org (Jeff Drost)
017     */
018    public class MethodKey implements Serializable, Comparable {
019    
020        private static final Logger LOG = Logger.getLogger(MethodKey.class);
021        private static final long serialVersionUID = 1;
022    
023    
024        private ClassKey classKey = null;
025        private String methodName = null;
026        private String signature = null;
027        private int hashCode = 0;
028        private transient String toStringValue = null;
029        private transient Signature sig = null;
030    
031        // todo: decide if the weak map helps
032        private static Map CACHE = new WeakHashMap(); //<MethodKey, MethodKey>
033    
034    
035        public static MethodKey getInstance(String fullyQualifiedClassName, String methodName, String signature) {
036            ClassKey classKey = ClassKey.getInstance(fullyQualifiedClassName);
037            MethodKey key = new MethodKey(classKey, methodName, signature);
038            MethodKey value = (MethodKey) CACHE.get(key);
039            if (value == null) {
040                CACHE.put(key, key);
041                value = key;
042            }
043            return value;
044        }
045    
046        private MethodKey() {
047        }
048    
049    
050        private MethodKey(ClassKey classKey, String methodName, String signature) {
051    
052            Assert.assertNotNull("classKey", classKey);
053            Assert.assertNotNull("methodName", methodName);
054            Assert.assertNotNull("signature", signature);
055    
056            this.classKey = classKey;
057            this.methodName = methodName;
058            this.signature = signature;
059    
060            hashCode = classKey.hashCode();
061            hashCode = (29 * hashCode) + methodName.hashCode();
062            hashCode = (29 * hashCode) + signature.hashCode();
063        }
064    
065        /**
066         * setCat(Cat)
067         */
068        public final String getShortMethodDescription() {
069            return methodName + "(" + getSig().getShortText() + ")";
070        }
071    
072        public final String getMethodName() {
073            return methodName;
074        }
075    
076    
077        public final String getSignature() {
078            return signature;
079        }
080    
081    
082        public String getPackageName() {
083            return classKey.getPackageName();
084        }
085    
086        /**
087         * Gets the package's name in pieces.
088         */
089        public String[] getPackageNameParts() {
090            return classKey.getPackageNameParts();
091        }
092    
093        public final String getFullyQualifiedClassName() {
094            return classKey.getFullyQualifiedClassName();
095        }
096    
097        /**
098         * Returns just the class name w/o a package.
099         */
100        public final String getClassName() {
101            return classKey.getClassName();
102        }
103    
104        public final boolean equals(Object o) {
105    
106            if (this == o) {
107                return true;
108            }
109    
110            if (!(o instanceof MethodKey)) {
111                return false;
112            }
113    
114            final MethodKey other = (MethodKey) o;
115    
116            if (!classKey.equals(classKey)) {
117                return false;
118            }
119    
120            if (!methodName.equals(other.methodName)) {
121                return false;
122            }
123    
124            if (!signature.equals(other.signature)) {
125                return false;
126            }
127    
128            return true;
129        }
130    
131    
132        public final String toString() {
133    
134            if (toStringValue == null) {
135                toStringValue = classKey.getClassName() + '.' + methodName + getPrettySignature();
136            }
137    
138            return toStringValue;
139        }
140    
141    
142        public Signature getSig() {
143    
144            if (sig == null) {
145                sig = new Signature(signature);
146            }
147    
148            return sig;
149        }
150    
151    
152        public int compareTo(Object o) {
153            MethodKey other = (MethodKey) o;
154            int c = classKey.compareTo(other.classKey);
155            if (c == 0) {
156                c = methodName.compareTo(other.methodName);
157                if (c == 0) {
158                    c = signature.compareTo(other.signature);
159                }
160            }
161            return c;
162        }
163    
164        public final String getPrettySignature() {
165            return "(" + getSig().getShortText() + ")";
166        }
167    
168    
169        public final int hashCode() {
170            return hashCode;
171        }
172    
173    }