// Path: src/main/java/com/at/avro/config/AvroConfig.java
// public class AvroConfig {
// 
//     private boolean representEnumsAsStrings = false;
//     private boolean nullableTrueByDefault = false;
//     private boolean allFieldsDefaultNull = false;
//     private boolean useSqlCommentsAsDoc = false;
// 
//     private Class<?> decimalTypeClass = BigDecimal.class;
//     private Class<?> dateTypeClass = Date.class;
// 
//     private final String namespace;
// 
//     private Function<String, String> schemaNameMapper = tableName -> tableName;
//     private Function<String, String> fieldNameMapper = columnName -> columnName;
//     private Function<String, String> unknownTypeResolver = dbType -> { throw new IllegalArgumentException("unknown data type: " + dbType); };
//     private BiConsumer<AvroSchema, Table> avroSchemaPostProcessor = (schema, table) -> {};
// 
//     public AvroConfig(String namespace) {
//         this.namespace = namespace;
//     }
// 
//     /**
//      * Provide custom schema name resolver function which takes DB table name as an input.
//      * Table name is used by default.
//      */
//     public AvroConfig setSchemaNameMapper(Function<String, String> schemaNameMapper) {
//         this.schemaNameMapper = schemaNameMapper;
//         return this;
//     }
// 
//     public Function<String, String> getSchemaNameMapper() {
//         return schemaNameMapper;
//     }
// 
//     /**
//      * Provide custom field names resolver function which takes DB column name as an input.
//      * Column name is used by default.
//      */
//     public AvroConfig setFieldNameMapper(Function<String, String> fieldNameMapper) {
//         this.fieldNameMapper = fieldNameMapper;
//         return this;
//     }
// 
//     public Function<String, String> getFieldNameMapper() {
//         return fieldNameMapper;
//     }
// 
//     /**
//      * Resolve 'enum' type to 'string' instead of 'enum'.
//      */
//     public AvroConfig setRepresentEnumsAsStrings(boolean representEnumsAsStrings) {
//         this.representEnumsAsStrings = representEnumsAsStrings;
//         return this;
//     }
// 
//     public boolean representEnumsAsStrings() {
//         return representEnumsAsStrings;
//     }
// 
//     /**
//      * Set to true to make all fields default to null. DB column definition is used by default.
//      */
//     public AvroConfig setAllFieldsDefaultNull(boolean allFieldsDefaultNull) {
//         this.allFieldsDefaultNull = allFieldsDefaultNull;
//         return this;
//     }
// 
//     public boolean isAllFieldsDefaultNull() {
//         return allFieldsDefaultNull;
//     }
// 
//     public String getNamespace() {
//         return namespace;
//     }
// 
//     /**
//      * Set to true to make all fields nullable in avro schema. DB column definition is used by default.
//      */
//     public AvroConfig setNullableTrueByDefault(boolean nullableTrueByDefault) {
//         this.nullableTrueByDefault = nullableTrueByDefault;
//         return this;
//     }
// 
//     public boolean isNullableTrueByDefault() {
//         return nullableTrueByDefault;
//     }
// 
//     /**
//      * Sets a "java-class" property in this fields definition.
//      * This might be used by avro java code generator to use the class you want for dates.
//      */
//     public AvroConfig setDateTypeClass(Class<?> dateTypeClass) {
//         this.dateTypeClass = dateTypeClass;
//         return this;
//     }
// 
//     public Class<?> getDateTypeClass() {
//         return dateTypeClass;
//     }
// 
//     /**
//      * Sets a "java-class" property in this fields definition.
//      * This might be used by avro java code generator to use the class you want for decimals.
//      */
//     public AvroConfig setDecimalTypeClass(Class<?> decimalTypeClass) {
//         this.decimalTypeClass = decimalTypeClass;
//         return this;
//     }
// 
//     public Class<?> getDecimalTypeClass() {
//         return decimalTypeClass;
//     }
//     
//     /**
//      * Provide mapper for unknown db types. Throws IllegalArgumentException by default.
//      * For example, if you want to default all unknown types to string:
//      * <code>
//      *     avroConfig.setUnknownTypeResolver(type -> "string")
//      * </code>
//      * IllegalArgumentException is thrown by default.
//      **/
//     public AvroConfig setUnknownTypeResolver(Function<String, String> unknownTypeResolver) {
//         this.unknownTypeResolver = unknownTypeResolver;
//         return this;
//     }
//     
//     public Function<String, String> getUnknownTypeResolver() {
//         return unknownTypeResolver;
//     }
//     
//     /**
//      * Set a callback that will be called after avro model was built.
//      * Schema model is ready by this point, but you can still modify it by adding custom properties.
//      */
//     public AvroConfig setAvroSchemaPostProcessor(BiConsumer<AvroSchema, Table> avroSchemaPostProcessor) {
//         this.avroSchemaPostProcessor = avroSchemaPostProcessor;
//         return this;
//     }
//     
//     public BiConsumer<AvroSchema, Table> getAvroSchemaPostProcessor() {
//         return avroSchemaPostProcessor;
//     }
//     
//     /**
//      * Set to true to use SQL comments at table and field level as optional avro doc fields.
//      */
//     public AvroConfig setUseSqlCommentsAsDoc(boolean useSqlCommentsAsDoc) {
//         this.useSqlCommentsAsDoc = useSqlCommentsAsDoc;
//         return this;
//     }
//     
//     public boolean isUseSqlCommentsAsDoc() {
//         return useSqlCommentsAsDoc;
//     }
//     
// }


