[protobuf] How to construct a Builder from a FieldDescriptor with JavaType.MESSAGE

2015-01-26 Thread Jon Emerson
Hi There,

I'm writing a utility to convert data stored in MongoDB back to protocol 
buffer format.  My strategy is to look for each field in the protocol 
buffer definition, and if there's a matching field from my MongoDB object, 
then pull that data and set it on my protocol buffer builder.  This works 
great, except for embedded messages.  I can't figure out how to create a 
Builder for an embedded message.

Here's my first try:

  switch (fieldDescriptor.getJavaType()) {
...
case MESSAGE:
  ClassT type = (ClassT) 
fieldDescriptor.getDefaultValue().getClass(); // getDefaultValue throws.
  messageBuilder.addRepeatedField(fieldDescriptor,
  fromDBObject((BasicBSONObject) object.get(fieldName), 
type));
  break;

But the noted line throws with the error, 
java.lang.UnsupportedOperationException: FieldDescriptor.getDefaultValue() 
called on an embedded message field.

Here's my second try:
  switch (fieldDescriptor.getJavaType()) {
...
case MESSAGE:
  Message.Builder embeddedMessageBuilder = 
messageBuilder.getFieldBuilder(fieldDescriptor); // getFieldBuilder throws.
  ClassT type = (ClassT) 
embeddedMessageBuilder.getDefaultInstanceForType().getClass();
  messageBuilder.addRepeatedField(fieldDescriptor,
  fromDBObject((BasicBSONObject) object.get(fieldName), 
type));
  break;

Here, the noted line throws with the error, 
java.lang.UnsupportedOperationException: getFieldBuilder() called on a 
non-Message type.

I'm not sure what else to try.  My question boils down to a very simple 
one: Given a FieldDescriptor that describes an embedded repeated MESSAGE 
field, how can you create a Builder for it?

Thanks!
jon

-- 
You received this message because you are subscribed to the Google Groups 
Protocol Buffers group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to protobuf+unsubscr...@googlegroups.com.
To post to this group, send email to protobuf@googlegroups.com.
Visit this group at http://groups.google.com/group/protobuf.
For more options, visit https://groups.google.com/d/optout.


Re: [protobuf] How to construct a Builder from a FieldDescriptor with JavaType.MESSAGE

2015-01-26 Thread Jon Emerson
Ah, thanks for the response!  That wasn't it though - Calling
.getRepeatedFieldBuilder(FieldDescriptor, int) against a Builder I'm just
starting to populate will inevitably give only IndexOutOfBounds
exceptions... Since nothing's set in the repeated field yet!

But your response did give give me a huge hint: LOTS of new functionality
for working with repeated field builders was added in the November 2014
release to Github.  I was still using the release from July.  So I didn't
see .newBuilderForField(FieldDescriptor)... that was what I needed!  After
upgrading to the latest branch I was up and going in no time.

Here's my final (working!) code:

case MESSAGE:
  Message.Builder embeddedMessageBuilder =
  messageBuilder.newBuilderForField(fieldDescriptor);
  ClassT type = (ClassT)
embeddedMessageBuilder.getDefaultInstanceForType().getClass();
  for (T t : fromDBList((BasicBSONList) object.get(fieldName),
type)) {
messageBuilder.addRepeatedField(fieldDescriptor, t);
  }
  break;

It's still a bit janky that I construct a Builder to get its
DefaultInstance to then get its Class (I do this because I call my methods
recursively, and the top-most method needs a hint as to the top-most
Object's class)... But, hey, it works for now.  If there's more elegant
ways to get a Class from a repeated FieldDescriptor, I'd love to hear it.

Thanks!!

On Mon, Jan 26, 2015 at 5:55 PM, Feng Xiao xiaof...@google.com wrote:

 As it's a repeated field, you should use getRepeatedFieldBuilder.

 On Mon Jan 26 2015 at 5:38:23 PM Jon Emerson panac...@gmail.com wrote:

 Hi There,

 I'm writing a utility to convert data stored in MongoDB back to protocol
 buffer format.  My strategy is to look for each field in the protocol
 buffer definition, and if there's a matching field from my MongoDB object,
 then pull that data and set it on my protocol buffer builder.  This works
 great, except for embedded messages.  I can't figure out how to create a
 Builder for an embedded message.

 Here's my first try:

   switch (fieldDescriptor.getJavaType()) {
 ...
 case MESSAGE:
   ClassT type = (ClassT)
 fieldDescriptor.getDefaultValue().getClass(); // getDefaultValue throws.
   messageBuilder.addRepeatedField(fieldDescriptor,
   fromDBObject((BasicBSONObject) object.get(fieldName),
 type));
   break;

 But the noted line throws with the error,
 java.lang.UnsupportedOperationException: FieldDescriptor.getDefaultValue()
 called on an embedded message field.

 Here's my second try:
   switch (fieldDescriptor.getJavaType()) {
 ...
 case MESSAGE:
   Message.Builder embeddedMessageBuilder =
 messageBuilder.getFieldBuilder(fieldDescriptor); // getFieldBuilder throws.
   ClassT type = (ClassT)
 embeddedMessageBuilder.getDefaultInstanceForType().getClass();
   messageBuilder.addRepeatedField(fieldDescriptor,
   fromDBObject((BasicBSONObject) object.get(fieldName),
 type));
   break;

 Here, the noted line throws with the error,
 java.lang.UnsupportedOperationException: getFieldBuilder() called on a
 non-Message type.

 I'm not sure what else to try.  My question boils down to a very simple
 one: Given a FieldDescriptor that describes an embedded repeated MESSAGE
 field, how can you create a Builder for it?

 Thanks!
 jon

 --
 You received this message because you are subscribed to the Google Groups
 Protocol Buffers group.
 To unsubscribe from this group and stop receiving emails from it, send an
 email to protobuf+unsubscr...@googlegroups.com.
 To post to this group, send email to protobuf@googlegroups.com.
 Visit this group at http://groups.google.com/group/protobuf.
 For more options, visit https://groups.google.com/d/optout.



-- 
You received this message because you are subscribed to the Google Groups 
Protocol Buffers group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to protobuf+unsubscr...@googlegroups.com.
To post to this group, send email to protobuf@googlegroups.com.
Visit this group at http://groups.google.com/group/protobuf.
For more options, visit https://groups.google.com/d/optout.