1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.commons.jexl2.internal.introspection;
19
20 import java.lang.reflect.Method;
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25
26 /**
27 * A map of method names to methods.
28 * @since 1.0
29 */
30 final class MethodMap {
31 /**
32 * Keep track of all methods with the same name.
33 */
34 private final Map<String, List<Method>> methodByNameMap = new HashMap<String, List<Method>>();
35
36 /**
37 * Add a method to a list of methods by name. For a particular class we are
38 * keeping track of all the methods with the same name.
39 *
40 * @param method the method.
41 */
42 public synchronized void add(Method method) {
43 String methodName = method.getName();
44
45 List<Method> l = methodByNameMap.get(methodName);
46
47 if (l == null) {
48 l = new ArrayList<Method>();
49 methodByNameMap.put(methodName, l);
50 }
51
52 l.add(method);
53 }
54
55 /**
56 * Return a list of methods with the same name.
57 *
58 * @param key the name.
59 * @return List list of methods.
60 */
61 public synchronized List<Method> get(String key) {
62 return methodByNameMap.get(key);
63 }
64
65 /**
66 * Returns the array of method names accessible in this class.
67 * @return the array of names
68 */
69 public synchronized String[] names() {
70 java.util.Set<String> set = methodByNameMap.keySet();
71 return set.toArray(new String[set.size()]);
72 }
73
74 /**
75 * <p>
76 * Find a method. Attempts to find the
77 * most specific applicable method using the
78 * algorithm described in the JLS section
79 * 15.12.2 (with the exception that it can't
80 * distinguish a primitive type argument from
81 * an object type argument, since in reflection
82 * primitive type arguments are represented by
83 * their object counterparts, so for an argument of
84 * type (say) java.lang.Integer, it will not be able
85 * to decide between a method that takes int and a
86 * method that takes java.lang.Integer as a parameter.
87 * </p>
88 *
89 * <p>
90 * This turns out to be a relatively rare case
91 * where this is needed - however, functionality
92 * like this is needed.
93 * </p>
94 *
95 * @param methodName name of method
96 * @param args the actual arguments with which the method is called
97 * @return the most specific applicable method, or null if no
98 * method is applicable.
99 * @throws MethodKey.AmbiguousException if there is more than one maximally
100 * specific applicable method
101 */
102 // CSOFF: RedundantThrows
103 public Method find(String methodName, Object[] args) throws MethodKey.AmbiguousException {
104 return find(new MethodKey(methodName, args));
105 }
106
107 /**
108 * Finds a method by key.
109 * @param methodKey the key
110 * @return the method
111 * @throws MethodKey.AmbiguousException if find is ambiguous
112 */
113 Method find(MethodKey methodKey) throws MethodKey.AmbiguousException {
114 List<Method> methodList = get(methodKey.getMethod());
115 if (methodList == null) {
116 return null;
117 }
118 return methodKey.getMostSpecificMethod(methodList);
119 } // CSON: RedundantThrows
120
121 }