I'm constructing DynamicMessage
in java from .proto
file I loaded during runtime.
My problem is setting extension to such message.
I have:
Descriptors.Descriptor
of the containing type and DynamicMessage
created for it
Descriptors.Descriptor
of the extension type and DynamicMessage
created for it
Now I don't know how to set the extension to the containing message.
The containing descriptor, if I ask for field list, lists only the fields without the fields in the extension. Which makes sense.
The extension descriptor has only the fields from the extending type (it doesn't have the fields from containing type).
Please advice how I can combine these together.
To get to the context you might want to have a look on my previous question on this topic which didn't care about extensions: Protocol buffer objects generated at runtime
EDIT:
In fact I'm looking for analogy of .setExtension
of the generated message. I noticed that only GeneratedMessage
extends ExtendableMessage
but I believe there must be a way :)
Extensions are described by FieldDescriptor
s, just like regular fields, so when using the dynamic interfaces, you actually use exactly the same methods to access either one.
Keep in mind that extensions are actually declared independently from either the extended type or the extension type. For example, this is valid:
message Foo { extensions 1000 to max; }
message Bar { ... }
extend Foo {
optional Bar ext1 = 1234;
optional Bar ext2 = 2345;
}
Notice that we declared two extensions to Foo
of type Bar
. So, simply knowing that you're looking for an extension of type Bar
is not good enough -- you have to specify which one.
In any case, the various descriptor types like FileDescriptor
and Descriptor
have findExtensionByName()
methods which can be used to look up an extension descriptor. Note that this method looks for extensions declared within the scope of the descriptor on which you call it -- it does not find extensions to that message type. That is, if you have:
message Foo { extensions 1000 to max; }
message Bar {
extend Foo {
optional int32 ext1 = 1234;
}
}
extend Foo {
optional int32 ext2 = 2345;
}
In order to find the extension ext1
, you would have to call findExtensionByName("ext1")
on the Descriptor
for Bar
, not the descriptor for Foo
. To find ext2
, you would have to call findExtensionByName("ext2")
on the file's FileDescriptor
.
You may also want to take a look at the ExtensionRegistry
class, which can be used to look up extensions by their fully-qualified name (e.g. "mypackage.Bar.ext1"
), but this requires that you first register the descriptors you're interested in, so it might not be terribly helpful.
I also tring to find a solution to this in C++ and it seems easier with following code:
const Reflection* reflection = merged_doc_info.GetReflection();<br/>
const FieldDescriptor * ext_fld=reflection->FindKnownExtensionByName("msg.usage");
assert(ext_fld!=0);
reflection->SetUInt32(&merged_doc_info,ext_fld,123);
an altenative way is to simulate how protoc command does, generate lines of java code
like
msgBuilder.setExtension(msg.usage, "1");