use of com.squareup.wire.schema.internal.parser.MessageElement 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();
}
use of com.squareup.wire.schema.internal.parser.MessageElement in project schema-registry by confluentinc.
the class ProtobufSchema method toMessageName.
public String toMessageName(MessageIndexes indexes) {
StringBuilder sb = new StringBuilder();
List<TypeElement> types = schemaObj.getTypes();
boolean first = true;
for (Integer index : indexes.indexes()) {
if (!first) {
sb.append(".");
} else {
first = false;
}
MessageElement message = getMessageAtIndex(types, index);
if (message == null) {
throw new IllegalArgumentException("Invalid message indexes: " + indexes);
}
sb.append(message.getName());
types = message.getNestedTypes();
}
String messageName = sb.toString();
String packageName = schemaObj.getPackageName();
return packageName != null && !packageName.isEmpty() ? packageName + '.' + messageName : messageName;
}
use of com.squareup.wire.schema.internal.parser.MessageElement in project schema-registry by confluentinc.
the class ProtobufSchema method toMessage.
private static MessageElement toMessage(FileDescriptorProto file, DescriptorProto descriptor) {
String name = descriptor.getName();
log.trace("*** msg name: {}", name);
ImmutableList.Builder<FieldElement> fields = ImmutableList.builder();
ImmutableList.Builder<TypeElement> nested = ImmutableList.builder();
ImmutableList.Builder<ReservedElement> reserved = ImmutableList.builder();
LinkedHashMap<String, ImmutableList.Builder<FieldElement>> oneofsMap = new LinkedHashMap<>();
for (OneofDescriptorProto od : descriptor.getOneofDeclList()) {
oneofsMap.put(od.getName(), ImmutableList.builder());
}
List<Map.Entry<String, ImmutableList.Builder<FieldElement>>> oneofs = new ArrayList<>(oneofsMap.entrySet());
for (FieldDescriptorProto fd : descriptor.getFieldList()) {
if (fd.hasOneofIndex() && !fd.getProto3Optional()) {
FieldElement field = toField(file, fd, true);
oneofs.get(fd.getOneofIndex()).getValue().add(field);
} else {
FieldElement field = toField(file, fd, false);
fields.add(field);
}
}
for (DescriptorProto nestedDesc : descriptor.getNestedTypeList()) {
MessageElement nestedMessage = toMessage(file, nestedDesc);
nested.add(nestedMessage);
}
for (EnumDescriptorProto nestedDesc : descriptor.getEnumTypeList()) {
EnumElement nestedEnum = toEnum(nestedDesc);
nested.add(nestedEnum);
}
for (ReservedRange range : descriptor.getReservedRangeList()) {
ReservedElement reservedElem = toReserved(range);
reserved.add(reservedElem);
}
for (String reservedName : descriptor.getReservedNameList()) {
ReservedElement reservedElem = new ReservedElement(DEFAULT_LOCATION, "", Collections.singletonList(reservedName));
reserved.add(reservedElem);
}
ImmutableList.Builder<OptionElement> options = ImmutableList.builder();
if (descriptor.getOptions().hasNoStandardDescriptorAccessor()) {
OptionElement option = new OptionElement(NO_STANDARD_DESCRIPTOR_ACCESSOR, Kind.BOOLEAN, descriptor.getOptions().getNoStandardDescriptorAccessor(), false);
options.add(option);
}
if (descriptor.getOptions().hasDeprecated()) {
OptionElement option = new OptionElement(DEPRECATED, Kind.BOOLEAN, descriptor.getOptions().getDeprecated(), false);
options.add(option);
}
if (descriptor.getOptions().hasMapEntry()) {
OptionElement option = new OptionElement(MAP_ENTRY, Kind.BOOLEAN, descriptor.getOptions().getMapEntry(), false);
options.add(option);
}
if (descriptor.getOptions().hasExtension(MetaProto.messageMeta)) {
Meta meta = descriptor.getOptions().getExtension(MetaProto.messageMeta);
OptionElement option = toOption(CONFLUENT_MESSAGE_META, meta);
if (option != null) {
options.add(option);
}
}
// NOTE: skip extensions, groups
return new MessageElement(DEFAULT_LOCATION, name, "", nested.build(), options.build(), reserved.build(), fields.build(), oneofs.stream().map(e -> toOneof(e.getKey(), e.getValue())).filter(e -> !e.getFields().isEmpty()).collect(Collectors.toList()), Collections.emptyList(), Collections.emptyList());
}
use of com.squareup.wire.schema.internal.parser.MessageElement in project schema-registry by confluentinc.
the class ProtobufSchemaUtils method toString.
private static String toString(Context ctx, MessageElement type, boolean normalize) {
StringBuilder sb = new StringBuilder();
sb.append("message ");
sb.append(type.getName());
sb.append(" {");
if (!type.getReserveds().isEmpty()) {
sb.append('\n');
List<ReservedElement> reserveds = type.getReserveds();
if (normalize) {
reserveds = reserveds.stream().flatMap(r -> r.getValues().stream().map(o -> new ReservedElement(r.getLocation(), r.getDocumentation(), Collections.singletonList(o)))).collect(Collectors.toList());
Comparator<Object> cmp = Comparator.comparing(r -> {
Object o = ((ReservedElement) r).getValues().get(0);
if (o instanceof IntRange) {
return ((IntRange) o).getStart();
} else if (o instanceof Integer) {
return (Integer) o;
} else {
return Integer.MAX_VALUE;
}
}).thenComparing(r -> ((ReservedElement) r).getValues().get(0).toString());
reserveds.sort(cmp);
}
for (ReservedElement reserved : reserveds) {
appendIndented(sb, toString(ctx, reserved, normalize));
}
}
if (!type.getOptions().isEmpty()) {
sb.append('\n');
List<OptionElement> options = type.getOptions();
if (normalize) {
options = new ArrayList<>(options);
options.sort(Comparator.comparing(OptionElement::getName));
}
for (OptionElement option : options) {
appendIndented(sb, toOptionString(option, normalize));
}
}
if (!type.getFields().isEmpty()) {
sb.append('\n');
List<FieldElement> fields = type.getFields();
if (normalize) {
fields = new ArrayList<>(fields);
fields.sort(Comparator.comparing(FieldElement::getTag));
}
for (FieldElement field : fields) {
appendIndented(sb, toString(ctx, field, normalize));
}
}
if (!type.getOneOfs().isEmpty()) {
sb.append('\n');
List<OneOfElement> oneOfs = type.getOneOfs();
if (normalize) {
oneOfs = oneOfs.stream().filter(o -> !o.getFields().isEmpty()).map(o -> {
List<FieldElement> fields = new ArrayList<>(o.getFields());
fields.sort(Comparator.comparing(FieldElement::getTag));
return new OneOfElement(o.getName(), o.getDocumentation(), fields, o.getGroups(), o.getOptions());
}).collect(Collectors.toList());
oneOfs.sort(Comparator.comparing(o -> o.getFields().get(0).getTag()));
}
for (OneOfElement oneOf : oneOfs) {
appendIndented(sb, toString(ctx, oneOf, normalize));
}
}
if (!type.getGroups().isEmpty()) {
sb.append('\n');
for (GroupElement group : type.getGroups()) {
appendIndented(sb, group.toSchema());
}
}
if (!type.getExtensions().isEmpty()) {
sb.append('\n');
for (ExtensionsElement extension : type.getExtensions()) {
appendIndented(sb, extension.toSchema());
}
}
if (!type.getNestedTypes().isEmpty()) {
sb.append('\n');
// the non-normalized schema to serialize message indexes
for (TypeElement typeElement : type.getNestedTypes()) {
if (typeElement instanceof MessageElement) {
if (normalize) {
TypeElementInfo typeInfo = ctx.getType(typeElement.getName(), true);
if (typeInfo != null && typeInfo.isMap()) {
// don't emit synthetic map message
continue;
}
}
try (Context.NamedScope nameScope = ctx.enterName(typeElement.getName())) {
appendIndented(sb, toString(ctx, (MessageElement) typeElement, normalize));
}
}
}
for (TypeElement typeElement : type.getNestedTypes()) {
if (typeElement instanceof EnumElement) {
try (Context.NamedScope nameScope = ctx.enterName(typeElement.getName())) {
appendIndented(sb, toString(ctx, (EnumElement) typeElement, normalize));
}
}
}
}
sb.append("}\n");
return sb.toString();
}
use of com.squareup.wire.schema.internal.parser.MessageElement in project aws-glue-schema-registry by awslabs.
the class ProtobufFile method buildIndexes.
private void buildIndexes() {
for (TypeElement typeElement : element.getTypes()) {
if (typeElement instanceof MessageElement) {
MessageElement messageElement = (MessageElement) typeElement;
processMessageElement("", messageElement);
} else if (typeElement instanceof EnumElement) {
EnumElement enumElement = (EnumElement) typeElement;
processEnumElement("", enumElement);
} else {
throw new RuntimeException();
}
}
for (ServiceElement serviceElement : element.getServices()) {
Set<String> rpcNames = new HashSet<>();
Map<String, String> rpcSignatures = new HashMap<>();
for (RpcElement rpcElement : serviceElement.getRpcs()) {
rpcNames.add(rpcElement.getName());
String signature = rpcElement.getRequestType() + ":" + rpcElement.getRequestStreaming() + "->" + rpcElement.getResponseType() + ":" + rpcElement.getResponseStreaming();
rpcSignatures.put(rpcElement.getName(), signature);
}
if (!rpcNames.isEmpty()) {
serviceRPCnames.put(serviceElement.getName(), rpcNames);
serviceRPCSignatures.put(serviceElement.getName(), rpcSignatures);
}
}
}
Aggregations