This sample .proto is taken from http://blog.wolfman.com/articles/2011/11/23/how-to-implement-polymorphic-protocol-buffers-in-java. The groovy is rewritten in Java and C++. Also see
example 2
example.proto
package example;
option java_outer_classname = "Commands";
message BaseCommand {
extensions 100 to max;
enum CommandType {
VERSION = 1;
LOGIN = 2;
}
required CommandType type = 1;
}
message Version {
extend BaseCommand {
required Version cmd = 100;
}
required fixed32 protocol = 1;
required fixed32 versions = 2;
}
message Login {
extend BaseCommand {
required Login cmd = 101;
}
required string username = 1;
required string password = 2;
}
example.cpp
#include
#include "example.pb.h"
using namespace std;
using namespace example;
int main()
{
string sl;
BaseCommand b;
#if 0
Version ver;
ver.set_versions(10);
ver.set_protocol(15);
b.MutableExtension(Version::cmd)->set_versions(10);
b.MutableExtension(Version::cmd)->set_protocol(15);
b.set_type( BaseCommand::VERSION);
#else
b.set_type( BaseCommand::LOGIN);
b.MutableExtension(Login::cmd)->set_username("rain");
b.MutableExtension(Login::cmd)->set_password("heavy");
#endif
b.SerializeToString(&sl);
printf("%d\n", sl.length());
BaseCommand* bcmd = new BaseCommand();
if (bcmd->ParseFromString(sl))
{
printf("ParsePartialFromString ok\n");
}
printf("%d\n", bcmd->type());
switch(bcmd->type())
{
case BaseCommand::LOGIN:
{
printf("login\n");
printf("%s %s\n", b.MutableExtension(Login::cmd)->username().c_str(), b.MutableExtension(Login::cmd)->password().c_str());
break;
}
case BaseCommand::VERSION:
{
printf("version\n");
printf("%d %d\n", b.MutableExtension(Version::cmd)->versions(), b.MutableExtension(Version::cmd)->protocol());
break;
}
default:
break;
}
return 1;
}
example.java
import example.Commands;
import example.Commands.BaseCommand;
import com.google.protobuf.GeneratedMessage;
import com.google.protobuf.ExtensionRegistry;
import java.io.IOException;
class ProtoBufExample {
// Helper which wraps the BaseCommand around the extension command
static BaseCommand wrap(BaseCommand.CommandType type, GeneratedMessage.GeneratedExtension extension, Type cmd) {
return BaseCommand.newBuilder().setType(type).setExtension(extension, cmd).build();
}
ExtensionRegistry registry;
ProtoBufExample() {
// we need to register all the extensions and tell the decoder about them
// otherwise the extension will be ignored
registry= ExtensionRegistry.newInstance();
Commands.registerAllExtensions(registry);
}
BaseCommand buildVersion(int v1, int v2) {
Commands.Version vers= Commands.Version.newBuilder().setProtocol(v1).setVersions(v2).build();
// BaseCommand bcmd= BaseCommand.newBuilder().setType(BaseCommand.CommandType.VERSION).setExtension(Commands.Version.cmd, vers).build();
return wrap(BaseCommand.CommandType.VERSION, Commands.Version.cmd, vers);
}
BaseCommand buildLogin(String username, String password) {
Commands.Login l= Commands.Login.newBuilder().setUsername(username).setPassword(password).build();
return wrap(BaseCommand.CommandType.LOGIN, Commands.Login.cmd, l);
}
BaseCommand decodeIt(byte [] ba) {
// use the registry so extensions will be decoded
try{
BaseCommand b=BaseCommand.newBuilder().mergeFrom(ba, registry).build();
return b;
}
catch (IOException e) {
System.out.println("Unable to create " +e.getMessage());
return buildVersion(0,1);
}
}
public static void main(String[] args) throws Exception {
ProtoBufExample pb= new ProtoBufExample();
BaseCommand b= pb.buildVersion(1234, 5678);
//BaseCommand b= pb.buildLogin("user1", "test");
System.out.println(b);
System.out.println ("size: " + b.toByteArray().length);
BaseCommand decoded= pb.decodeIt(b.toByteArray());
System.out.println ("We got a "+ decoded.getType() +" message");
// We can switch on the CommandType enum and extract the specific command type (extension) we got
switch(decoded.getType()) {
case VERSION:
System.out.println (decoded.getExtension(Commands.Version.cmd));
break;
case LOGIN:
System.out.println (decoded.getExtension(Commands.Login.cmd));
break;
default:
System.out.println ("Don't know this type");
}
}
}