All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adgear.data.plugin.ExportBase Maven / Gradle / Ivy

package com.adgear.data.plugin;

import org.apache.avro.Schema;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Base class for exporting an Avro schema in another data declaration format, such as Thrift.
 */
abstract public class ExportBase {

  static final protected Pattern idPattern =
      Pattern.compile("^\\s*\\[([0-9]+)\\]", Pattern.MULTILINE);

  static public List collectDependencies(Schema root,
                                                 List list,
                                                 boolean includeOnly) {
    switch (root.getType()) {
      case ENUM:
        if (!list.contains(root)) {
          list.add(root);
        }
        break;
      case UNION:
        for (Schema s : root.getTypes()) {
          collectDependencies(s, list, includeOnly);
        }
        break;
      case MAP:
        collectDependencies(root.getValueType(), list, includeOnly);
        break;
      case ARRAY:
        collectDependencies(root.getElementType(), list, includeOnly);
        break;
      case RECORD:
        if (!includeOnly) {
          for (Schema.Field field : root.getFields()) {
            collectDependencies(field.schema(), list, false);
          }
        }
        if (!list.contains(root)) {
          list.add(root);
        }
        break;
      default:
    }
    return list;
  }

  public String exportEnum(Schema s) throws IOException {
    StringBuilder sb = new StringBuilder();
    buildNameSpace(s, sb);
    sb.append('\n');
    buildEnumHeader(s, sb);
    int pos = 0;
    for (String symbol : s.getEnumSymbols()) {
      buildEnumField(symbol, pos++, sb);
    }
    buildEnumFooter(sb);
    return sb.toString();
  }

  public String exportRecord(Schema s, Map includePaths, Map names)
      throws IOException {
    StringBuilder sb = new StringBuilder();
    buildNameSpace(s, sb);
    sb.append('\n');
    List includeList = new ArrayList();
    for (Schema.Field field : s.getFields()) {
      collectDependencies(field.schema(), includeList, true);
    }
    for (Schema include : includeList) {
      buildInclude(include, includePaths, sb);
    }
    sb.append('\n');

    buildRecordHeader(s, sb);
    int pos = 0;
    for (Schema.Field field : s.getFields()) {
      if (field.doc() == null) {
        throw new IOException(String.format("Missing docstring for field %s in record %s.",
                                            field.name(), s.getFullName()));
      }
      Matcher idMatcher = idPattern.matcher(field.doc());
      if (!idMatcher.find()) {
        throw new IOException(String.format("Bad docstring for field %s in record %s.",
                                            field.name(), s.getFullName()));
      }
      final String id = idMatcher.group(1);
      buildRecordField(id, field, names, pos++, sb);
    }
    buildRecordFooter(sb);
    return sb.toString();
  }


  abstract protected void buildNameSpace(Schema s, StringBuilder sb);

  abstract protected void buildInclude(Schema s,
                                       Map includePaths,
                                       StringBuilder sb);

  abstract protected void buildEnumHeader(Schema s, StringBuilder sb);

  abstract protected void buildEnumFooter(StringBuilder sb);

  abstract protected void buildEnumField(String symbol, int pos, StringBuilder sb);

  abstract protected void buildRecordHeader(Schema s, StringBuilder sb);

  abstract protected void buildRecordFooter(StringBuilder sb);

  abstract protected void buildRecordField(String id,
                                           Schema.Field field,
                                           Map names,
                                           int pos,
                                           StringBuilder sb) throws IOException;

  final protected Schema resolveSchema(Schema s) throws IOException {
    if (s.getType() == Schema.Type.UNION) {
      if (s.getTypes().size() == 2) {
        if (s.getTypes().get(0).getType() == Schema.Type.NULL) {
          return s.getTypes().get(1);
        } else if (s.getTypes().get(1).getType() == Schema.Type.NULL) {
          return s.getTypes().get(0);
        }
      }
      throw new IOException("Complex unions are not supported.");
    }
    return s;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy