cdc.util.rdb.tools.dump.DatabaseConfigIo Maven / Gradle / Ivy
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