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, ProtoFileElement protoFile, boolean normalize) {
StringBuilder sb = new StringBuilder();
if (protoFile.getSyntax() != null) {
sb.append("syntax = \"");
sb.append(protoFile.getSyntax());
sb.append("\";\n");
}
if (protoFile.getPackageName() != null) {
sb.append("package ");
sb.append(protoFile.getPackageName());
sb.append(";\n");
}
if (!protoFile.getImports().isEmpty() || !protoFile.getPublicImports().isEmpty()) {
sb.append('\n');
List<String> imports = protoFile.getImports();
if (normalize) {
imports = imports.stream().sorted().distinct().collect(Collectors.toList());
}
for (String file : imports) {
sb.append("import \"");
sb.append(file);
sb.append("\";\n");
}
List<String> publicImports = protoFile.getPublicImports();
if (normalize) {
publicImports = publicImports.stream().sorted().distinct().collect(Collectors.toList());
}
for (String file : publicImports) {
sb.append("import public \"");
sb.append(file);
sb.append("\";\n");
}
}
if (!protoFile.getOptions().isEmpty()) {
sb.append('\n');
List<OptionElement> options = protoFile.getOptions();
if (normalize) {
options = new ArrayList<>(options);
options.sort(Comparator.comparing(OptionElement::getName));
}
for (OptionElement option : options) {
sb.append(toOptionString(option, normalize));
}
}
if (!protoFile.getTypes().isEmpty()) {
sb.append('\n');
// the non-normalized schema to serialize message indexes
for (TypeElement typeElement : protoFile.getTypes()) {
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())) {
sb.append(toString(ctx, (MessageElement) typeElement, normalize));
}
}
}
for (TypeElement typeElement : protoFile.getTypes()) {
if (typeElement instanceof EnumElement) {
try (Context.NamedScope nameScope = ctx.enterName(typeElement.getName())) {
sb.append(toString(ctx, (EnumElement) typeElement, normalize));
}
}
}
}
if (!protoFile.getExtendDeclarations().isEmpty()) {
sb.append('\n');
for (ExtendElement extendDeclaration : protoFile.getExtendDeclarations()) {
sb.append(extendDeclaration.toSchema());
}
}
if (!protoFile.getServices().isEmpty()) {
sb.append('\n');
// we don't sort message/enum elements
for (ServiceElement service : protoFile.getServices()) {
sb.append(toString(ctx, service, normalize));
}
}
return sb.toString();
}
use of com.squareup.wire.schema.internal.parser.MessageElement in project schema-registry by confluentinc.
the class Context method collectTypeInfo.
private void collectTypeInfo(final SchemaReference ref, final List<TypeElement> types, boolean isOriginal) {
for (TypeElement typeElement : types) {
try (Context.NamedScope namedScope = enterName(typeElement.getName())) {
boolean isMap = false;
Optional<FieldElement> key = Optional.empty();
Optional<FieldElement> value = Optional.empty();
if (typeElement instanceof MessageElement) {
MessageElement messageElement = (MessageElement) typeElement;
isMap = ProtobufSchema.findOption("map_entry", messageElement.getOptions()).map(o -> Boolean.valueOf(o.getValue().toString())).orElse(false);
if (isMap) {
key = findField(ProtobufSchema.KEY_FIELD, messageElement.getFields());
value = findField(ProtobufSchema.VALUE_FIELD, messageElement.getFields());
}
}
addType(ref, typeElement, isMap, key.orElse(null), value.orElse(null), isOriginal);
collectTypeInfo(ref, typeElement.getNestedTypes(), isOriginal);
}
}
}
use of com.squareup.wire.schema.internal.parser.MessageElement in project schema-registry by confluentinc.
the class SchemaDiff method compareMessageElements.
private static void compareMessageElements(List<TypeElement> types, Map<String, MessageElement> messages, Map<String, Integer> messageIndexes, Map<String, EnumElement> enums) {
int index = 0;
for (TypeElement typeElement : types) {
if (typeElement instanceof MessageElement) {
MessageElement messageElement = (MessageElement) typeElement;
messages.put(messageElement.getName(), messageElement);
messageIndexes.put(messageElement.getName(), index++);
} else if (typeElement instanceof EnumElement) {
EnumElement enumElement = (EnumElement) typeElement;
enums.put(enumElement.getName(), enumElement);
}
}
}
use of com.squareup.wire.schema.internal.parser.MessageElement in project schema-registry by confluentinc.
the class SchemaDiff method compareTypeElements.
public static void compareTypeElements(final Context ctx, final List<TypeElement> original, final List<TypeElement> update) {
Map<String, MessageElement> originalMessages = new HashMap<>();
Map<String, MessageElement> updateMessages = new HashMap<>();
Map<String, Integer> originalMessageIndexes = new HashMap<>();
Map<String, Integer> updateMessageIndexes = new HashMap<>();
Map<String, EnumElement> originalEnums = new HashMap<>();
Map<String, EnumElement> updateEnums = new HashMap<>();
compareMessageElements(original, originalMessages, originalMessageIndexes, originalEnums);
compareMessageElements(update, updateMessages, updateMessageIndexes, updateEnums);
Set<String> allMessageNames = new HashSet<>(originalMessages.keySet());
allMessageNames.addAll(updateMessages.keySet());
Set<String> allEnumNames = new HashSet<>(originalEnums.keySet());
allEnumNames.addAll(updateEnums.keySet());
for (String name : allMessageNames) {
try (Context.NamedScope nameScope = ctx.enterName(name)) {
MessageElement originalMessage = originalMessages.get(name);
MessageElement updateMessage = updateMessages.get(name);
if (updateMessage == null) {
TypeElementInfo originalType = ctx.getType(name, true);
if (originalType != null && !originalType.isMap()) {
ctx.addDifference(MESSAGE_REMOVED);
}
} else if (originalMessage == null) {
TypeElementInfo updateType = ctx.getType(name, false);
if (updateType != null && !updateType.isMap()) {
ctx.addDifference(MESSAGE_ADDED);
}
} else {
MessageSchemaDiff.compare(ctx, originalMessage, updateMessage);
Integer originalMessageIndex = originalMessageIndexes.get(name);
Integer updateMessageIndex = updateMessageIndexes.get(name);
if (originalMessageIndex == null || !originalMessageIndex.equals(updateMessageIndex)) {
// Moving or reordering a message is compatible since serialized message indexes
// are w.r.t. the schema of the corresponding ID
ctx.addDifference(MESSAGE_MOVED);
}
}
}
}
for (String name : allEnumNames) {
try (Context.NamedScope nameScope = ctx.enterName(name)) {
EnumElement originalEnum = originalEnums.get(name);
EnumElement updateEnum = updateEnums.get(name);
if (updateEnum == null) {
ctx.addDifference(ENUM_REMOVED);
} else if (originalEnum == null) {
ctx.addDifference(ENUM_ADDED);
} else {
EnumSchemaDiff.compare(ctx, originalEnum, updateEnum);
}
}
}
}
use of com.squareup.wire.schema.internal.parser.MessageElement in project apicurio-registry by Apicurio.
the class FileDescriptorUtils method toDynamicMessage.
private static MessageDefinition toDynamicMessage(MessageElement messageElem) {
MessageDefinition.Builder message = MessageDefinition.newBuilder(messageElem.getName());
for (TypeElement type : messageElem.getNestedTypes()) {
if (type instanceof MessageElement) {
message.addMessageDefinition(toDynamicMessage((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 = findOption("json_name", field.getOptions()).map(o -> o.getValue().toString()).orElse(null);
oneofBuilder.addField(field.getType(), field.getName(), field.getTag(), defaultVal, jsonName);
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;
String fieldType = field.getType();
String defaultVal = field.getDefaultValue();
String jsonName = field.getJsonName();
Boolean isPacked = findOption("packed", field.getOptions()).map(o -> Boolean.valueOf(o.getValue().toString())).orElse(null);
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.getSimpleName(), KEY_FIELD, 1, null);
mapMessage.addField(null, valueType.getSimpleName(), VALUE_FIELD, 2, null);
message.addMessageDefinition(mapMessage.build());
}
message.addField(label, fieldType, field.getName(), field.getTag(), defaultVal, jsonName, isPacked);
}
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);
} else if (elem instanceof IntRange) {
IntRange range = (IntRange) elem;
message.addReservedRange(range.getStart(), range.getEndInclusive());
} else {
throw new IllegalStateException("Unsupported reserved type: " + elem.getClass().getName());
}
}
}
Boolean isMapEntry = findOption("map_entry", messageElem.getOptions()).map(o -> Boolean.valueOf(o.getValue().toString())).orElse(null);
if (isMapEntry != null) {
message.setMapEntry(isMapEntry);
}
return message.build();
}
Aggregations