* Licensed 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 rx.util.functions;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import org.jackhuang.hellominecraft.utils.logging.logger.Logger;
/**
* Allows execution of functions from multiple different languages.
*
* Language support is provided via implementations of
* {@link FunctionLanguageAdaptor}.
*
* This class will dynamically look for known language adaptors on the classpath
* at startup or new ones can be registered using
* {@link #registerLanguageAdaptor(Class[], FunctionLanguageAdaptor)}.
*/
public class Functions {
private static final Logger logger = new Logger("Functions");
private final static ConcurrentHashMap, FunctionLanguageAdaptor> languageAdaptors = new ConcurrentHashMap<>();
private static boolean loadLanguageAdaptor(String name) {
String className = "rx.lang." + name.toLowerCase() + "." + name + "Adaptor";
try {
Class> c = Class.forName(className);
FunctionLanguageAdaptor a = (FunctionLanguageAdaptor) c.newInstance();
registerLanguageAdaptor(a.getFunctionClass(), a);
logger.info("Successfully loaded function language adaptor: " + name + " with path: " + className);
} catch (ClassNotFoundException e) {
logger.info("Could not find function language adaptor: " + name + " with path: " + className);
return false;
} catch (Exception e) {
logger.error("Failed trying to initialize function language adaptor: " + className, e);
return false;
}
return true;
}
public static void registerLanguageAdaptor(Class>[] functionClasses, FunctionLanguageAdaptor adaptor) {
for (Class> functionClass : functionClasses) {
if (functionClass.getPackage().getName().startsWith("java."))
throw new IllegalArgumentException("FunctionLanguageAdaptor implementations can not specify java.lang.* classes.");
languageAdaptors.put(functionClass, adaptor);
}
}
public static void removeLanguageAdaptor(Class> functionClass) {
languageAdaptors.remove(functionClass);
}
public static Collection getRegisteredLanguageAdaptors() {
return languageAdaptors.values();
}
/**
* Utility method for determining the type of closure/function and executing
* it.
*
* @param function
*/
@SuppressWarnings({ "rawtypes" })
public static FuncN from(final Object function) {
if (function == null)
throw new RuntimeException("function is null. Can't send arguments to null function.");
/*
* check for typed Rx Function implementation first
*/
if (function instanceof Function)
return fromFunction((Function) function);
else
/*
* not an Rx Function so try language adaptors
*/
// check for language adaptor
for (final Class c : languageAdaptors.keySet())
if (c.isInstance(function)) {
final FunctionLanguageAdaptor la = languageAdaptors.get(c);
// found the language adaptor so wrap in FuncN and return
return new FuncN() {
@Override
public Object call(Object... args) {
return la.call(function, args);
}
};
} // no language adaptor found
// no support found
throw new RuntimeException("Unsupported closure type: " + function.getClass().getSimpleName());
}
//
// @SuppressWarnings("unchecked")
// private static R executionRxFunction(Function function, Object... args) {
// // check Func* classes
// if (function instanceof Func0) {
// Func0 f = (Func0) function;
// if (args.length != 0) {
// throw new RuntimeException("The closure was Func0 and expected no arguments, but we received: " + args.length);
// }
// return (R) f.call();
// } else if (function instanceof Func1) {
// Func1