use of io.confluent.kafka.schemaregistry.protobuf.dynamic.MessageDefinition in project schema-registry by confluentinc.
the class ProtobufData method messageDefinitionFromConnectSchema.
private MessageDefinition messageDefinitionFromConnectSchema(FromConnectContext ctx, DynamicSchema.Builder schema, String name, Schema messageElem) {
MessageDefinition.Builder message = MessageDefinition.newBuilder(name);
int index = 1;
for (Field field : messageElem.fields()) {
Schema fieldSchema = field.schema();
String fieldTag = fieldSchema.parameters() != null ? fieldSchema.parameters().get(PROTOBUF_TYPE_TAG) : null;
int tag = fieldTag != null ? Integer.parseInt(fieldTag) : index++;
FieldDefinition fieldDef = fieldDefinitionFromConnectSchema(ctx, schema, message, fieldSchema, scrubName(field.name()), tag);
if (fieldDef != null) {
boolean isProto3Optional = "optional".equals(fieldDef.getLabel());
if (isProto3Optional) {
// Add a synthentic oneof
MessageDefinition.OneofBuilder oneofBuilder = message.addOneof("_" + fieldDef.getName());
oneofBuilder.addField(true, fieldDef.getType(), fieldDef.getName(), fieldDef.getNum(), fieldDef.getDefaultVal(), fieldDef.getDoc(), fieldDef.getParams());
} else {
message.addField(fieldDef.getLabel(), fieldDef.getType(), fieldDef.getName(), fieldDef.getNum(), fieldDef.getDefaultVal(), fieldDef.getDoc(), fieldDef.getParams());
}
}
}
return message.build();
}
use of io.confluent.kafka.schemaregistry.protobuf.dynamic.MessageDefinition in project schema-registry by confluentinc.
the class ProtobufSchema method toDynamicSchema.
private static DynamicSchema toDynamicSchema(String name, ProtoFileElement rootElem, Map<String, ProtoFileElement> dependencies) {
if (log.isTraceEnabled()) {
log.trace("*** toDynamicSchema: {}", ProtobufSchemaUtils.toString(rootElem));
}
DynamicSchema.Builder schema = DynamicSchema.newBuilder();
try {
Syntax syntax = rootElem.getSyntax();
if (syntax != null) {
schema.setSyntax(syntax.toString());
}
if (rootElem.getPackageName() != null) {
schema.setPackage(rootElem.getPackageName());
}
for (TypeElement typeElem : rootElem.getTypes()) {
if (typeElem instanceof MessageElement) {
MessageDefinition message = toDynamicMessage(syntax, (MessageElement) typeElem);
schema.addMessageDefinition(message);
} else if (typeElem instanceof EnumElement) {
EnumDefinition enumer = toDynamicEnum((EnumElement) typeElem);
schema.addEnumDefinition(enumer);
}
}
for (ServiceElement serviceElement : rootElem.getServices()) {
ServiceDefinition service = toDynamicService(serviceElement);
schema.addServiceDefinition(service);
}
for (String ref : rootElem.getImports()) {
ProtoFileElement dep = dependencies.get(ref);
if (dep != null) {
schema.addDependency(ref);
schema.addSchema(toDynamicSchema(ref, dep, dependencies));
}
}
for (String ref : rootElem.getPublicImports()) {
ProtoFileElement dep = dependencies.get(ref);
if (dep != null) {
schema.addPublicDependency(ref);
schema.addSchema(toDynamicSchema(ref, dep, dependencies));
}
}
Map<String, OptionElement> options = mergeOptions(rootElem.getOptions());
OptionElement javaPackageName = options.get(JAVA_PACKAGE);
if (javaPackageName != null) {
schema.setJavaPackage(javaPackageName.getValue().toString());
}
OptionElement javaOuterClassname = options.get(JAVA_OUTER_CLASSNAME);
if (javaOuterClassname != null) {
schema.setJavaOuterClassname(javaOuterClassname.getValue().toString());
}
OptionElement javaMultipleFiles = options.get(JAVA_MULTIPLE_FILES);
if (javaMultipleFiles != null) {
schema.setJavaMultipleFiles(Boolean.parseBoolean(javaMultipleFiles.getValue().toString()));
}
OptionElement javaStringCheckUtf8 = options.get(JAVA_STRING_CHECK_UTF8);
if (javaStringCheckUtf8 != null) {
schema.setJavaStringCheckUtf8(Boolean.parseBoolean(javaStringCheckUtf8.getValue().toString()));
}
OptionElement optimizeFor = options.get(OPTIMIZE_FOR);
if (optimizeFor != null) {
schema.setOptimizeFor(OptimizeMode.valueOf(optimizeFor.getValue().toString()));
}
OptionElement goPackage = options.get(GO_PACKAGE);
if (goPackage != null) {
schema.setGoPackage(goPackage.getValue().toString());
}
OptionElement ccGenericServices = options.get(CC_GENERIC_SERVICES);
if (ccGenericServices != null) {
schema.setCcGenericServices(Boolean.parseBoolean(ccGenericServices.getValue().toString()));
}
OptionElement javaGenericServices = options.get(JAVA_GENERIC_SERVICES);
if (javaGenericServices != null) {
schema.setJavaGenericServices(Boolean.parseBoolean(javaGenericServices.getValue().toString()));
}
OptionElement pyGenericServices = options.get(PY_GENERIC_SERVICES);
if (pyGenericServices != null) {
schema.setPyGenericServices(Boolean.parseBoolean(pyGenericServices.getValue().toString()));
}
OptionElement phpGenericServices = options.get(PHP_GENERIC_SERVICES);
if (phpGenericServices != null) {
schema.setPhpGenericServices(Boolean.parseBoolean(phpGenericServices.getValue().toString()));
}
OptionElement isDeprecated = options.get(DEPRECATED);
if (isDeprecated != null) {
schema.setDeprecated(Boolean.parseBoolean(isDeprecated.getValue().toString()));
}
OptionElement ccEnableArenas = options.get(CC_ENABLE_ARENAS);
if (ccEnableArenas != null) {
schema.setCcEnableArenas(Boolean.parseBoolean(ccEnableArenas.getValue().toString()));
}
OptionElement objcClassPrefix = options.get(OBJC_CLASS_PREFIX);
if (objcClassPrefix != null) {
schema.setObjcClassPrefix(objcClassPrefix.getValue().toString());
}
OptionElement csharpNamespace = options.get(CSHARP_NAMESPACE);
if (csharpNamespace != null) {
schema.setCsharpNamespace(csharpNamespace.getValue().toString());
}
OptionElement swiftPrefix = options.get(SWIFT_PREFIX);
if (swiftPrefix != null) {
schema.setSwiftPrefix(swiftPrefix.getValue().toString());
}
OptionElement phpClassPrefix = options.get(PHP_CLASS_PREFIX);
if (phpClassPrefix != null) {
schema.setPhpClassPrefix(phpClassPrefix.getValue().toString());
}
OptionElement phpNamespace = options.get(PHP_NAMESPACE);
if (phpNamespace != null) {
schema.setPhpNamespace(phpNamespace.getValue().toString());
}
OptionElement phpMetadataNamespace = options.get(PHP_METADATA_NAMESPACE);
if (phpMetadataNamespace != null) {
schema.setPhpMetadataNamespace(phpMetadataNamespace.getValue().toString());
}
OptionElement rubyPackage = options.get(RUBY_PACKAGE);
if (rubyPackage != null) {
schema.setRubyPackage(rubyPackage.getValue().toString());
}
Optional<OptionElement> meta = findOption(CONFLUENT_FILE_META, options);
String doc = findDoc(meta);
Map<String, String> params = findParams(meta);
schema.setMeta(doc, params);
schema.setName(name);
return schema.build();
} catch (Descriptors.DescriptorValidationException e) {
throw new IllegalStateException(e);
}
}
use of io.confluent.kafka.schemaregistry.protobuf.dynamic.MessageDefinition in project schema-registry by confluentinc.
the class ProtobufSchema method toDynamicMessage.
private static MessageDefinition toDynamicMessage(Syntax syntax, MessageElement messageElem) {
log.trace("*** message: {}", messageElem.getName());
MessageDefinition.Builder message = MessageDefinition.newBuilder(messageElem.getName());
for (TypeElement type : messageElem.getNestedTypes()) {
if (type instanceof MessageElement) {
message.addMessageDefinition(toDynamicMessage(syntax, (MessageElement) type));
} else if (type instanceof EnumElement) {
message.addEnumDefinition(toDynamicEnum((EnumElement) type));
}
}
Set<String> added = new HashSet<>();
for (OneOfElement oneof : messageElem.getOneOfs()) {
MessageDefinition.OneofBuilder oneofBuilder = message.addOneof(oneof.getName());
for (FieldElement field : oneof.getFields()) {
String defaultVal = field.getDefaultValue();
String jsonName = field.getJsonName();
Map<String, OptionElement> options = mergeOptions(field.getOptions());
CType ctype = findOption(CTYPE, options).map(o -> CType.valueOf(o.getValue().toString())).orElse(null);
JSType jstype = findOption(JSTYPE, options).map(o -> JSType.valueOf(o.getValue().toString())).orElse(null);
Boolean isDeprecated = findOption(DEPRECATED, options).map(o -> Boolean.valueOf(o.getValue().toString())).orElse(null);
Optional<OptionElement> meta = findOption(CONFLUENT_FIELD_META, options);
String doc = findDoc(meta);
Map<String, String> params = findParams(meta);
oneofBuilder.addField(false, field.getType(), field.getName(), field.getTag(), defaultVal, jsonName, doc, params, ctype, jstype, isDeprecated);
added.add(field.getName());
}
}
// Process fields after messages so that any newly created map entry messages are at the end
for (FieldElement field : messageElem.getFields()) {
if (added.contains(field.getName())) {
continue;
}
Field.Label fieldLabel = field.getLabel();
String label = fieldLabel != null ? fieldLabel.toString().toLowerCase() : null;
boolean isProto3Optional = "optional".equals(label) && syntax == Syntax.PROTO_3;
String fieldType = field.getType();
String defaultVal = field.getDefaultValue();
String jsonName = field.getJsonName();
Map<String, OptionElement> options = mergeOptions(field.getOptions());
CType ctype = findOption(CTYPE, options).map(o -> CType.valueOf(o.getValue().toString())).orElse(null);
Boolean isPacked = findOption(PACKED, options).map(o -> Boolean.valueOf(o.getValue().toString())).orElse(null);
JSType jstype = findOption(JSTYPE, options).map(o -> JSType.valueOf(o.getValue().toString())).orElse(null);
Boolean isDeprecated = findOption(DEPRECATED, options).map(o -> Boolean.valueOf(o.getValue().toString())).orElse(null);
Optional<OptionElement> meta = findOption(CONFLUENT_FIELD_META, options);
String doc = findDoc(meta);
Map<String, String> params = findParams(meta);
ProtoType protoType = ProtoType.get(fieldType);
ProtoType keyType = protoType.getKeyType();
ProtoType valueType = protoType.getValueType();
// Map fields are only permitted in messages
if (protoType.isMap() && keyType != null && valueType != null) {
label = "repeated";
fieldType = toMapEntry(field.getName());
MessageDefinition.Builder mapMessage = MessageDefinition.newBuilder(fieldType);
mapMessage.setMapEntry(true);
mapMessage.addField(null, keyType.toString(), KEY_FIELD, 1, null, null, null);
mapMessage.addField(null, valueType.toString(), VALUE_FIELD, 2, null, null, null);
message.addMessageDefinition(mapMessage.build());
}
if (isProto3Optional) {
// Add synthetic oneof after real oneofs
MessageDefinition.OneofBuilder oneofBuilder = message.addOneof("_" + field.getName());
oneofBuilder.addField(true, fieldType, field.getName(), field.getTag(), defaultVal, jsonName, doc, params, ctype, jstype, isDeprecated);
} else {
message.addField(label, fieldType, field.getName(), field.getTag(), defaultVal, jsonName, doc, params, ctype, isPacked, jstype, isDeprecated);
}
}
for (ReservedElement reserved : messageElem.getReserveds()) {
for (Object elem : reserved.getValues()) {
if (elem instanceof String) {
message.addReservedName((String) elem);
} else if (elem instanceof Integer) {
int tag = (Integer) elem;
message.addReservedRange(tag, tag + 1);
} else if (elem instanceof IntRange) {
IntRange range = (IntRange) elem;
message.addReservedRange(range.getStart(), range.getEndInclusive() + 1);
} else {
throw new IllegalStateException("Unsupported reserved type: " + elem.getClass().getName());
}
}
}
Map<String, OptionElement> options = mergeOptions(messageElem.getOptions());
Boolean noStandardDescriptorAccessor = findOption(NO_STANDARD_DESCRIPTOR_ACCESSOR, options).map(o -> Boolean.valueOf(o.getValue().toString())).orElse(null);
if (noStandardDescriptorAccessor != null) {
message.setNoStandardDescriptorAccessor(noStandardDescriptorAccessor);
}
Boolean isDeprecated = findOption(DEPRECATED, options).map(o -> Boolean.valueOf(o.getValue().toString())).orElse(null);
if (isDeprecated != null) {
message.setDeprecated(isDeprecated);
}
Boolean isMapEntry = findOption(MAP_ENTRY, options).map(o -> Boolean.valueOf(o.getValue().toString())).orElse(null);
if (isMapEntry != null) {
message.setMapEntry(isMapEntry);
}
Optional<OptionElement> meta = findOption(CONFLUENT_MESSAGE_META, options);
String doc = findDoc(meta);
Map<String, String> params = findParams(meta);
message.setMeta(doc, params);
return message.build();
}
Aggregations