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

cdc.util.rdb.tools.dump.DatabaseConfigIo Maven / Gradle / Ivy

There is a newer version: 0.9.0
Show newest version
package cdc.util.rdb.tools.dump;

import java.io.File;
import java.io.IOException;
import java.io.PrintStream;

import cdc.util.converters.Converter;
import cdc.util.converters.ConvertersIo;
import cdc.util.data.Element;
import cdc.util.data.util.AbstractResourceLoader;
import cdc.util.function.Iterables;
import cdc.util.lang.FailureReaction;
import cdc.util.lang.IntMasks;
import cdc.util.xml.XmlWriter;

public final class DatabaseConfigIo {
    private static final String COLUMN = "column";
    private static final String CONVERTER = "converter";
    private static final String DATABASE = "database";
    private static final String EXTERNAL = "external";
    private static final String INTERNAL = "internal";
    private static final String NAMESPACE = "https://www.gitlab.com/cdc-java";
    private static final String NOTE = "note";
    private static final String ORDER = "order";
    private static final String KEEP = "keep";
    private static final String SCHEMA = "schema";
    private static final String SORTING = "sorting";
    private static final String TABLE = "table";

    private DatabaseConfigIo() {
    }

    public static class Printer {
        private final XmlWriter writer;
        /** Mask of enabled features. */
        private int features = 0;

        public enum Feature {
            DEBUG
        }

        Printer(XmlWriter writer) {
            this.writer = writer;
            this.writer.setEnabled(XmlWriter.Feature.PRETTY_PRINT, true);
            this.writer.setTabSize(2);
        }

        public final Printer setEnabled(Feature feature,
                                        boolean enabled) {
            features = IntMasks.setEnabled(features, feature, enabled);
            return this;
        }

        public final Printer setEnabled(Feature... features) {
            if (features != null) {
                for (final Feature feature : features) {
                    setEnabled(feature, true);
                }
            }
            return this;
        }

        public final boolean isEnabled(Feature feature) {
            return IntMasks.isEnabled(features, feature);
        }

        public static void print(DatabaseConfig database,
                                 XmlWriter writer,
                                 Feature... features) throws IOException {
            final Printer printer = new Printer(writer);
            printer.setEnabled(features);
            printer.print(database);
        }

        public static void print(DatabaseConfig database,
                                 PrintStream out,
                                 Feature... features) throws IOException {
            print(database, new XmlWriter(out), features);
        }

        public static void print(DatabaseConfig database,
                                 File file,
                                 Feature... features) throws IOException {
            print(database, new XmlWriter(file), features);
        }

        void print(DatabaseConfig database) throws IOException {
            writer.beginDocument();
            writer.beginElement(DATABASE);
            writer.addAttribute(XmlWriter.XMLNS, NAMESPACE);
            writer.addAttribute(XmlWriter.XMLNS_XSI, XmlWriter.XML_SCHEMA_INSTANCE);
            writer.addAttribute(XmlWriter.XSI_SCHEMA_LOCATION, "https://www.gitlab.com/cdc-java https://www.gitlab.com/cdc-java/database-config.xsd");
            printConfig(database);

            for (final String schemaName : Iterables.toSortedList(database.getSchemaNames())) {
                final SchemaConfig schemaConfig = database.getSchemaConfig(schemaName);
                printSchema(schemaConfig);
            }

            writer.endElement();
            writer.endDocument();
            writer.close();
        }

        private void printConfig(AbstractConfig config) throws IOException {
            if (config.getParent() == null) {
                writer.addAttribute(KEEP, config.getProcessing() == Processing.KEEP);
            } else {
                if (config.getProcessing() != Processing.INHERIT) {
                    writer.addAttribute(KEEP, config.getProcessing() == Processing.KEEP);
                }
            }
            if (isEnabled(Feature.DEBUG)) {
                writer.addAttribute("processing", config.getProcessing().name());
                writer.addAttribute("inherited-processing", config.getInheritedProcessing().name());
                writer.addAttribute("effective-processing", config.getEffectiveProcessing().name());
            }
            if (config.getNote() != null && !config.getNote().isEmpty()) {
                writer.beginElement(NOTE);
                writer.addElementContent(config.getNote());
                writer.endElement();
            }
        }

        private void printNamedConfig(AbstractNamedConfig config) throws IOException {
            writer.addAttribute(INTERNAL, config.getInternal());
            writer.addAttribute(EXTERNAL, config.getExternal());
            printConfig(config);
        }

        private void printSchema(SchemaConfig schema) throws IOException {
            writer.beginElement(SCHEMA);
            printNamedConfig(schema);
            for (final String tableName : Iterables.toSortedList(schema.getTableNames())) {
                final TableConfig tableConfig = schema.getTableConfig(tableName);
                printTable(tableConfig);
            }
            writer.endElement();
        }

        private void printTable(TableConfig table) throws IOException {
            writer.beginElement(TABLE);
            printNamedConfig(table);
            for (final ColumnSorting sorting : table.getColumnsSorting()) {
                printSorting(sorting);
            }

            for (final String columnName : Iterables.toSortedList(table.getColumnsNames())) {
                final ColumnConfig columnConfig = table.getColumnConfig(columnName);
                printColumn(columnConfig);
            }
            writer.endElement();
        }

