}
}
protected void writeBinding(FragmentGeneratorContext context, JMethod binding)
throws UnableToCompleteException {
TreeLogger logger = context.parentLogger.branch(TreeLogger.DEBUG,
"Writing binding function", null);
context = new FragmentGeneratorContext(context);
context.parentLogger = logger;
SourceWriter sw = context.sw;
TypeOracle typeOracle = context.typeOracle;
Binding bindingAnnotation = JSWrapperGenerator.hasTag(logger, binding,
Binding.class);
// Write the java half to add assertions to the code. These will be elided
// in web mode, and the method become a pure delegation, allowing it to
// be removed completely
sw.print("public void ");
sw.print(binding.getName());
sw.print("(");
JParameter[] params = binding.getParameters();
context.parameterName = "jso";
sw.print(params[0].getType().getQualifiedSourceName());
sw.print(" ");
sw.print(context.parameterName);
JClassType bindingType = null;
if (params.length == 2) {
// Infer the binding type from the second parameter of the binding
// method.
bindingType = params[1].getType().isClassOrInterface();
context.objRef = "obj";
sw.print(", ");
sw.print(bindingType.getQualifiedSourceName());
sw.print(" ");
sw.print(context.objRef);
} else if (bindingAnnotation != null
&& bindingAnnotation.value().length() > 0) {
// Use the binding type specified in the the gwt.binding annotation.
bindingType = typeOracle.findType(bindingAnnotation.value());
if (bindingType == null) {
logger.log(TreeLogger.ERROR, "Could not resolve binding type "
+ bindingType, null);
throw new UnableToCompleteException();
}
}
sw.println(") {");
sw.indent();
for (Task t : context.tasks) {
if (t.imported != null) {
String fieldName = t.getFieldName(logger);
sw.print("assert JSONWrapperUtil.hasField(");
sw.print(context.parameterName);
sw.print(", \"");
sw.print(fieldName);
sw.print("\") : \"Backing JSO missing imported function ");
sw.print(fieldName);
sw.println("\";");
}
}
sw.print(binding.getName());
sw.print("Native (");
sw.print(context.parameterName);
if (params.length == 2) {
sw.print(",");
sw.print(context.objRef);
}
sw.println(");");
sw.outdent();
sw.println("}");
// Write the native half to perform the actual binding operations
sw.print("public native void ");
sw.print(binding.getName());
sw.print("Native (");
sw.print(params[0].getType().getQualifiedSourceName());
sw.print(" ");
sw.print(context.parameterName);
if (params.length == 2) {
sw.print(", ");
sw.print(bindingType.getQualifiedSourceName());
sw.print(" ");
sw.print(context.objRef);
}
sw.println(") /*-{");
sw.indent();
// A binding should have been declared void
context.returnType = JPrimitiveType.VOID;
if (context.maintainIdentity && params.length == 2) {
// XXX link the Java object to the JSO?
// Verify that the incoming object doesn't already have a wrapper object.
// If there is a backreference, throw an exception.
sw.print("if (");
sw.print(context.parameterName);
sw.print(".");
sw.print(BACKREF);
sw.println(") {");
sw.indent();
sw.println("@com.google.gwt.jsio.client.impl.JSONWrapperUtil::throwMultipleWrapperException()();");
sw.outdent();
sw.println("}");
// Assign the backreference from the JSO object to the delegate
sw.print(context.parameterName);
sw.print(".");
sw.print(BACKREF);
sw.print(" = ");
sw.print(context.objRef);
sw.println(";");
}
writeEmptyFieldInitializers(context);
if (bindingType != null) {
// Extract the exported methods
context.tasks = TaskFactory.extractMethods(logger, typeOracle,
bindingType, TaskFactory.EXPORTER_POLICY).values();
writeMethodBindings(context);
} else {
logger.log(TreeLogger.DEBUG,
"Not binding methods to any particular type.", null);
}
sw.outdent();
sw.println("}-*/;");