static SpecificData getModelForSchema()

in parquet-avro/src/main/java/org/apache/parquet/avro/AvroRecordConverter.java [183:244]


  static SpecificData getModelForSchema(Schema schema) {
    final Class<?> clazz;

    if (schema != null && (schema.getType() == Schema.Type.RECORD || schema.getType() == Schema.Type.UNION)) {
      clazz = SpecificData.get().getClass(schema);
    } else {
      return null;
    }

    // If clazz == null, the underlying Avro class for the schema is not on the classpath
    if (clazz == null) {
      return null;
    }

    final SpecificData model;
    try {
      final Field modelField = clazz.getDeclaredField("MODEL$");
      modelField.setAccessible(true);

      model = (SpecificData) modelField.get(null);
    } catch (NoSuchFieldException e) {
      LOG.info(String.format(
        "Generated Avro class %s did not contain a MODEL$ field. Parquet will use default SpecificData model for " +
          "reading and writing.", clazz));
      return null;
    } catch (IllegalAccessException e) {
      LOG.warn(String.format(
        "Field `MODEL$` in class %s was inaccessible. Parquet will use default SpecificData model for " +
          "reading and writing.", clazz), e);
      return null;
    }

    final String avroVersion = getRuntimeAvroVersion();
    // Avro 1.7 and 1.8 don't include conversions in the MODEL$ field by default
    if (avroVersion != null && (avroVersion.startsWith("1.8.") || avroVersion.startsWith("1.7."))) {
      final Field conversionsField;
      try {
        conversionsField = clazz.getDeclaredField("conversions");
      } catch (NoSuchFieldException e) {
        // Avro classes without logical types (denoted by the "conversions" field) can be returned as-is
        return model;
      }

      final Conversion<?>[] conversions;
      try {
        conversionsField.setAccessible(true);
        conversions = (Conversion<?>[]) conversionsField.get(null);
      } catch (IllegalAccessException e) {
        LOG.warn(String.format("Field `conversions` in class %s was inaccessible. Parquet will use default " +
          "SpecificData model for reading and writing.", clazz));
        return null;
      }

      for (int i = 0; i < conversions.length; i++) {
        if (conversions[i] != null) {
          model.addLogicalTypeConversion(conversions[i]);
        }
      }
    }

    return model;
  }