in packages/pigeon/lib/java_generator.dart [116:253]
void _writeHostApi(Indent indent, Api api) {
assert(api.location == ApiLocation.host);
indent.writeln(
'/** Generated interface from Pigeon that represents a handler of messages from Flutter.*/');
indent.write('public interface ${api.name} ');
indent.scoped('{', '}', () {
for (final Method method in api.methods) {
final String returnType = method.isAsynchronous
? 'void'
: _javaTypeForDartType(method.returnType);
final List<String> argSignature = <String>[];
if (method.arguments.isNotEmpty) {
final Iterable<String> argTypes =
method.arguments.map((NamedType e) => _javaTypeForDartType(e.type));
final Iterable<String> argNames =
method.arguments.map((NamedType e) => e.name);
argSignature
.addAll(map2(argTypes, argNames, (String argType, String argName) {
return '$argType $argName';
}));
}
if (method.isAsynchronous) {
final String returnType = method.returnType.isVoid
? 'Void'
: _javaTypeForDartType(method.returnType);
argSignature.add('Result<$returnType> result');
}
indent.writeln('$returnType ${method.name}(${argSignature.join(', ')});');
}
indent.addln('');
final String codecName = _getCodecName(api);
indent.format('''
/** The codec used by ${api.name}. */
static MessageCodec<Object> getCodec() {
\treturn $codecName.INSTANCE;
}
''');
indent.writeln(
'/** Sets up an instance of `${api.name}` to handle messages through the `binaryMessenger`. */');
indent.write(
'static void setup(BinaryMessenger binaryMessenger, ${api.name} api) ');
indent.scoped('{', '}', () {
for (final Method method in api.methods) {
final String channelName = makeChannelName(api, method);
indent.write('');
indent.scoped('{', '}', () {
indent.writeln('BasicMessageChannel<Object> channel =');
indent.inc();
indent.inc();
indent.writeln(
'new BasicMessageChannel<>(binaryMessenger, "$channelName", getCodec());');
indent.dec();
indent.dec();
indent.write('if (api != null) ');
indent.scoped('{', '} else {', () {
indent.write('channel.setMessageHandler((message, reply) -> ');
indent.scoped('{', '});', () {
final String returnType = method.returnType.isVoid
? 'Void'
: _javaTypeForDartType(method.returnType);
indent.writeln('Map<String, Object> wrapped = new HashMap<>();');
indent.write('try ');
indent.scoped('{', '}', () {
final List<String> methodArgument = <String>[];
if (method.arguments.isNotEmpty) {
indent.writeln(
'ArrayList<Object> args = (ArrayList<Object>)message;');
enumerate(method.arguments, (int index, NamedType arg) {
// The StandardMessageCodec can give us [Integer, Long] for
// a Dart 'int'. To keep things simple we just use 64bit
// longs in Pigeon with Java.
final bool isInt = arg.type.baseName == 'int';
final String argType =
isInt ? 'Number' : _javaTypeForDartType(arg.type);
final String argCast = isInt ? '.longValue()' : '';
final String argName = _getSafeArgumentName(index, arg);
indent.writeln(
'$argType $argName = ($argType)args.get($index);');
indent.write('if ($argName == null) ');
indent.scoped('{', '}', () {
indent.writeln(
'throw new NullPointerException("$argName unexpectedly null.");');
});
methodArgument.add('$argName$argCast');
});
}
if (method.isAsynchronous) {
final String resultValue =
method.returnType.isVoid ? 'null' : 'result';
const String resultName = 'resultCallback';
indent.format('''
Result<$returnType> $resultName = new Result<$returnType>() {
\tpublic void success($returnType result) {
\t\twrapped.put("${Keys.result}", $resultValue);
\t\treply.reply(wrapped);
\t}
\tpublic void error(Throwable error) {
\t\twrapped.put("${Keys.error}", wrapError(error));
\t\treply.reply(wrapped);
\t}
};
''');
methodArgument.add(resultName);
}
final String call =
'api.${method.name}(${methodArgument.join(', ')})';
if (method.isAsynchronous) {
indent.writeln('$call;');
} else if (method.returnType.isVoid) {
indent.writeln('$call;');
indent.writeln('wrapped.put("${Keys.result}", null);');
} else {
indent.writeln('$returnType output = $call;');
indent.writeln('wrapped.put("${Keys.result}", output);');
}
});
indent.write('catch (Error | RuntimeException exception) ');
indent.scoped('{', '}', () {
indent.writeln(
'wrapped.put("${Keys.error}", wrapError(exception));');
if (method.isAsynchronous) {
indent.writeln('reply.reply(wrapped);');
}
});
if (!method.isAsynchronous) {
indent.writeln('reply.reply(wrapped);');
}
});
});
indent.scoped(null, '}', () {
indent.writeln('channel.setMessageHandler(null);');
});
});
}
});
});
}