SuperX-Kernmodul
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

154 lines
5.5 KiB

package de.superx.db.export;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.springframework.stereotype.Component;
/**
* Reads export group configuration from an XML file.
*
* Expected format:
* <pre>{@code
* <export-config>
* <group name="my_group" schema="staging">
* <table>table_one</table>
* <table>table_two</table>
* </group>
* </export-config>
* }</pre>
*/
@Component
public class ExportConfigReader {
public ExportConfig read(File configFile) throws JDOMException, IOException {
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(configFile);
return parse(doc);
}
public ExportConfig read(InputStream in) throws JDOMException, IOException {
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(in);
return parse(doc);
}
private ExportConfig parse(Document doc) {
Element root = doc.getRootElement();
List<ExportGroup> groups = new ArrayList<>();
for (Element groupEl : root.getChildren("group")) {
String name = groupEl.getAttributeValue("name");
if (name == null || name.isBlank()) {
throw new IllegalArgumentException("Export group must have a 'name' attribute");
}
String schema = groupEl.getAttributeValue("schema");
// Parse optional filter
String filterColumn = null;
String filterSource = null;
Element filterEl = groupEl.getChild("filter");
if (filterEl != null) {
filterColumn = filterEl.getAttributeValue("column");
if (filterColumn == null || filterColumn.isBlank()) {
throw new IllegalArgumentException(
"Filter in group '" + name + "' must have a 'column' attribute");
}
String sourceAttr = filterEl.getAttributeValue("source");
String valuesAttr = filterEl.getAttributeValue("values");
if (sourceAttr != null && !sourceAttr.isBlank()) {
filterSource = sourceAttr;
} else if (valuesAttr != null && !valuesAttr.isBlank()) {
filterSource = buildValuesSubquery(valuesAttr);
} else {
throw new IllegalArgumentException(
"Filter in group '" + name
+ "' must have a 'source' or 'values' attribute");
}
}
// Parse tables with optional per-table column, source, columns, and orderBy overrides
List<ExportTableConfig> tableConfigs = new ArrayList<>();
for (Element tableEl : groupEl.getChildren("table")) {
String tableName = tableEl.getTextTrim();
if (!tableName.isEmpty()) {
String colOverride = tableEl.getAttributeValue("column");
String sourceOverride = tableEl.getAttributeValue("source");
String columnsAttr = tableEl.getAttributeValue("columns");
String orderByAttr = tableEl.getAttributeValue("orderBy");
List<String> columnsList = null;
if (columnsAttr != null && !columnsAttr.isBlank()) {
columnsList = new ArrayList<>();
for (String col : columnsAttr.split(",")) {
String trimmed = col.trim();
if (!trimmed.isEmpty()) {
columnsList.add(trimmed);
}
}
}
tableConfigs.add(new ExportTableConfig(
tableName, colOverride, sourceOverride,
columnsList, orderByAttr));
}
}
if (tableConfigs.isEmpty()) {
throw new IllegalArgumentException("Export group '" + name + "' has no tables defined");
}
groups.add(new ExportGroup(name, schema, tableConfigs,
filterColumn, filterSource));
}
return new ExportConfig(groups);
}
/**
* Converts a comma-separated values string into a SQL VALUES clause.
* Each value is trimmed. Numeric values are kept as-is;
* non-numeric values are single-quoted.
*
* Example: "100, 200, 300" → "VALUES (100),(200),(300)"
* Example: "ZUL, FIN" → "VALUES ('ZUL'),('FIN')"
*/
private String buildValuesSubquery(String valuesAttr) {
String[] parts = valuesAttr.split(",");
StringBuilder sb = new StringBuilder("VALUES ");
for (int i = 0; i < parts.length; i++) {
String val = parts[i].trim();
if (val.isEmpty()) {
continue;
}
if (i > 0) {
sb.append(",");
}
if (isNumeric(val)) {
sb.append("(").append(val).append(")");
} else {
sb.append("('").append(val.replace("'", "''")).append("')");
}
}
return sb.toString();
}
private boolean isNumeric(String s) {
try {
Double.parseDouble(s);
return true;
} catch (NumberFormatException e) {
return false;
}
}
}