}
// Check all of the fields in the new schema
for(Field newField: newSchema.getFields()) {
String fieldName = newField.name();
Field oldField = oldSchema.getField(fieldName);
if(oldField == null) {
// This is a new field that did not exist in the original
// schema.
// Check if it is optional or has a default value.
if(isOptional(newField)) {
if(newField.defaultValue() == null) {
messages.add(new Message(Level.INFO, "Added optional field " + name + "."
+ fieldName
+ " with no default value."));
} else {
messages.add(new Message(Level.INFO, "Added optional field " + name + "."
+ fieldName + " with default value: "
+ newField.defaultValue()));
}
} else {
if(newField.defaultValue() == null) {
messages.add(new Message(Level.ERROR, "Added required field " + name + "."
+ fieldName
+ " with no default value."));
} else {
messages.add(new Message(Level.INFO, "Added required field " + name + "."
+ fieldName + " with default value: "
+ newField.defaultValue()));
}
}
} else {
// This is a field that existed in the original schema.
// Check if the field was changed from optional to required or
// vice versa.
boolean newFieldIsOptional = isOptional(newField);
boolean oldFieldIsOptional = isOptional(oldField);
if(oldFieldIsOptional != newFieldIsOptional) {
if(oldFieldIsOptional) {
messages.add(new Message(Level.ERROR,
"Existing field " + name + "." + fieldName
+ " was optional and is now required."));
} else {
messages.add(new Message(Level.WARN, "Existing field " + name + "."
+ fieldName
+ " was required and is now optional."));
}
}
// Recursively compare the nested field types
compareTypes(oldField.schema(), newField.schema(), messages, name + "." + fieldName);
// Check if the default value has been changed
if(newField.defaultValue() == null) {
if(oldField.defaultValue() != null) {
messages.add(new Message(Level.WARN,
"Removed default value for existing field " + name
+ "." + fieldName
+ ". The old default was: "
+ oldField.defaultValue()));
}
} else // newField.defaultValue() != null
{
if(oldField.defaultValue() == null) {
messages.add(new Message(Level.WARN,
"Added a default value for existing field " + name
+ "." + fieldName
+ ". The new default is: "
+ newField.defaultValue()));
} else if(!newField.defaultValue().equals(oldField.defaultValue())) {
messages.add(new Message(Level.INFO,
"Changed the default value for existing field "
+ name + "." + fieldName
+ ". The old default was: "
+ oldField.defaultValue()
+ ". The new default is: "
+ newField.defaultValue()));
}
}
}
// For all fields in the new schema (whether or not it existed in
// the old schema), if there is a default value for this field, make
// sure it is legal.
if(newField.defaultValue() != null) {
checkDefaultValueIsLegal(newField, messages, name + "." + fieldName);
}
}
// Check if any fields were removed.
for(Field oldField: newSchema.getFields()) {
String fieldName = oldField.name();
Field newField = newSchema.getField(fieldName);
if(newField == null) {
if(isOptional(oldField)) {
messages.add(new Message(Level.INFO, "Removed optional field " + name + "."
+ fieldName));