private SchemaCompatibilityResult calculateCompatibility()

in lang/java/avro/src/main/java/org/apache/avro/SchemaCompatibility.java [262:391]


    private SchemaCompatibilityResult calculateCompatibility(final Schema reader, final Schema writer,
        final Deque<String> location) {
      assert (reader != null);
      assert (writer != null);
      SchemaCompatibilityResult result = SchemaCompatibilityResult.compatible();

      if (reader.getType() == writer.getType()) {
        switch (reader.getType()) {
        case NULL:
        case BOOLEAN:
        case INT:
        case LONG:
        case FLOAT:
        case DOUBLE:
        case BYTES:
        case STRING: {
          return result;
        }
        case ARRAY: {
          return result
              .mergedWith(getCompatibility("items", reader.getElementType(), writer.getElementType(), location));
        }
        case MAP: {
          return result.mergedWith(getCompatibility("values", reader.getValueType(), writer.getValueType(), location));
        }
        case FIXED: {
          result = result.mergedWith(checkSchemaNames(reader, writer, location));
          return result.mergedWith(checkFixedSize(reader, writer, location));
        }
        case ENUM: {
          result = result.mergedWith(checkSchemaNames(reader, writer, location));
          return result.mergedWith(checkReaderEnumContainsAllWriterEnumSymbols(reader, writer, location));
        }
        case RECORD: {
          result = result.mergedWith(checkSchemaNames(reader, writer, location));
          return result.mergedWith(checkReaderWriterRecordFields(reader, writer, location));
        }
        case UNION: {
          // Check that each individual branch of the writer union can be decoded:
          int i = 0;
          for (final Schema writerBranch : writer.getTypes()) {
            location.addFirst(Integer.toString(i));
            SchemaCompatibilityResult compatibility = getCompatibility(reader, writerBranch);
            if (compatibility.getCompatibility() == SchemaCompatibilityType.INCOMPATIBLE) {
              String message = String.format("reader union lacking writer type: %s", writerBranch.getType());
              result = result.mergedWith(SchemaCompatibilityResult.incompatible(
                  SchemaIncompatibilityType.MISSING_UNION_BRANCH, reader, writer, message, asList(location)));
            }
            location.removeFirst();
            i++;
          }
          // Each schema in the writer union can be decoded with the reader:
          return result;
        }

        default: {
          throw new AvroRuntimeException("Unknown schema type: " + reader.getType());
        }
        }

      } else {
        // Reader and writer have different schema types:

        // Reader compatible with all branches of a writer union is compatible
        if (writer.getType() == Schema.Type.UNION) {
          int index = 0;
          for (Schema s : writer.getTypes()) {
            result = result.mergedWith(getCompatibility(Integer.toString(index), reader, s, location));
            index++;
          }
          return result;
        }

        switch (reader.getType()) {
        case NULL:
          return result.mergedWith(typeMismatch(reader, writer, location));
        case BOOLEAN:
          return result.mergedWith(typeMismatch(reader, writer, location));
        case INT:
          return result.mergedWith(typeMismatch(reader, writer, location));
        case LONG: {
          return (writer.getType() == Type.INT) ? result : result.mergedWith(typeMismatch(reader, writer, location));
        }
        case FLOAT: {
          return ((writer.getType() == Type.INT) || (writer.getType() == Type.LONG)) ? result
              : result.mergedWith(typeMismatch(reader, writer, location));

        }
        case DOUBLE: {
          return ((writer.getType() == Type.INT) || (writer.getType() == Type.LONG) || (writer.getType() == Type.FLOAT))
              ? result
              : result.mergedWith(typeMismatch(reader, writer, location));
        }
        case BYTES: {
          return (writer.getType() == Type.STRING) ? result : result.mergedWith(typeMismatch(reader, writer, location));
        }
        case STRING: {
          return (writer.getType() == Type.BYTES) ? result : result.mergedWith(typeMismatch(reader, writer, location));
        }

        case ARRAY:
          return result.mergedWith(typeMismatch(reader, writer, location));
        case MAP:
          return result.mergedWith(typeMismatch(reader, writer, location));
        case FIXED:
          return result.mergedWith(typeMismatch(reader, writer, location));
        case ENUM:
          return result.mergedWith(typeMismatch(reader, writer, location));
        case RECORD:
          return result.mergedWith(typeMismatch(reader, writer, location));
        case UNION: {
          for (final Schema readerBranch : reader.getTypes()) {
            SchemaCompatibilityResult compatibility = getCompatibility(readerBranch, writer);
            if (compatibility.getCompatibility() == SchemaCompatibilityType.COMPATIBLE) {
              return result;
            }
          }
          // No branch in the reader union has been found compatible with the writer
          // schema:
          String message = String.format("reader union lacking writer type: %s", writer.getType());
          return result.mergedWith(SchemaCompatibilityResult
              .incompatible(SchemaIncompatibilityType.MISSING_UNION_BRANCH, reader, writer, message, asList(location)));
        }

        default: {
          throw new AvroRuntimeException("Unknown schema type: " + reader.getType());
        }
        }
      }
    }