/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.react.bridge;
import javax.annotation.concurrent.Immutable;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.Set;
import com.facebook.react.common.MapBuilder;
import com.facebook.infer.annotation.Assertions;
/**
* Registration info for a {@link JavaScriptModule}. Maps its methods to method ids.
*/
@Immutable
class JavaScriptModuleRegistration {
private final int mModuleId;
private final Class<? extends JavaScriptModule> mModuleInterface;
private final Map<Method, Integer> mMethodsToIds;
private final Map<Method, String> mMethodsToTracingNames;
JavaScriptModuleRegistration(int moduleId, Class<? extends JavaScriptModule> moduleInterface) {
mModuleId = moduleId;
mModuleInterface = moduleInterface;
mMethodsToIds = MapBuilder.newHashMap();
mMethodsToTracingNames = MapBuilder.newHashMap();
final Method[] declaredMethods = mModuleInterface.getDeclaredMethods();
Arrays.sort(declaredMethods, new Comparator<Method>() {
@Override
public int compare(Method lhs, Method rhs) {
return lhs.getName().compareTo(rhs.getName());
}
});
// Methods are sorted by name so we can dupe check and have obvious ordering
String previousName = null;
for (int i = 0; i < declaredMethods.length; i++) {
Method method = declaredMethods[i];
String name = method.getName();
Assertions.assertCondition(
!name.equals(previousName),
"Method overloading is unsupported: " + mModuleInterface.getName() + "#" + name);
previousName = name;
mMethodsToIds.put(method, i);
mMethodsToTracingNames.put(method, "JSCall__" + getName() + "_" + method.getName());
}
}
public int getModuleId() {
return mModuleId;
}
public int getMethodId(Method method) {
final Integer id = mMethodsToIds.get(method);
if (id == null) {
Assertions.assertUnreachable("Unknown method: " + method.getName());
}
return id.intValue();
}
public String getTracingName(Method method) {
return Assertions.assertNotNull(mMethodsToTracingNames.get(method));
}
public Class<? extends JavaScriptModule> getModuleInterface() {
return mModuleInterface;
}
public String getName() {
// With proguard obfuscation turned on, proguard apparently (poorly) emulates inner classes or
// something because Class#getSimpleName() no longer strips the outer class name. We manually
// strip it here if necessary.
String name = mModuleInterface.getSimpleName();
int dollarSignIndex = name.lastIndexOf('$');
if (dollarSignIndex != -1) {
name = name.substring(dollarSignIndex + 1);
}
return name;
}
public Set<Method> getMethods() {
return mMethodsToIds.keySet();
}
}