        private void printSorting(ColumnSorting sorting) throws IOException {
            writer.beginElement(SORTING);
            writer.addAttribute(INTERNAL, sorting.getInternal());
            if (sorting.getOrder() == Order.DESCENDING) {
                writer.addAttribute(ORDER, sorting.getOrder().name());
            }
            writer.endElement();
        }

        private void printColumn(ColumnConfig column) throws IOException {
            writer.beginElement(COLUMN);
            printNamedConfig(column);
            printConverter(column.getConverter());
            writer.endElement();
        }

        private void printConverter(Converter converter) throws IOException {
            if (converter != null) {
                writer.beginElement(CONVERTER);
                ConvertersIo.write(writer, converter);
                writer.endElement();
            }
        }
    }

    public static final class Loader extends AbstractResourceLoader {
        private final ConvertersIo.Loader converterLoader;

        public Loader(FailureReaction reaction) {
            super(reaction);
            converterLoader = new ConvertersIo.Loader(reaction);
        }

        @Override
        public DatabaseConfig loadRoot(Element root) {
            final DatabaseConfig database = new DatabaseConfig();

            if (DATABASE.equals(root.getName())) {
                loadConfig(database, root);
                for (final Element child : root.getChildren(Element.class)) {
                    if (SCHEMA.equals(child.getName())) {
                        loadSchema(database, child);
                    } else if (NOTE.equals(child.getName())) {
                        // Ignore
                    } else {
                        unexpectedElement(child);
                    }
                }
            } else {
                unexpectedElement(root);
            }
            return database;
        }

        private static void loadConfig(AbstractConfig config,
                                       Element element) {
            if (config.getParent() == null) {
                final boolean keep = element.getAttributeAsBoolean(KEEP, true);
                config.setProcessing(keep ? Processing.KEEP : Processing.IGNORE);
            } else {
                final Boolean keep = element.getAttributeAsOptionalBoolean(KEEP, null);
                if (keep == null) {
                    config.setProcessing(Processing.INHERIT);
                } else {
                    config.setProcessing(keep ? Processing.KEEP : Processing.IGNORE);
                }
            }
            for (final Element child : element.getChildren(Element.class)) {
                if (NOTE.equals(child.getName())) {
                    config.setNote(child.getText(null));
                }
            }
        }

        private static void loadNamedConfig(AbstractNamedConfig config,
                                            Element element) {
            final String external = element.getAttributeValue(EXTERNAL, null);
            config.setExternal(external);
            loadConfig(config, element);
        }

        private void loadSchema(DatabaseConfig database,
                                Element element) {
            final String internal = element.getAttributeValue(INTERNAL, null);
            final SchemaConfig schemaConfig = database.getOrCreateSchemaConfig(internal);
            loadNamedConfig(schemaConfig, element);

            for (final Element child : element.getChildren(Element.class)) {
                if (TABLE.equals(child.getName())) {
                    loadTable(schemaConfig, child);
                } else if (NOTE.equals(child.getName())) {
                    // Ignore
                } else {
                    unexpectedElement(child);
                }
            }
        }

        private void loadTable(SchemaConfig schema,
                               Element element) {
            final String internal = element.getAttributeValue(INTERNAL, null);
            final TableConfig tableConfig = schema.getOrCreateTableConfig(internal);
            loadNamedConfig(tableConfig, element);
            for (final Element child : element.getChildren(Element.class)) {
                if (COLUMN.equals(child.getName())) {
                    loadColumn(tableConfig, child);
                } else if (NOTE.equals(child.getName())) {
                    // Ignore
                } else if (SORTING.equals(child.getName())) {
                    loadSorting(tableConfig, child);
                } else {
                    unexpectedElement(child);
                }
            }
        }

        private void loadColumn(TableConfig table,
                                Element element) {
            final String internal = element.getAttributeValue(INTERNAL, null);
            final ColumnConfig columnConfig = table.getOrCreateColumnConfig(internal);
            loadNamedConfig(columnConfig, element);
            for (final Element child : element.getChildren(Element.class)) {
                if (CONVERTER.equals(child.getName())) {
                    loadConverter(columnConfig, child);
                } else if (NOTE.equals(child.getName())) {
                    // Ignore
                } else {
                    unexpectedElement(child);
                }
            }
        }

        private static void loadSorting(TableConfig table,
                                        Element element) {
            final String name = element.getAttributeValue(INTERNAL, null);
            final Order order = element.getAttributeAsEnum(ORDER, Order.class, Order.ASCENDING);
            final ColumnSorting sorting = new ColumnSorting(name);
            sorting.setOrder(order);
            table.addColumnSorting(sorting);
        }

        private void loadConverter(ColumnConfig column,
                                   Element element) {
            if (element.getChildrenCount(Element.class) == 1) {
                final Converter converter = converterLoader.loadConverter(element.getChildAt(Element.class, 0));
                column.setConverter(converter);
            } else {
                onError("Exactly one child expected under " + element);
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy