View Javadoc

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 }