package org.ovirt.engine.ui.webadmin.plugin.jsni;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
/**
* Simple wrapper around a native JS function object.
*/
public final class JsFunction extends JavaScriptObject {
/**
* Callback interface for handling results from native function invocation.
*/
public interface ResultHandler<T> {
void onResult(T result);
}
/**
* Callback interface for handling errors during native function invocation.
*/
public interface ErrorHandler {
void onError(String message);
}
public static final String RESULT_TYPE_STRING = "string"; //$NON-NLS-1$
public static final String RESULT_TYPE_NUMBER = "number"; //$NON-NLS-1$
public static final String RESULT_TYPE_BOOLEAN = "boolean"; //$NON-NLS-1$
protected JsFunction() {
}
/**
* Retrieves a function object from the given {@code owner} object.
* <p>
* Returns an empty (no-op) function in following situations:
* <ul>
* <li>{@code owner} object is {@code null}
* <li>requested function object is not present in {@code owner} object
* <li>requested function object is present in {@code owner} object, but has wrong type (i.e. not a function)
* </ul>
* <p>
* As a result, this method will never return {@code null}.
*/
public static native JsFunction get(JavaScriptObject owner, String functionName) /*-{
var targetFunction = (owner != null) ? owner[functionName] : null;
if (targetFunction != null && typeof targetFunction === 'function') {
return targetFunction;
}
return function() {};
}-*/;
/**
* Invokes the native function, without expecting return value.
* <p>
* All method parameters are optional (can be {@code null}).
* <p>
* Returns {@code true} if the function completed successfully, or {@code false} if an exception escaped the
* function call.
*/
public boolean invoke(JsArray<?> args, ErrorHandler errorHandler) {
return invoke(args, null, null, errorHandler);
}
/**
* Invokes the native function.
* <p>
* All method parameters are optional (can be {@code null}). Following result types are supported:
* <ul>
* <li>{@value #RESULT_TYPE_STRING}, maps to {@code ResultHandler<String>}
* <li>{@value #RESULT_TYPE_NUMBER}, maps to {@code ResultHandler<Double>}
* <li>{@value #RESULT_TYPE_BOOLEAN}, maps to {@code ResultHandler<Boolean>}
* </ul>
* <p>
* Returns {@code true} if the function completed successfully, or {@code false} if an exception escaped the
* function call.
*/
public native <T> boolean invoke(JsArray<?> args, String resultType, ResultHandler<T> resultHandler, ErrorHandler errorHandler) /*-{
var wrappedFunction = this;
var invokeWrappedFunction = function() {
if (typeof wrappedFunction === 'function') {
return wrappedFunction.apply(this, args);
} else {
// If the wrapped object is not a JavaScript function, use null as invocation result
return null;
}
};
var handleInvocationResult = function(result) {
if (resultHandler != null && resultType != null && (typeof result === resultType || result === null)) {
switch (resultType) {
case 'string':
resultHandler.@org.ovirt.engine.ui.webadmin.plugin.jsni.JsFunction.ResultHandler::onResult(Ljava/lang/Object;)(result);
break;
case 'number':
// All native JavaScript numeric values are implicitly double-precision
resultHandler.@org.ovirt.engine.ui.webadmin.plugin.jsni.JsFunction.ResultHandler::onResult(Ljava/lang/Object;)(@java.lang.Double::valueOf(D)(result));
break;
case 'boolean':
resultHandler.@org.ovirt.engine.ui.webadmin.plugin.jsni.JsFunction.ResultHandler::onResult(Ljava/lang/Object;)(@java.lang.Boolean::valueOf(Z)(result));
break;
}
}
};
var handleInvocationError = function(error) {
if (errorHandler != null) {
errorHandler.@org.ovirt.engine.ui.webadmin.plugin.jsni.JsFunction.ErrorHandler::onError(Ljava/lang/String;)(error.toString());
}
};
try {
handleInvocationResult(invokeWrappedFunction());
return true;
} catch (e) {
handleInvocationError(e);
return false;
}
}-*/;
}