/** * Assigns all fields in {@link JsonNode} instance to a {@link Builder}. * * @param builder the builder to be populated * @param root the JSON object * @return the original builder, populated with any fields that were discovered */ public static Builder toProto(final Builder builder, final JsonNode root) { Descriptor type = builder.getDescriptorForType(); for (final FieldDescriptor fieldDesc : type.getFields()) { final String attrName = fieldDesc.getName(); final JsonNode node = root.get(attrName); if (node == null) { continue; } if (node.isNull()) { continue; } if (fieldDesc.isRepeated()) { final Iterator<JsonNode> iter = node.getElements(); while (iter.hasNext()) { builder.addRepeatedField(fieldDesc, toJavaObj(builder, fieldDesc, iter.next())); } } else { builder.setField(fieldDesc, toJavaObj(builder, fieldDesc, node)); } } return builder; }
private static Object readSingleFieldNoTag( CodedInputStream input, FieldDescriptor fd, Builder enclosingBuilder) throws IOException { switch (fd.getType()) { case DOUBLE: return input.readDouble(); case FLOAT: return input.readFloat(); case INT64: case UINT64: return input.readInt64(); case INT32: return input.readInt32(); case FIXED64: return input.readFixed64(); case FIXED32: return input.readFixed32(); case BOOL: return input.readBool(); case STRING: return input.readString(); case GROUP: case MESSAGE: Builder fieldBuilder = enclosingBuilder.newBuilderForField(fd); input.readMessage(fieldBuilder, null); return fieldBuilder.build(); case BYTES: return input.readBytes(); case UINT32: return input.readUInt32(); case ENUM: EnumValueDescriptor eVal = fd.getEnumType().findValueByNumber(input.readEnum()); // ideally if a given enum does not exist, we should search // unknown fields. but we don't have access to that here. return default return eVal != null ? eVal : fd.getDefaultValue(); case SFIXED32: return input.readSFixed32(); case SFIXED64: return input.readSFixed64(); case SINT32: return input.readSInt32(); case SINT64: return input.readSInt64(); default: throw new IllegalArgumentException( "Unknown type " + fd.getType() + " for " + fd.getFullName()); } }
static void mergeCollection( Readable reader, ExtensionRegistry extensionRegistry, @SuppressWarnings("TypeMayBeWeakened") Builder builder, MergeCallback callback) throws IOException { CharSequence input = toStringBuilder(reader); Tokenizer tokenizer = new Tokenizer(input.subSequence(0, input.length())); tokenizer.consume(JS_ARRAY_OPEN_STR); // Special case of empty list of messages: "[]" if (!tokenizer.tryConsume(JS_ARRAY_CLOSE_STR)) { // At least one Message present do { Builder thisBuilder = builder.clone(); tokenizer.consume("{"); // Needs to happen when the object starts. while (!tokenizer.tryConsume("}")) { // Continue till the object is done mergeField(tokenizer, extensionRegistry, thisBuilder); } callback.onMerge(thisBuilder); // Iterate if we consume a separator. } while (tokenizer.tryConsume(JS_ARRAY_SEP_STR)); // Make sure the next character terminates the array tokenizer.consume(JS_ARRAY_CLOSE_STR); } }
private static Object toJavaObj( final Builder builder, final FieldDescriptor fieldDesc, final JsonNode node) { Object value; switch (fieldDesc.getJavaType()) { case MESSAGE: final Builder subBuilder = builder.newBuilderForField(fieldDesc); value = toProto(subBuilder, node).build(); break; case BOOLEAN: value = Boolean.valueOf(node.getBooleanValue()); break; case BYTE_STRING: try { value = node.getBinaryValue(); } catch (IOException e) { throw new RuntimeException(e); } break; case DOUBLE: value = Double.valueOf(node.getDoubleValue()); break; case FLOAT: value = Float.valueOf(Double.valueOf(node.getDoubleValue()).floatValue()); break; case ENUM: value = fieldDesc.getEnumType().findValueByName(node.getTextValue()); break; case INT: value = Integer.valueOf(node.getIntValue()); break; case LONG: value = Long.valueOf(node.getLongValue()); break; case STRING: value = node.getTextValue(); break; default: throw new IllegalArgumentException(); } return value; }
/** * Converts a DataBag into a List of objects with the type in the given FieldDescriptor. DataBags * don't map cleanly to repeated protobuf types, so each Tuple has to be unwrapped (by taking the * first element if the type is primitive or by converting the Tuple to a Message if the type is * MESSAGE), and the contents have to be appended to a List. * * @param containingMessageBuilder a Message builder for the Message that contains this repeated * field * @param fieldDescriptor a FieldDescriptor for this repeated field * @param bag the DataBag being serialized * @return a protobuf-friendly List of fieldDescriptor-type objects */ public List<Object> dataBagToRepeatedField( Builder containingMessageBuilder, FieldDescriptor fieldDescriptor, DataBag bag) { ArrayList<Object> bagContents = new ArrayList<Object>((int) bag.size()); Iterator<Tuple> bagIter = bag.iterator(); while (bagIter.hasNext()) { Tuple tuple = bagIter.next(); if (fieldDescriptor.getType() == FieldDescriptor.Type.MESSAGE) { Builder nestedMessageBuilder = containingMessageBuilder.newBuilderForField(fieldDescriptor); bagContents.add(tupleToMessage((Builder) nestedMessageBuilder, tuple)); } else { try { bagContents.add(tupleFieldToSingleField(fieldDescriptor, tuple.get(0))); } catch (ExecException e) { LOG.warn("Could not add a value for repeated field with descriptor " + fieldDescriptor); } } } return bagContents; }
/** * Turn a Tuple into a Message with the given type. * * @param builder a builder for the Message type the tuple will be converted to * @param tuple the tuple * @return a message representing the given tuple */ public Message tupleToMessage(Builder builder, Tuple tuple) { List<FieldDescriptor> fieldDescriptors = builder.getDescriptorForType().getFields(); if (tuple == null) { return builder.build(); } for (int i = 0; i < fieldDescriptors.size() && i < tuple.size(); i++) { Object tupleField = null; FieldDescriptor fieldDescriptor = fieldDescriptors.get(i); try { tupleField = tuple.get(i); } catch (ExecException e) { LOG.warn( "Could not convert tuple field " + tupleField + " to field with descriptor " + fieldDescriptor); continue; } if (tupleField != null) { if (fieldDescriptor.isRepeated()) { // Repeated fields are set with Lists containing objects of the fields' Java type. builder.setField( fieldDescriptor, dataBagToRepeatedField(builder, fieldDescriptor, (DataBag) tupleField)); } else { if (fieldDescriptor.getType() == FieldDescriptor.Type.MESSAGE) { Builder nestedMessageBuilder = builder.newBuilderForField(fieldDescriptor); builder.setField( fieldDescriptor, tupleToMessage((Builder) nestedMessageBuilder, (Tuple) tupleField)); } else { builder.setField(fieldDescriptor, tupleFieldToSingleField(fieldDescriptor, tupleField)); } } } } return builder.build(); }
/** * Returns a field descriptor for the field of the given builder with the given CAP name. Takes * care of differences in casing between CAP and proto. * * @param builder the builder to search in * @param name the CAP name to search for * @return the field, or null if it does not exist */ public static FieldDescriptor findFieldByName(Builder builder, String name) { return builder == null ? null : builder.getDescriptorForType().findFieldByName(underscoreCase(name).toLowerCase()); }
/** * Wrapper around {@link #readFieldNoTag(CodedInputStream, FieldDescriptor, Builder)}. <br> * same as <br> * <code> * builder.setField(fd, readFieldNoTag(input, fd, builder)); </code> */ public static void setFieldValue(CodedInputStream input, FieldDescriptor fd, Builder builder) throws IOException { builder.setField(fd, readFieldNoTag(input, fd, builder)); }