Writing xml schema

Writing xml schema for PAMGuard database with annotations as complex
types
This commit is contained in:
Douglas Gillespie 2022-11-08 16:42:57 +00:00
parent fcdb64e467
commit 61dd6ef4d1
7 changed files with 167 additions and 35 deletions

View File

@ -17,7 +17,7 @@ public class SnrSqlAddon implements SQLLoggingAddon {
public SnrSqlAddon(SNRAnnotationType snrAnnotationType) { public SnrSqlAddon(SNRAnnotationType snrAnnotationType) {
super(); super();
this.snrAnnotationType = snrAnnotationType; this.snrAnnotationType = snrAnnotationType;
snr = new PamTableItem("snr", Types.DOUBLE); snr = new PamTableItem("snr", Types.DOUBLE, "Signal to Noise ratio");
} }
@Override @Override

View File

@ -18,10 +18,10 @@ public class SPLSqlAddon implements SQLLoggingAddon {
public SPLSqlAddon(SPLAnnotationType splAnnotationType) { public SPLSqlAddon(SPLAnnotationType splAnnotationType) {
super(); super();
this.splAnnotationType = splAnnotationType; this.splAnnotationType = splAnnotationType;
rms = new PamTableItem("RMS", Types.DOUBLE); rms = new PamTableItem("RMS", Types.DOUBLE, "RMS Level");
zeroPeak = new PamTableItem("ZeroPeak", Types.DOUBLE); zeroPeak = new PamTableItem("ZeroPeak", Types.DOUBLE, "Zero to Peak Level");
peakPeak = new PamTableItem("PeakPeak", Types.DOUBLE); peakPeak = new PamTableItem("PeakPeak", Types.DOUBLE, "Peak to Peak Level");
sel = new PamTableItem("SEL", Types.DOUBLE); sel = new PamTableItem("SEL", Types.DOUBLE, "Sound Exposure Level");
} }
@Override @Override

View File

@ -20,7 +20,7 @@ public class StringSQLLogging implements SQLLoggingAddon {
super(); super();
this.stringAnnotationType = stringAnnotationType; this.stringAnnotationType = stringAnnotationType;
notes = new PamTableItem(stringAnnotationType.getAnnotationName(), notes = new PamTableItem(stringAnnotationType.getAnnotationName(),
Types.CHAR, stringAnnotationType.getMaxLength()); Types.CHAR, stringAnnotationType.getMaxLength(), "Notes");
} }
@Override @Override

View File

@ -21,16 +21,16 @@ public class BearingAnnotationSQL implements SQLLoggingAddon {
public BearingAnnotationSQL(BearingAnnotationType bearingAnnotationType) { public BearingAnnotationSQL(BearingAnnotationType bearingAnnotationType) {
super(); super();
this.bearingAnnotationType = bearingAnnotationType; this.bearingAnnotationType = bearingAnnotationType;
algoName = new PamTableItem("BearingAlgorithm", Types.CHAR, 30); algoName = new PamTableItem("BearingAlgorithm", Types.CHAR, 30, "Algorithm Name");
angle[0] = new PamTableItem("BearingAngle1", Types.REAL); angle[0] = new PamTableItem("BearingAngle1", Types.REAL, "Horizontal angle (radians)");
angle[1] = new PamTableItem("BearingAngle2", Types.REAL); angle[1] = new PamTableItem("BearingAngle2", Types.REAL, "Vertical angle (radians)");
angleError[0] = new PamTableItem("BearingError1", Types.REAL); angleError[0] = new PamTableItem("BearingError1", Types.REAL, "Horizontal angle error (radians)");
angleError[1] = new PamTableItem("BearingError2", Types.REAL); angleError[1] = new PamTableItem("BearingError2", Types.REAL, "Vertical angle error (radians)");
refAngles[0] = new PamTableItem("ReferenceAngle1", Types.REAL); refAngles[0] = new PamTableItem("ReferenceAngle1", Types.REAL, "Horizontal angle reference");
refAngles[1] = new PamTableItem("ReferenceAngle2", Types.REAL); refAngles[1] = new PamTableItem("ReferenceAngle2", Types.REAL, "Vertical angle reference");
bfPhones = new PamTableItem("BearingPhones", Types.INTEGER); bfPhones = new PamTableItem("BearingPhones", Types.INTEGER, "Used hydrophones bitmap");
bfArrayType = new PamTableItem("BearingArrayType", Types.SMALLINT); bfArrayType = new PamTableItem("BearingArrayType", Types.SMALLINT, "Array Type 1=point;2=line;3=plane;4=volume");
bfContents = new PamTableItem("BearingLocContents", Types.INTEGER); bfContents = new PamTableItem("BearingLocContents", Types.INTEGER, "Bitmap of localisation information types");
} }
@Override @Override

View File

@ -3,6 +3,8 @@ package generalDatabase;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.sql.Types; import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
@ -20,10 +22,24 @@ import PamguardMVC.PamDataBlock;
*/ */
public class DBSchemaWriter { public class DBSchemaWriter {
private PamTableDefinition baseTableDefinition = new PamTableDefinition("PamTableDefinition");
private PamTableDefinition parentTable;
public DBSchemaWriter() { public DBSchemaWriter() {
// TODO Auto-generated constructor stub // TODO Auto-generated constructor stub
} }
public boolean writeStandardTableDef(File outputFolder, PamDataBlock dataBlock) {
PamTableDefinition aTable = new PamTableDefinition("PamStandardTable");
parentTable = null;
exportDatabaseSchema(outputFolder, dataBlock, null, aTable);
parentTable = aTable;
return true;
}
public boolean writeSchema(File outputFolder, PamDataBlock dataBlock) { public boolean writeSchema(File outputFolder, PamDataBlock dataBlock) {
if (dataBlock == null) { if (dataBlock == null) {
return false; return false;
@ -33,21 +49,105 @@ public class DBSchemaWriter {
return false; return false;
} }
PamTableDefinition tableDef = logging.getTableDefinition(); PamTableDefinition tableDef = logging.getTableDefinition();
exportDatabaseSchema(outputFolder, dataBlock, tableDef); tableDef = logging.getBaseTableDefinition();
if (tableDef instanceof PamTableDefinition) {
writeStandardTableDef(outputFolder, dataBlock);
}
else {
parentTable = null;
}
exportDatabaseSchema(outputFolder, dataBlock, logging, tableDef);
return true; return true;
} }
private void exportDatabaseSchema(File outputFolder, PamDataBlock dataBlock, PamTableDefinition tableDef) { private void exportDatabaseSchema(File outputFolder, PamDataBlock dataBlock, SQLLogging logging, PamTableDefinition tableDef) {
/**
* write a parent item, e.g. if tableDef is a sub class of PamTableDefinition
*/
// String parentName = writeParentTableSchema(outputFolder, dataBlock, tableDef);
String tableName = tableDef.getTableName(); String tableName = tableDef.getTableName();
File outputFile = new File(outputFolder, tableName+".xsd");
Document doc = PamUtils.XMLUtils.createBlankDoc(); Document doc = PamUtils.XMLUtils.createBlankDoc();
Element el = doc.createElement("xs:schema"); Element schemaEl = doc.createElement("xs:schema");
el.setAttribute("xmlns:xs","http://www.w3.org/2001/XMLSchema"); schemaEl.setAttribute("xmlns:xs","http://www.w3.org/2001/XMLSchema");
el.setAttribute("targetNamespace", "http://tethys.sdsu.edu/schema/1.0"); schemaEl.setAttribute("targetNamespace", "http://tethys.sdsu.edu/schema/1.0");
doc.appendChild(el); doc.appendChild(schemaEl);
for (PamTableItem tableItem : tableDef.pamTableItems) { if (parentTable != null) {
Element parentEl = doc.createElement("xs:include");
parentEl.setAttribute("schemaLocation", parentTable.getTableName()+".xsd");
schemaEl.appendChild(parentEl);
}
fillItemElement(doc, schemaEl, tableDef.pamTableItems);
if (logging != null) {
ArrayList<SQLLoggingAddon> annots = logging.getLoggingAddOns();
if (annots != null) {
for (SQLLoggingAddon addon : annots) {
Element compEl = addAddonElement(doc, schemaEl, addon);
if (compEl != null) {
schemaEl.appendChild(compEl);
}
}
}
}
try {
File outputFile = new File(outputFolder, tableName+".xsd");
XMLUtils.writeToFile(doc, outputFile);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Add a complex element for a SQLLogging addon.
* @param doc
* @param schemaEl
* @param addon
*/
private Element addAddonElement(Document doc, Element schemaEl, SQLLoggingAddon addon) {
Element compEl = doc.createElement("xs:complexType");
Element oEl = doc.createElement("xs:element");
oEl.setAttribute("name", addon.getName());
Element seqEl = doc.createElement("xs:sequence");
PamTableDefinition mtTable = new PamTableDefinition(addon.getName());
addon.addTableItems(mtTable);
// this is a mess ! must avoid the standard items.
fillItemElement(doc, seqEl, mtTable.pamTableItems);
compEl.appendChild(seqEl);
oEl.appendChild(compEl);
return oEl;
}
/**
* Fills information on items in a list into the given element
* This may be the schema element or may be a complex element.
* @param doc
* @param schemaEl
* @param tableItems
*/
private void fillItemElement(Document doc, Element schemaEl, List<PamTableItem> tableItems) {
for (PamTableItem tableItem : tableItems) {
if (shouldSkip(tableItem, parentTable)) {
// element is included in parent table, so skip it.
continue;
}
Element itemEl = doc.createElement("xs:element"); Element itemEl = doc.createElement("xs:element");
itemEl.setAttribute("name", tableItem.getName()); itemEl.setAttribute("name", tableItem.getName());
itemEl.setAttribute("type", sqlTypeToString(tableItem.getSqlType(), tableItem.getLength())); itemEl.setAttribute("type", sqlTypeToString(tableItem.getSqlType(), tableItem.getLength()));
@ -59,16 +159,41 @@ public class DBSchemaWriter {
docEl.setTextContent(documentation); docEl.setTextContent(documentation);
annotation.appendChild(docEl); annotation.appendChild(docEl);
} }
el.appendChild(itemEl); schemaEl.appendChild(itemEl);
}
}
private boolean shouldSkip(PamTableItem tableItem, PamTableDefinition parentTable) {
if (parentTable == null) {
return false;
}
if (parentTable.findTableItem(tableItem.getName()) != null) {
return true;
}
return false;
} }
try { // private String writeParentTableSchema(File outputFolder, PamDataBlock dataBlock, PamTableDefinition tableDef) {
XMLUtils.writeToFile(doc, outputFile); // /**
} catch (IOException e) { // * Write a schema of everything that is in the parent table, then include a reference to that
e.printStackTrace(); // * schema. To do this, we need to a) establish if there is a table def parent, then go through
} // * all the fields in THIS tableDef, see if the field exists in the parent. IF it exists in the
} // * parent, write it in the parent doc, if it's only in this, write it in this doc. So far so good, but
// * we need to also make this recursive so it can build layer on layer ?
// * Reaslistically, this is all too complicated ! Just write out the schema for the PamTableDefinition
// * at the start of everything, and skip those fields in everything else. This will be a bit ad-hoc, but
// * it will otherwise be a nightmare since we don't know which table items are in which class at this point.
// */
// Class tableClass = tableDef.getClass();
// Class parentClass = tableClass.getSuperclass();
// if (parentClass.isAssignableFrom(tableClass) == false) {
// return null;
// }
//
//
// return null;
// }
private String sqlTypeToString(int sqlType, int length) { private String sqlTypeToString(int sqlType, int length) {
switch (sqlType) { switch (sqlType) {

View File

@ -43,7 +43,7 @@ public class EmptyTableDefinition implements Cloneable {
this.tableName = tableName; this.tableName = tableName;
this.setUpdatePolicy(updatePolicy); this.setUpdatePolicy(updatePolicy);
pamTableItems = new ArrayList<PamTableItem>(); pamTableItems = new ArrayList<PamTableItem>();
pamTableItems.add(indexItem = new PamTableItem(indexColName, Types.INTEGER)); pamTableItems.add(indexItem = new PamTableItem(indexColName, Types.INTEGER, "Primary key"));
indexItem.setPrimaryKey(true); indexItem.setPrimaryKey(true);
indexItem.setCounter(true); indexItem.setCounter(true);
} }

View File

@ -2183,5 +2183,12 @@ public abstract class SQLLogging {
return subDetection.getSuperDetection(superDataBlock); return subDetection.getSuperDetection(superDataBlock);
} }
/**
* @return the loggingAddOns
*/
public ArrayList<SQLLoggingAddon> getLoggingAddOns() {
return loggingAddOns;
}
} }