blob: dfc429e2b27bb4339667cced6c00e6377c06b020 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.jexl2.internal.introspection;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
* @author <a href="mailto:bob@werken.com">Bob McWhirter</a>
* @author <a href="mailto:Christoph.Reck@dlr.de">Christoph Reck</a>
* @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
* @author <a href="mailto:szegedia@freemail.hu">Attila Szegedi</a>
* @version $Id$
* @since 1.0
*/
final class MethodMap {
/**
* Keep track of all methods with the same name.
*/
private final Map<String, List<Method>> methodByNameMap = new HashMap<String, List<Method>>();
/**
* Add a method to a list of methods by name. For a particular class we are
* keeping track of all the methods with the same name.
*
* @param method the method.
*/
public synchronized void add(Method method) {
String methodName = method.getName();
List<Method> l = methodByNameMap.get(methodName);
if (l == null) {
l = new ArrayList<Method>();
methodByNameMap.put(methodName, l);
}
l.add(method);
}
/**
* Return a list of methods with the same name.
*
* @param key the name.
* @return List list of methods.
*/
public synchronized List<Method> get(String key) {
return methodByNameMap.get(key);
}
/**
* Returns the array of method names accessible in this class.
* @return the array of names
*/
public synchronized String[] names() {
java.util.Set<String> set = methodByNameMap.keySet();
return set.toArray(new String[set.size()]);
}
/**
* <p>
* Find a method. Attempts to find the
* most specific applicable method using the
* algorithm described in the JLS section
* 15.12.2 (with the exception that it can't
* distinguish a primitive type argument from
* an object type argument, since in reflection
* primitive type arguments are represented by
* their object counterparts, so for an argument of
* type (say) java.lang.Integer, it will not be able
* to decide between a method that takes int and a
* method that takes java.lang.Integer as a parameter.
* </p>
*
* <p>
* This turns out to be a relatively rare case
* where this is needed - however, functionality
* like this is needed.
* </p>
*
* @param methodName name of method
* @param args the actual arguments with which the method is called
* @return the most specific applicable method, or null if no
* method is applicable.
* @throws MethodKey.AmbiguousException if there is more than one maximally
* specific applicable method
*/
// CSOFF: RedundantThrows
public Method find(String methodName, Object[] args) throws MethodKey.AmbiguousException {
return find(new MethodKey(methodName, args));
}
/**
* Finds a method by key.
* @param methodKey the key
* @return the method
* @throws MethodKey.AmbiguousException if find is ambiguous
*/
Method find(MethodKey methodKey) throws MethodKey.AmbiguousException {
List<Method> methodList = get(methodKey.getMethod());
if (methodList == null) {
return null;
}
return methodKey.getMostSpecificMethod(methodList);
} // CSON: RedundantThrows
}