import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import com.at.avro.config.AvroConfig;
import org.apache.commons.lang3.StringUtils;
import schemacrawler.schema.Column;
import schemacrawler.schema.Table;
package com.at.avro;




/**
 * @author artur@callfire.com
 */
public class AvroSchema {
    private final String name;
    private final String namespace;
    private final String doc;

    private List<AvroField> fields;

    private Map<String, String> customProperties = new LinkedHashMap<>();

// Path: src/main/java/com/at/avro/config/AvroConfig.java
// public class AvroConfig {
// 
//     private boolean representEnumsAsStrings = false;
//     private boolean nullableTrueByDefault = false;
//     private boolean allFieldsDefaultNull = false;
//     private boolean useSqlCommentsAsDoc = false;
// 
//     private Class<?> decimalTypeClass = BigDecimal.class;
//     private Class<?> dateTypeClass = Date.class;
// 
//     private final String namespace;
// 
//     private Function<String, String> schemaNameMapper = tableName -> tableName;
//     private Function<String, String> fieldNameMapper = columnName -> columnName;
//     private Function<String, String> unknownTypeResolver = dbType -> { throw new IllegalArgumentException("unknown data type: " + dbType); };
//     private BiConsumer<AvroSchema, Table> avroSchemaPostProcessor = (schema, table) -> {};
// 
//     public AvroConfig(String namespace) {
//         this.namespace = namespace;
//     }
// 
//     /**
//      * Provide custom schema name resolver function which takes DB table name as an input.
//      * Table name is used by default.
//      */
//     public AvroConfig setSchemaNameMapper(Function<String, String> schemaNameMapper) {
//         this.schemaNameMapper = schemaNameMapper;
//         return this;
//     }
// 
//     public Function<String, String> getSchemaNameMapper() {
//         return schemaNameMapper;
//     }
// 
//     /**
//      * Provide custom field names resolver function which takes DB column name as an input.
//      * Column name is used by default.
//      */
//     public AvroConfig setFieldNameMapper(Function<String, String> fieldNameMapper) {
//         this.fieldNameMapper = fieldNameMapper;
//         return this;
//     }
// 
//     public Function<String, String> getFieldNameMapper() {
//         return fieldNameMapper;
//     }
// 
//     /**
//      * Resolve 'enum' type to 'string' instead of 'enum'.
//      */
//     public AvroConfig setRepresentEnumsAsStrings(boolean representEnumsAsStrings) {
//         this.representEnumsAsStrings = representEnumsAsStrings;
//         return this;
//     }
// 
//     public boolean representEnumsAsStrings() {
//         return representEnumsAsStrings;
//     }
// 
//     /**
//      * Set to true to make all fields default to null. DB column definition is used by default.
//      */
//     public AvroConfig setAllFieldsDefaultNull(boolean allFieldsDefaultNull) {
//         this.allFieldsDefaultNull = allFieldsDefaultNull;
//         return this;
//     }
// 
//     public boolean isAllFieldsDefaultNull() {
//         return allFieldsDefaultNull;
//     }
// 
//     public String getNamespace() {
//         return namespace;
//     }
// 
//     /**
//      * Set to true to make all fields nullable in avro schema. DB column definition is used by default.
//      */
//     public AvroConfig setNullableTrueByDefault(boolean nullableTrueByDefault) {
//         this.nullableTrueByDefault = nullableTrueByDefault;
//         return this;
//     }
// 
//     public boolean isNullableTrueByDefault() {
//         return nullableTrueByDefault;
//     }
// 
//     /**
//      * Sets a "java-class" property in this fields definition.
//      * This might be used by avro java code generator to use the class you want for dates.
//      */
//     public AvroConfig setDateTypeClass(Class<?> dateTypeClass) {
//         this.dateTypeClass = dateTypeClass;
//         return this;
//     }
// 
//     public Class<?> getDateTypeClass() {
//         return dateTypeClass;
//     }
// 
//     /**
//      * Sets a "java-class" property in this fields definition.
//      * This might be used by avro java code generator to use the class you want for decimals.
//      */
//     public AvroConfig setDecimalTypeClass(Class<?> decimalTypeClass) {
//         this.decimalTypeClass = decimalTypeClass;
//         return this;
//     }
// 
//     public Class<?> getDecimalTypeClass() {
//         return decimalTypeClass;
//     }
//     
//     /**
//      * Provide mapper for unknown db types. Throws IllegalArgumentException by default.
//      * For example, if you want to default all unknown types to string:
//      * <code>
//      *     avroConfig.setUnknownTypeResolver(type -> "string")
//      * </code>
//      * IllegalArgumentException is thrown by default.
//      **/
//     public AvroConfig setUnknownTypeResolver(Function<String, String> unknownTypeResolver) {
//         this.unknownTypeResolver = unknownTypeResolver;
//         return this;
//     }
//     
//     public Function<String, String> getUnknownTypeResolver() {
//         return unknownTypeResolver;
//     }
//     
//     /**
//      * Set a callback that will be called after avro model was built.
//      * Schema model is ready by this point, but you can still modify it by adding custom properties.
//      */
//     public AvroConfig setAvroSchemaPostProcessor(BiConsumer<AvroSchema, Table> avroSchemaPostProcessor) {
//         this.avroSchemaPostProcessor = avroSchemaPostProcessor;
//         return this;
//     }
//     
//     public BiConsumer<AvroSchema, Table> getAvroSchemaPostProcessor() {
//         return avroSchemaPostProcessor;
//     }
//     
//     /**
//      * Set to true to use SQL comments at table and field level as optional avro doc fields.
//      */
//     public AvroConfig setUseSqlCommentsAsDoc(boolean useSqlCommentsAsDoc) {
//         this.useSqlCommentsAsDoc = useSqlCommentsAsDoc;
//         return this;
//     }
//     
//     public boolean isUseSqlCommentsAsDoc() {
//         return useSqlCommentsAsDoc;
//     }
//     
// }


// Path: src/main/java/com/at/avro/AvroSchema.java
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import com.at.avro.config.AvroConfig;
import org.apache.commons.lang3.StringUtils;
import schemacrawler.schema.Column;
import schemacrawler.schema.Table;

package com.at.avro;




/**
 * @author artur@callfire.com
 */
public class AvroSchema {
    private final String name;
    private final String namespace;
    private final String doc;

    private List<AvroField> fields;

    private Map<String, String> customProperties = new LinkedHashMap<>();

    public AvroSchema(Table table, AvroConfig avroConfig) {