From 29230a5c5feb53bc5686ae7280ebae82c18058f0 Mon Sep 17 00:00:00 2001 From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com> Date: Wed, 23 Nov 2022 14:56:25 +0000 Subject: [PATCH 1/5] Better XML Improving XML data for each detector --- .../output/xml/PamguardXMLWriter.java | 7 ++++--- src/PamguardMVC/AcousticDataBlock.java | 10 +++++++++ src/PamguardMVC/DataBlock2D.java | 17 +++++++++++++++ src/PamguardMVC/PamDataBlock.java | 21 +++++++++++++++++++ src/fftManager/FFTDataBlock.java | 10 +++++++++ 5 files changed, 62 insertions(+), 3 deletions(-) diff --git a/src/PamController/settings/output/xml/PamguardXMLWriter.java b/src/PamController/settings/output/xml/PamguardXMLWriter.java index 1e9aae0f..7149b3fc 100644 --- a/src/PamController/settings/output/xml/PamguardXMLWriter.java +++ b/src/PamController/settings/output/xml/PamguardXMLWriter.java @@ -765,9 +765,10 @@ public class PamguardXMLWriter implements PamSettings { processData.setAttribute("Name", process.getProcessName()); PamDataBlock source = process.getParentDataBlock(); if (source != null) { - Element inputEl = doc.createElement("Input"); - inputEl.setAttribute("Name", source.getLongDataName()); - inputEl.setAttribute("Channels", String.format("0x%X", source.getChannelMap())); + Element inputEl = source.getDataBlockXML(doc); +// Element inputEl = doc.createElement("Input"); +// inputEl.setAttribute("Name", source.getLongDataName()); +// inputEl.setAttribute("Channels", String.format("0x%X", source.getChannelMap())); processData.appendChild(inputEl); } int nOut = process.getNumOutputDataBlocks(); diff --git a/src/PamguardMVC/AcousticDataBlock.java b/src/PamguardMVC/AcousticDataBlock.java index ec7477c1..f7fb5c8e 100644 --- a/src/PamguardMVC/AcousticDataBlock.java +++ b/src/PamguardMVC/AcousticDataBlock.java @@ -1,5 +1,8 @@ package PamguardMVC; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + import PamController.PamControllerInterface; import PamguardMVC.nanotime.NanosFromSamples; @@ -90,5 +93,12 @@ abstract public class AcousticDataBlock extends PamD return parentSourceData; } + @Override + public Element getDataBlockXML(Document doc) { + Element el = super.getDataBlockXML(doc); + el.setAttribute("SampleRate", String.format("%3.1f", getSampleRate())); + return el; + } + } diff --git a/src/PamguardMVC/DataBlock2D.java b/src/PamguardMVC/DataBlock2D.java index beae1e15..89eb0ec9 100644 --- a/src/PamguardMVC/DataBlock2D.java +++ b/src/PamguardMVC/DataBlock2D.java @@ -1,5 +1,8 @@ package PamguardMVC; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + import dataPlotsFX.data.DataTypeInfo; abstract public class DataBlock2D extends AcousticDataBlock { @@ -39,4 +42,18 @@ abstract public class DataBlock2D extends AcousticDat * @return data type information. */ abstract public DataTypeInfo getScaleInfo(); + + public Element getDataBlockXML(Document doc) { + Element el = super.getDataBlockXML(doc); + DataTypeInfo dti = getScaleInfo(); + if (dti != null) { + if (dti.dataType != null) { + el.setAttribute("DataType", dti.dataType.toString()); + } + if (dti.dataUnits != null) { + el.setAttribute("DataUnits", dti.dataUnits.toString()); + } + } + return el; + } } diff --git a/src/PamguardMVC/PamDataBlock.java b/src/PamguardMVC/PamDataBlock.java index 2b987ffa..b6056e9c 100644 --- a/src/PamguardMVC/PamDataBlock.java +++ b/src/PamguardMVC/PamDataBlock.java @@ -44,6 +44,8 @@ import javax.swing.Timer; import javax.swing.border.EmptyBorder; import org.springframework.core.GenericTypeResolver; +import org.w3c.dom.Document; +import org.w3c.dom.Element; import Acquisition.AcquisitionControl; import Acquisition.AcquisitionProcess; @@ -4199,4 +4201,23 @@ public class PamDataBlock extends PamObservable { public void setBackgroundManager(BackgroundManager backgroundManager) { this.backgroundManager = backgroundManager; } + + /** + * Get a brief summary of datablock to include in XML descriptions. + * Basic output is very simple. Expect other datablock to extend this by + * adding additional attributes. + * @param doc + * @return XML element with description of data. + */ + public Element getDataBlockXML(Document doc) { + Element inputEl = doc.createElement("Input"); + if (getParentProcess() != null && getParentProcess().getPamControlledUnit() != null) { + PamControlledUnit pcu = getParentProcess().getPamControlledUnit(); + inputEl.setAttribute("ModuleType", pcu.getUnitType()); + inputEl.setAttribute("ModuleName", pcu.getUnitName()); + } + inputEl.setAttribute("Name", getLongDataName()); + inputEl.setAttribute("Channels", String.format("0x%X", getChannelMap())); + return inputEl; + } } diff --git a/src/fftManager/FFTDataBlock.java b/src/fftManager/FFTDataBlock.java index db04f8d6..3bf0b7b1 100644 --- a/src/fftManager/FFTDataBlock.java +++ b/src/fftManager/FFTDataBlock.java @@ -4,6 +4,9 @@ import java.util.List; import java.util.ListIterator; import java.util.Vector; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + import PamView.GeneralProjector.ParameterType; import PamView.GeneralProjector.ParameterUnits; import PamguardMVC.DataBlock2D; @@ -186,6 +189,13 @@ public class FFTDataBlock extends DataBlock2D { public DataTypeInfo getScaleInfo() { return dataTypeInfo; } + @Override + public Element getDataBlockXML(Document doc) { + Element el = super.getDataBlockXML(doc); + el.setAttribute("FFTLength", String.format("%d", getFftLength())); + el.setAttribute("FFTHop", String.format("%d", getFftHop())); + return el; + } From 48716cb36662bf037268bd39d6cd6aa9502f823d Mon Sep 17 00:00:00 2001 From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com> Date: Mon, 12 Dec 2022 17:04:20 +0000 Subject: [PATCH 2/5] XML Settings Added a new log of XML settings / Effort for each module to the database. Had to make a lot of changes so that the base table in SQLLogging is of type EmptyTableDefinition, not PamTableDefinition. Needs a lot of testing and may break plugins using logging features. --- src/Acquisition/FolderInputSystem.java | 2 +- src/GPS/GpsLogger.java | 3 +- src/IshmaelDetector/IshLogger.java | 5 +- src/IshmaelLocator/IshLocSqlLogging.java | 5 +- src/Map/GebcoMapFile.java | 11 +- src/PamController/PamController.java | 24 ++++ src/PamController/PamSettingsSource.java | 8 ++ .../output/xml/PamguardXMLWriter.java | 28 +++- src/RightWhaleEdgeDetector/RWESQLLogging.java | 3 +- src/analogarraysensor/ArraySensorLogging.java | 3 +- src/annotation/calcs/snr/SnrSqlAddon.java | 7 +- src/annotation/calcs/spl/SPLSqlAddon.java | 7 +- src/annotation/calcs/wav/WavSqlAddon.java | 7 +- .../handler/OneStopAnnotationHandler.java | 3 +- .../targetmotion/TMAnnotationLogging.java | 3 +- src/annotation/string/StringSQLLogging.java | 7 +- .../timestamp/TimestampSQLLogging.java | 7 +- .../userforms/UserFormSQLAddon.java | 7 +- .../annotation/BFAnnotationLogging.java | 7 +- .../annotation/BearingAnnotationSQL.java | 7 +- .../BinarySettingsStorage.java | 6 + src/binaryFileStorage/BinaryStore.java | 6 + src/binaryFileStorage/BinaryStoreProcess.java | 3 +- .../annotation/ClickAnnotationSQL.java | 7 +- .../TrackedClickGroupLogging.java | 4 +- .../dataSelector/ClickTrainDataSelector2.java | 2 +- .../offlineFuncs/DatabaseChecks.java | 7 +- .../offlineFuncs/OfflineClickLogging.java | 5 +- .../rcImport/RainbowDatabseConverter.java | 4 +- .../trackedGroups/TrackedGroupSqlLogging.java | 2 +- src/generalDatabase/DBControl.java | 8 +- src/generalDatabase/DBProcess.java | 15 ++- src/generalDatabase/DBSchemaWriter.java | 4 +- src/generalDatabase/DbSpecial.java | 2 +- src/generalDatabase/EmptyTableDefinition.java | 11 +- src/generalDatabase/LogSettings.java | 5 +- src/generalDatabase/LogXMLDataUnit.java | 75 +++++++++++ src/generalDatabase/LogXMLSettings.java | 123 ++++++++++++++++++ src/generalDatabase/PamTableDefinition.java | 9 +- src/generalDatabase/PamTableItem.java | 2 +- src/generalDatabase/SQLLogging.java | 84 ++++++------ src/generalDatabase/SQLLoggingAddon.java | 6 +- .../XMLSettingsTableDefinition.java | 94 +++++++++++++ src/gpl/io/GPLLogging.java | 3 +- src/loc3d_Thode/TowedArray3DSQLLogging.java | 8 +- .../annotation/MatchedClickAnnotationSQL.java | 7 +- src/nidaqdev/networkdaq/NIDaqLogging.java | 7 +- .../logging/DLAnnotationSQL.java | 7 +- .../TargetMotionSQLLogging.java | 13 +- src/whistleDetector/WhistleLogger.java | 3 +- 50 files changed, 554 insertions(+), 132 deletions(-) create mode 100644 src/generalDatabase/LogXMLDataUnit.java create mode 100644 src/generalDatabase/LogXMLSettings.java create mode 100644 src/generalDatabase/XMLSettingsTableDefinition.java diff --git a/src/Acquisition/FolderInputSystem.java b/src/Acquisition/FolderInputSystem.java index 92ee94d7..0314a7c2 100644 --- a/src/Acquisition/FolderInputSystem.java +++ b/src/Acquisition/FolderInputSystem.java @@ -665,7 +665,7 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings{ if (currentFile > 0 && currentFile >= allFiles.size()) { fileListComplete(); } -// System.out.println("FolderinputSytem: daqHasEnded"); + System.out.println("FolderinputSytem: daqHasEnded"); } private void setFolderProgress() { diff --git a/src/GPS/GpsLogger.java b/src/GPS/GpsLogger.java index b02c32e6..f0f990c8 100644 --- a/src/GPS/GpsLogger.java +++ b/src/GPS/GpsLogger.java @@ -295,7 +295,8 @@ public class GpsLogger extends SQLLogging { * time from the UTC column which is NOT the GpsData time which was the real GPS time. */ int gpsIntTimeVal = gpsTime.getIntegerValue(); - Object ts = getTableDefinition().getTimeStampItem().getValue(); + PamTableDefinition pamTableDef = (PamTableDefinition) getTableDefinition(); + Object ts = pamTableDef.getTimeStampItem().getValue(); long gpsDate = sqlTypes.millisFromTimeStamp(ts); if (gpsDate%1000 == 0) { // some databases may have stored the milliseconds, in which diff --git a/src/IshmaelDetector/IshLogger.java b/src/IshmaelDetector/IshLogger.java index c9abdcfe..6bd47109 100644 --- a/src/IshmaelDetector/IshLogger.java +++ b/src/IshmaelDetector/IshLogger.java @@ -8,14 +8,13 @@ import java.sql.Types; import PamguardMVC.PamDataBlock; import PamguardMVC.PamDataUnit; - +import generalDatabase.EmptyTableDefinition; //import pamDatabase.SQLLogging; //import PamguardMVC.RecyclingDataBlock; import generalDatabase.PamDetectionLogging; public class IshLogger extends PamDetectionLogging { IshDetControl ishDetControl; - PamTableDefinition tableDefinition; PamTableItem systemDate, durationSecs, secSinceStart, peakHeight; // Peak is more important than start time for matched filter & spectrogram correlation PamTableItem peakSample, peakDelaySecs; @@ -25,7 +24,7 @@ public class IshLogger extends PamDetectionLogging { super(pamDataBlock, UPDATE_POLICY_WRITENEW); this.ishDetControl = ishDetControl; - tableDefinition = getTableDefinition(); + EmptyTableDefinition tableDefinition = getTableDefinition(); // PamTableItem tableItem; // setUpdatePolicy(UPDATE_POLICY_WRITENEW); diff --git a/src/IshmaelLocator/IshLocSqlLogging.java b/src/IshmaelLocator/IshLocSqlLogging.java index 0b95afe3..c43539d0 100644 --- a/src/IshmaelLocator/IshLocSqlLogging.java +++ b/src/IshmaelLocator/IshLocSqlLogging.java @@ -14,14 +14,13 @@ import IshmaelDetector.IshDetection; import PamUtils.LatLong; import PamguardMVC.PamDataBlock; import PamguardMVC.PamDataUnit; - +import generalDatabase.EmptyTableDefinition; //import pamDatabase.SQLLogging; //import PamguardMVC.RecyclingDataBlock; import generalDatabase.PamDetectionLogging; public class IshLocSqlLogging extends PamDetectionLogging { IshLocControl ishLocControl; - PamTableDefinition tableDefinition; PamTableItem systemDate, durationSecs, secSinceStart, peakHeight; private PamTableItem latitude, longitude, refLatitude, refLongitude, x, y, z; @@ -30,7 +29,7 @@ public class IshLocSqlLogging extends PamDetectionLogging { super(pamDataBlock, UPDATE_POLICY_WRITENEW); this.ishLocControl = ishDetControl; - tableDefinition = getTableDefinition(); + EmptyTableDefinition tableDefinition = getTableDefinition(); tableDefinition.addTableItem(latitude = new PamTableItem("Latitude", Types.DOUBLE)); tableDefinition.addTableItem(longitude = new PamTableItem("Longitude", Types.DOUBLE)); tableDefinition.addTableItem(refLatitude = new PamTableItem("ReferenceLatitude", Types.DOUBLE)); diff --git a/src/Map/GebcoMapFile.java b/src/Map/GebcoMapFile.java index f33474db..7945a026 100644 --- a/src/Map/GebcoMapFile.java +++ b/src/Map/GebcoMapFile.java @@ -13,6 +13,7 @@ import javax.swing.JOptionPane; import PamUtils.LatLong; import PamUtils.PamFileChooser; +import PamView.dialog.warn.WarnOnce; public class GebcoMapFile implements MapFileManager { @@ -83,7 +84,15 @@ public class GebcoMapFile implements MapFileManager { * @see Map.MapFile#readFileData(java.io.File) */ public boolean readFileData(File file) { - return readMapFile(file, true); + try { + return readMapFile(file, true); + } + catch (Exception e) { + // trap error someone reported at end November 22. Suspect it was their corrupt map file causing problems. + String err = String.format("Map file %s is missing or corrupt and cannot be loaded", file.getName()); + WarnOnce.showWarning("Map File Error", err, WarnOnce.OK_OPTION); + return false; + } } private boolean readMapFile(File gebcoFile, boolean readContours) { diff --git a/src/PamController/PamController.java b/src/PamController/PamController.java index c7546e04..bf231e5b 100644 --- a/src/PamController/PamController.java +++ b/src/PamController/PamController.java @@ -1192,6 +1192,8 @@ public class PamController implements PamControllerInterface, PamSettings { } if (saveSettings) { + startTime = PamCalendar.getSessionStartTime(); +// System.out.printf("Saving settings for start time %s\n", PamCalendar.formatDBDateTime(startTime)); saveSettings(PamCalendar.getSessionStartTime()); } @@ -1342,6 +1344,9 @@ public class PamController implements PamControllerInterface, PamSettings { } guiFrameManager.pamEnded(); + long stopTime = PamCalendar.getTimeInMillis(); + saveEndSettings(stopTime); + // no good having this here since it get's called at the end of every file. // if (GlobalArguments.getParam(PamController.AUTOEXIT) != null) { //// can exit here, since we've auto started, can auto exit. @@ -1467,6 +1472,25 @@ public class PamController implements PamControllerInterface, PamSettings { PamguardXMLWriter.getXMLWriter().writeStartSettings(timeNow); } + /** + * Gets called in pamStart and may / will attempt to store all + * PAMGUARD settings via the database and binary storage modules. + */ + private void saveEndSettings(long timeNow) { +// System.out.printf("Updating settings with end time %s\n", PamCalendar.formatDBDateTime(timeNow)); + PamControlledUnit pcu; + PamSettingsSource settingsSource; + for (int iU = 0; iU < pamControlledUnits.size(); iU++) { + pcu = pamControlledUnits.get(iU); + if (PamSettingsSource.class.isAssignableFrom(pcu.getClass())) { + settingsSource = (PamSettingsSource) pcu; + settingsSource.saveEndSettings(timeNow); + } + } + } + + + /** * Export configuration into an XML file * @param parentFrame diff --git a/src/PamController/PamSettingsSource.java b/src/PamController/PamSettingsSource.java index ed67807a..ba4079cc 100644 --- a/src/PamController/PamSettingsSource.java +++ b/src/PamController/PamSettingsSource.java @@ -20,6 +20,14 @@ public interface PamSettingsSource { */ public boolean saveStartSettings(long timeNow); + /** + * Save settings when processing ends. + * This may just be an update of the settings saves with saveStartSettings, e.g. an end time. + * @param timeNow + * @return true if saved correctly. + */ + public boolean saveEndSettings(long timeNow); + /** * Get the number of different settings * within the settings source. diff --git a/src/PamController/settings/output/xml/PamguardXMLWriter.java b/src/PamController/settings/output/xml/PamguardXMLWriter.java index 7149b3fc..72d54ac8 100644 --- a/src/PamController/settings/output/xml/PamguardXMLWriter.java +++ b/src/PamController/settings/output/xml/PamguardXMLWriter.java @@ -371,6 +371,32 @@ public class PamguardXMLWriter implements PamSettings { * @return xml content as a a string. */ public String getAsString(Document doc) { + return getAsString(doc, true); +// try { +// DOMSource domSource = new DOMSource(doc); +// StringWriter writer = new StringWriter(); +// StreamResult result = new StreamResult(writer); +// TransformerFactory tf = TransformerFactory.newInstance(); +// Transformer transformer = tf.newTransformer(); +// transformer.setOutputProperty(OutputKeys.METHOD, "xml"); +// transformer.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1"); +//// transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); +// transformer.setOutputProperty(OutputKeys.INDENT, "yes"); +// transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); +// transformer.transform(domSource, result); +// return writer.toString(); +// } catch (TransformerException e) { +// e.printStackTrace(); +// return null; +// } + } + /** + * Get the xml document as a String. + * @param doc xml document + * @param indent Indent / format the document. + * @return xml content as a a string. + */ + public String getAsString(Document doc, boolean indent) { try { DOMSource domSource = new DOMSource(doc); StringWriter writer = new StringWriter(); @@ -380,7 +406,7 @@ public class PamguardXMLWriter implements PamSettings { transformer.setOutputProperty(OutputKeys.METHOD, "xml"); transformer.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1"); // transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); - transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty(OutputKeys.INDENT, indent ? "yes" : "no"); transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); transformer.transform(domSource, result); return writer.toString(); diff --git a/src/RightWhaleEdgeDetector/RWESQLLogging.java b/src/RightWhaleEdgeDetector/RWESQLLogging.java index 82889f84..76e9f841 100644 --- a/src/RightWhaleEdgeDetector/RWESQLLogging.java +++ b/src/RightWhaleEdgeDetector/RWESQLLogging.java @@ -7,6 +7,7 @@ import PamDetection.AcousticSQLLogging; import PamUtils.PamUtils; import PamguardMVC.PamDataBlock; import PamguardMVC.PamDataUnit; +import generalDatabase.EmptyTableDefinition; import generalDatabase.PamTableDefinition; import generalDatabase.PamTableItem; import generalDatabase.SQLTypes; @@ -26,7 +27,7 @@ public class RWESQLLogging extends AcousticSQLLogging { angles = new PamTableItem[maxAngles]; angleErrors = new PamTableItem[maxAngles]; - PamTableDefinition tableDef = getTableDefinition(); + EmptyTableDefinition tableDef = getTableDefinition(); tableDef.addTableItem(score = new PamTableItem("score", Types.INTEGER)); tableDef.addTableItem(signal = new PamTableItem("signal", Types.DOUBLE)); tableDef.addTableItem(noise = new PamTableItem("noise", Types.DOUBLE)); diff --git a/src/analogarraysensor/ArraySensorLogging.java b/src/analogarraysensor/ArraySensorLogging.java index e4eba2e9..ca13752a 100644 --- a/src/analogarraysensor/ArraySensorLogging.java +++ b/src/analogarraysensor/ArraySensorLogging.java @@ -56,7 +56,8 @@ public class ArraySensorLogging extends SQLLogging { AnalogSensorData aData = new AnalogSensorData(rawValue, calValue); sensorData[i] = aData; } - int chanMap = getTableDefinition().getChannelBitmap().getIntegerValue(); + PamTableDefinition pamTableDef = (PamTableDefinition) getTableDefinition(); + int chanMap = pamTableDef.getChannelBitmap().getIntegerValue(); int streamer = PamUtils.getSingleChannel(chanMap); if (streamer < 0) streamer = 0; AnalogArraySensorDataUnit asdu = new AnalogArraySensorDataUnit(timeMilliseconds, streamer, sensorData); diff --git a/src/annotation/calcs/snr/SnrSqlAddon.java b/src/annotation/calcs/snr/SnrSqlAddon.java index e04c98e1..b0f25976 100644 --- a/src/annotation/calcs/snr/SnrSqlAddon.java +++ b/src/annotation/calcs/snr/SnrSqlAddon.java @@ -3,6 +3,7 @@ package annotation.calcs.snr; import java.sql.Types; import PamguardMVC.PamDataUnit; +import generalDatabase.EmptyTableDefinition; import generalDatabase.PamTableDefinition; import generalDatabase.PamTableItem; import generalDatabase.SQLLoggingAddon; @@ -21,13 +22,13 @@ public class SnrSqlAddon implements SQLLoggingAddon { } @Override - public void addTableItems(PamTableDefinition pamTableDefinition) { + public void addTableItems(EmptyTableDefinition pamTableDefinition) { pamTableDefinition.addTableItem(snr); } @Override - public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, + public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { SNRAnnotation snrAnnotation = (SNRAnnotation) pamDataUnit.findDataAnnotation(SNRAnnotation.class); if (snrAnnotation == null) { @@ -40,7 +41,7 @@ public class SnrSqlAddon implements SQLLoggingAddon { } @Override - public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, + public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { Double snrVal = (Double) snr.getValue(); if (snrVal != null) { diff --git a/src/annotation/calcs/spl/SPLSqlAddon.java b/src/annotation/calcs/spl/SPLSqlAddon.java index adc301fd..8966d024 100644 --- a/src/annotation/calcs/spl/SPLSqlAddon.java +++ b/src/annotation/calcs/spl/SPLSqlAddon.java @@ -3,6 +3,7 @@ package annotation.calcs.spl; import java.sql.Types; import PamguardMVC.PamDataUnit; +import generalDatabase.EmptyTableDefinition; import generalDatabase.PamTableDefinition; import generalDatabase.PamTableItem; import generalDatabase.SQLLoggingAddon; @@ -25,7 +26,7 @@ public class SPLSqlAddon implements SQLLoggingAddon { } @Override - public void addTableItems(PamTableDefinition pamTableDefinition) { + public void addTableItems(EmptyTableDefinition pamTableDefinition) { pamTableDefinition.addTableItem(rms); pamTableDefinition.addTableItem(zeroPeak); pamTableDefinition.addTableItem(peakPeak); @@ -33,7 +34,7 @@ public class SPLSqlAddon implements SQLLoggingAddon { } @Override - public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, + public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { SPLAnnotation splAnnotation = (SPLAnnotation) pamDataUnit.findDataAnnotation(SPLAnnotation.class); if (splAnnotation == null) { @@ -52,7 +53,7 @@ public class SPLSqlAddon implements SQLLoggingAddon { } @Override - public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, + public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { SPLAnnotation splAnnotation = new SPLAnnotation(splAnnotationType); if (splAnnotation != null) { diff --git a/src/annotation/calcs/wav/WavSqlAddon.java b/src/annotation/calcs/wav/WavSqlAddon.java index 73b869af..d9094a74 100644 --- a/src/annotation/calcs/wav/WavSqlAddon.java +++ b/src/annotation/calcs/wav/WavSqlAddon.java @@ -3,6 +3,7 @@ package annotation.calcs.wav; import java.sql.Types; import PamguardMVC.PamDataUnit; +import generalDatabase.EmptyTableDefinition; import generalDatabase.PamTableDefinition; import generalDatabase.PamTableItem; import generalDatabase.SQLLoggingAddon; @@ -21,13 +22,13 @@ public class WavSqlAddon implements SQLLoggingAddon { } @Override - public void addTableItems(PamTableDefinition pamTableDefinition) { + public void addTableItems(EmptyTableDefinition pamTableDefinition) { pamTableDefinition.addTableItem(wavFileName); } @Override - public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, + public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { WavAnnotation annotation = (WavAnnotation) pamDataUnit.findDataAnnotation(WavAnnotation.class); if (annotation == null) { @@ -40,7 +41,7 @@ public class WavSqlAddon implements SQLLoggingAddon { } @Override - public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, + public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { String fileName = (String) wavFileName.getValue(); if (fileName != null) { diff --git a/src/annotation/handler/OneStopAnnotationHandler.java b/src/annotation/handler/OneStopAnnotationHandler.java index cdcda357..50dc1983 100644 --- a/src/annotation/handler/OneStopAnnotationHandler.java +++ b/src/annotation/handler/OneStopAnnotationHandler.java @@ -15,6 +15,7 @@ import PamView.dialog.GenericSwingDialog; import PamguardMVC.PamDataBlock; import PamguardMVC.PamDataUnit; import generalDatabase.DBControlUnit; +import generalDatabase.EmptyTableDefinition; import generalDatabase.PamTableDefinition; import generalDatabase.SQLLogging; @@ -126,7 +127,7 @@ public abstract class OneStopAnnotationHandler extends AnnotationChoiceHandler i return; } // get, modify and set the modified tabelDef - PamTableDefinition tableDef = logging.getBaseTableDefinition(); + EmptyTableDefinition tableDef = logging.getBaseTableDefinition(); logging.setTableDefinition(tableDef); addAnnotationSqlAddons(logging); // this will add the additional columns. DBControlUnit dbc = DBControlUnit.findDatabaseControl(); diff --git a/src/annotation/localise/targetmotion/TMAnnotationLogging.java b/src/annotation/localise/targetmotion/TMAnnotationLogging.java index 0f7de36e..ab50818e 100644 --- a/src/annotation/localise/targetmotion/TMAnnotationLogging.java +++ b/src/annotation/localise/targetmotion/TMAnnotationLogging.java @@ -3,6 +3,7 @@ package annotation.localise.targetmotion; import Localiser.detectionGroupLocaliser.GroupLocalisation; import PamDetection.AbstractLocalisation; import PamguardMVC.PamDataUnit; +import generalDatabase.EmptyTableDefinition; import generalDatabase.PamTableDefinition; import generalDatabase.SQLTypes; import targetMotionOld.TargetMotionSQLLogging; @@ -17,7 +18,7 @@ public class TMAnnotationLogging extends TargetMotionSQLLogging { } @Override - public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { + public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { boolean ans = super.loadData(sqlTypes, pamTableDefinition, pamDataUnit); if (ans == false) return false; AbstractLocalisation loc = pamDataUnit.getLocalisation(); diff --git a/src/annotation/string/StringSQLLogging.java b/src/annotation/string/StringSQLLogging.java index 849328b0..e216f83d 100644 --- a/src/annotation/string/StringSQLLogging.java +++ b/src/annotation/string/StringSQLLogging.java @@ -3,6 +3,7 @@ package annotation.string; import java.sql.Types; import PamguardMVC.PamDataUnit; +import generalDatabase.EmptyTableDefinition; import generalDatabase.PamTableDefinition; import generalDatabase.PamTableItem; import generalDatabase.SQLLoggingAddon; @@ -24,12 +25,12 @@ public class StringSQLLogging implements SQLLoggingAddon { } @Override - public void addTableItems(PamTableDefinition pamTableDefinition) { + public void addTableItems(EmptyTableDefinition pamTableDefinition) { pamTableDefinition.addTableItem(notes); } @Override - public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { + public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { StringAnnotation stringAnnotation = (StringAnnotation) pamDataUnit.findDataAnnotation(StringAnnotation.class, stringAnnotationType.getAnnotationName()); if (stringAnnotation == null) { @@ -42,7 +43,7 @@ public class StringSQLLogging implements SQLLoggingAddon { } @Override - public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { + public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { try { String note = notes.getDeblankedStringValue(); if (note != null && note.length() > 0) { diff --git a/src/annotation/timestamp/TimestampSQLLogging.java b/src/annotation/timestamp/TimestampSQLLogging.java index fd1d7be6..2f6b0728 100644 --- a/src/annotation/timestamp/TimestampSQLLogging.java +++ b/src/annotation/timestamp/TimestampSQLLogging.java @@ -3,6 +3,7 @@ package annotation.timestamp; import java.sql.Types; import PamguardMVC.PamDataUnit; +import generalDatabase.EmptyTableDefinition; import generalDatabase.PamTableDefinition; import generalDatabase.PamTableItem; import generalDatabase.SQLLoggingAddon; @@ -22,12 +23,12 @@ public class TimestampSQLLogging implements SQLLoggingAddon { } @Override - public void addTableItems(PamTableDefinition pamTableDefinition) { + public void addTableItems(EmptyTableDefinition pamTableDefinition) { pamTableDefinition.addTableItem(timestamp); } @Override - public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { + public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { TimestampAnnotation timestampAnnotation = (TimestampAnnotation) pamDataUnit.findDataAnnotation(TimestampAnnotation.class, timestampAnnotationType.getAnnotationName()); if (timestampAnnotation == null) { @@ -40,7 +41,7 @@ public class TimestampSQLLogging implements SQLLoggingAddon { } @Override - public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { + public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { try { TimestampAnnotation timestampAnnotation = new TimestampAnnotation(timestampAnnotationType); Long note = sqlTypes.millisFromTimeStamp(timestamp.getValue()); diff --git a/src/annotation/userforms/UserFormSQLAddon.java b/src/annotation/userforms/UserFormSQLAddon.java index acecc6cc..e30e0ea3 100644 --- a/src/annotation/userforms/UserFormSQLAddon.java +++ b/src/annotation/userforms/UserFormSQLAddon.java @@ -3,6 +3,7 @@ package annotation.userforms; import java.util.ArrayList; import PamguardMVC.PamDataUnit; +import generalDatabase.EmptyTableDefinition; import generalDatabase.PamTableDefinition; import generalDatabase.PamTableItem; import generalDatabase.SQLLoggingAddon; @@ -31,7 +32,7 @@ public class UserFormSQLAddon implements SQLLoggingAddon { @Override - public void addTableItems(PamTableDefinition pamTableDefinition) { + public void addTableItems(EmptyTableDefinition pamTableDefinition) { loggerTableItems.clear(); FormDescription formDescription = userFormAnnotationType.findFormDescription(); if (formDescription == null) { @@ -51,7 +52,7 @@ public class UserFormSQLAddon implements SQLLoggingAddon { } @Override - public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { + public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { if (pamDataUnit == null) { clearTableItems(); return false; @@ -86,7 +87,7 @@ public class UserFormSQLAddon implements SQLLoggingAddon { } @Override - public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { + public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { FormDescription formDescription = userFormAnnotationType.findFormDescription(); if (formDescription == null) { return false; diff --git a/src/beamformer/annotation/BFAnnotationLogging.java b/src/beamformer/annotation/BFAnnotationLogging.java index 83d7641a..ba9bed54 100644 --- a/src/beamformer/annotation/BFAnnotationLogging.java +++ b/src/beamformer/annotation/BFAnnotationLogging.java @@ -6,6 +6,7 @@ import PamDetection.LocContents; import PamguardMVC.PamDataBlock; import PamguardMVC.PamDataUnit; import beamformer.loc.BeamFormerLocalisation; +import generalDatabase.EmptyTableDefinition; import generalDatabase.PamTableDefinition; import generalDatabase.PamTableItem; import generalDatabase.SQLLoggingAddon; @@ -29,7 +30,7 @@ public class BFAnnotationLogging implements SQLLoggingAddon { } @Override - public void addTableItems(PamTableDefinition pamTableDefinition) { + public void addTableItems(EmptyTableDefinition pamTableDefinition) { pamTableDefinition.addTableItem(bfPhones); pamTableDefinition.addTableItem(bfArrayType); pamTableDefinition.addTableItem(bfContents); @@ -38,7 +39,7 @@ public class BFAnnotationLogging implements SQLLoggingAddon { } @Override - public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { + public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { bfPhones.setValue(null); bfArrayType.setValue(null); bfContents.setValue(null); @@ -64,7 +65,7 @@ public class BFAnnotationLogging implements SQLLoggingAddon { } @Override - public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { + public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { Float[] Angles = new Float[2]; for (int i = 0; i < 2; i++) { Angles[i] = (Float) angle[i].getFloatValue(); diff --git a/src/bearinglocaliser/annotation/BearingAnnotationSQL.java b/src/bearinglocaliser/annotation/BearingAnnotationSQL.java index bc4b88bb..d56e8be7 100644 --- a/src/bearinglocaliser/annotation/BearingAnnotationSQL.java +++ b/src/bearinglocaliser/annotation/BearingAnnotationSQL.java @@ -4,6 +4,7 @@ import java.sql.Types; import PamguardMVC.PamDataUnit; import bearinglocaliser.BearingLocalisation; +import generalDatabase.EmptyTableDefinition; import generalDatabase.PamTableDefinition; import generalDatabase.PamTableItem; import generalDatabase.SQLLoggingAddon; @@ -34,7 +35,7 @@ public class BearingAnnotationSQL implements SQLLoggingAddon { } @Override - public void addTableItems(PamTableDefinition pamTableDefinition) { + public void addTableItems(EmptyTableDefinition pamTableDefinition) { pamTableDefinition.addTableItem(algoName); pamTableDefinition.addTableItem(bfPhones); pamTableDefinition.addTableItem(bfArrayType); @@ -48,7 +49,7 @@ public class BearingAnnotationSQL implements SQLLoggingAddon { } @Override - public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { + public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { algoName.setValue(null); bfPhones.setValue(null); bfArrayType.setValue(null); @@ -96,7 +97,7 @@ public class BearingAnnotationSQL implements SQLLoggingAddon { } @Override - public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { + public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { Float[] Angles = new Float[2]; int nNans = 0; for (int i = 0; i < 2; i++) { diff --git a/src/binaryFileStorage/BinarySettingsStorage.java b/src/binaryFileStorage/BinarySettingsStorage.java index 48278c1d..c59992d8 100644 --- a/src/binaryFileStorage/BinarySettingsStorage.java +++ b/src/binaryFileStorage/BinarySettingsStorage.java @@ -110,6 +110,12 @@ public class BinarySettingsStorage implements PamSettingsSource { return false;*/ } + @Override + public boolean saveEndSettings(long timeNow) { + // do nothing at the end of a run with binary store. + return true; + } + // private boolean writeData(DataOutputStream dos, int objectId, byte[] data) { // int totalLen = data.length + 16; // int dataLen = data.length; diff --git a/src/binaryFileStorage/BinaryStore.java b/src/binaryFileStorage/BinaryStore.java index c2007cb2..6d1ff8fe 100644 --- a/src/binaryFileStorage/BinaryStore.java +++ b/src/binaryFileStorage/BinaryStore.java @@ -537,6 +537,12 @@ PamSettingsSource, OfflineDataStore { return binarySettingsStorage.saveStartSettings(timeNow); } + @Override + public boolean saveEndSettings(long timeNow) { + // TODO Auto-generated method stub + return false; + } + @Override public int getNumSettings() { if (binarySettingsStorage == null) { diff --git a/src/binaryFileStorage/BinaryStoreProcess.java b/src/binaryFileStorage/BinaryStoreProcess.java index 7d653fbc..f1f06fd8 100644 --- a/src/binaryFileStorage/BinaryStoreProcess.java +++ b/src/binaryFileStorage/BinaryStoreProcess.java @@ -46,7 +46,8 @@ public class BinaryStoreProcess extends PamProcess { startTime = PamCalendar.getTimeInMillis(); long round = binaryStore.binaryStoreSettings.fileSeconds * 1000; nextFileTime = (startTime/round) * round + round; - System.out.println("Next file start at " + PamCalendar.formatDateTime(nextFileTime)); + // this was a print of the time of the NEXT binary file. Not really of interest. +// System.out.println("Next file start at " + PamCalendar.formatDateTime(nextFileTime)); timer = new Timer(); timer.schedule(new FileTimerTask(), 1000, 1000); diff --git a/src/clickDetector/ClickClassifiers/annotation/ClickAnnotationSQL.java b/src/clickDetector/ClickClassifiers/annotation/ClickAnnotationSQL.java index baa057ac..840d2086 100644 --- a/src/clickDetector/ClickClassifiers/annotation/ClickAnnotationSQL.java +++ b/src/clickDetector/ClickClassifiers/annotation/ClickAnnotationSQL.java @@ -3,6 +3,7 @@ package clickDetector.ClickClassifiers.annotation; import java.sql.Types; import PamguardMVC.PamDataUnit; +import generalDatabase.EmptyTableDefinition; import generalDatabase.PamTableDefinition; import generalDatabase.PamTableItem; import generalDatabase.SQLLoggingAddon; @@ -33,12 +34,12 @@ public class ClickAnnotationSQL implements SQLLoggingAddon { } @Override - public void addTableItems(PamTableDefinition pamTableDefinition) { + public void addTableItems(EmptyTableDefinition pamTableDefinition) { pamTableDefinition.addTableItem(classifierSetTable); } @Override - public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { + public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { ClickClassifierAnnotation clickAnnotation = (ClickClassifierAnnotation) pamDataUnit.findDataAnnotation(ClickClassificationType.class); //create a comma delimited string @@ -53,7 +54,7 @@ public class ClickAnnotationSQL implements SQLLoggingAddon { @Override - public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { + public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { String array = classifierSetTable.getDeblankedStringValue(); //read in the classification set. This a list of all the classifiers the clicks passed. diff --git a/src/clickDetector/TrackedClickGroupLogging.java b/src/clickDetector/TrackedClickGroupLogging.java index 6016f704..90e7af9a 100644 --- a/src/clickDetector/TrackedClickGroupLogging.java +++ b/src/clickDetector/TrackedClickGroupLogging.java @@ -1,5 +1,6 @@ package clickDetector; +import generalDatabase.PamTableDefinition; import generalDatabase.SQLTypes; import PamguardMVC.PamDataUnit; import clickDetector.offlineFuncs.OfflineEventDataUnit; @@ -30,7 +31,8 @@ public class TrackedClickGroupLogging extends ClickGroupLogging { boolean isUpdate = true; // Timestamp ts = (Timestamp) getTableDefinition().getTimeStampItem().getValue(); // long t = PamCalendar.millisFromTimeStamp(ts); - int updateIndex = (Integer) getTableDefinition().getUpdateReference().getValue(); + PamTableDefinition tableDef = (PamTableDefinition) getTableDefinition(); + int updateIndex = (Integer) tableDef.getUpdateReference().getValue(); if (updateIndex > 0) { tcg = this.clickGroupDataBlock.findByDatabaseIndex(updateIndex); } diff --git a/src/clickDetector/dataSelector/ClickTrainDataSelector2.java b/src/clickDetector/dataSelector/ClickTrainDataSelector2.java index 0520b4fb..9bde5123 100644 --- a/src/clickDetector/dataSelector/ClickTrainDataSelector2.java +++ b/src/clickDetector/dataSelector/ClickTrainDataSelector2.java @@ -82,7 +82,7 @@ public class ClickTrainDataSelector2 extends DataSelector { } SQLLogging logging = getPamDataBlock().getLogging(); if (logging == null) return null; //cannot happen! - PamTableDefinition tableDef = logging.getTableDefinition(); + EmptyTableDefinition tableDef = logging.getTableDefinition(); if (params.isIncludeUnclassified()) { return null; } diff --git a/src/clickDetector/offlineFuncs/DatabaseChecks.java b/src/clickDetector/offlineFuncs/DatabaseChecks.java index 38bfe6a5..585bbf50 100644 --- a/src/clickDetector/offlineFuncs/DatabaseChecks.java +++ b/src/clickDetector/offlineFuncs/DatabaseChecks.java @@ -102,16 +102,17 @@ public class DatabaseChecks { long resultTime; long firstTime = Long.MAX_VALUE; long lastTime = Long.MIN_VALUE; + PamTableDefinition pamTableDef = (PamTableDefinition) clickLogging.getTableDefinition(); try { Statement stmt = con.getConnection().createStatement(); ResultSet result = stmt.executeQuery(sqlStr); while (result.next()) { nClicks++; clickLogging.transferDataFromResult(sqlTypes, result); - ts = clickLogging.getTableDefinition().getTimeStampItem().getValue(); + ts = pamTableDef.getTimeStampItem().getValue(); resultTime = sqlTypes.millisFromTimeStamp(ts); if (resultTime%1000 == 0) { - resultTime += clickLogging.getTableDefinition().getTimeStampMillis().getIntegerValue(); + resultTime += pamTableDef.getTimeStampMillis().getIntegerValue(); } firstTime = Math.min(firstTime, resultTime); lastTime = Math.max(lastTime, resultTime); @@ -188,7 +189,7 @@ public class DatabaseChecks { eventDataBlock.addPamData(event); PamConnection con = DBControlUnit.findConnection(); // now find a cursor and save it. - PamTableDefinition eventTableDef = eventDataBlock.getLogging().getTableDefinition(); + PamTableDefinition eventTableDef = (PamTableDefinition) eventDataBlock.getLogging().getTableDefinition(); PamCursor cursor = eventDataBlock.getLogging().getViewerCursorFinder().getCursor(con, eventTableDef); cursor.immediateInsert(con); int newId = event.getDatabaseIndex(); diff --git a/src/clickDetector/offlineFuncs/OfflineClickLogging.java b/src/clickDetector/offlineFuncs/OfflineClickLogging.java index a75897f7..4b4360dc 100644 --- a/src/clickDetector/offlineFuncs/OfflineClickLogging.java +++ b/src/clickDetector/offlineFuncs/OfflineClickLogging.java @@ -277,13 +277,14 @@ public class OfflineClickLogging extends SQLLogging { Integer millis; Object ts; SQLTypes sqlTypes = dbControl.getConnection().getSqlTypes(); + PamTableDefinition tableDef = (PamTableDefinition) getTableDefinition(); try { while (resultSet.next()) { transferDataFromResult(sqlTypes, resultSet); - ts = getTableDefinition().getTimeStampItem().getValue(); + ts = tableDef.getTimeStampItem().getValue(); long m = SQLTypes.millisFromTimeStamp(ts); if (m%1000 == 0) { - millis = (Integer) getTableDefinition().getTimeStampMillis().getValue(); + millis = (Integer) tableDef.getTimeStampMillis().getValue(); if (millis != null) { m += millis; } diff --git a/src/clickDetector/offlineFuncs/rcImport/RainbowDatabseConverter.java b/src/clickDetector/offlineFuncs/rcImport/RainbowDatabseConverter.java index d4fb6fb2..0b9b0996 100644 --- a/src/clickDetector/offlineFuncs/rcImport/RainbowDatabseConverter.java +++ b/src/clickDetector/offlineFuncs/rcImport/RainbowDatabseConverter.java @@ -148,7 +148,7 @@ public class RainbowDatabseConverter { ClickDataBlock clickDataBlock = clickControl.getClickDataBlock(); clickLogging = new ClickImportLogging(clickControl); - PamTableDefinition tableDef = clickLogging.getTableDefinition(); + PamTableDefinition tableDef = (PamTableDefinition) clickLogging.getTableDefinition(); boolean ok = checkTable(pamConnection, tableDef); if (!ok) { System.out.println("Error in Pamguard clicks table"); @@ -156,7 +156,7 @@ public class RainbowDatabseConverter { } eventLogging = new OfflineEventLogging(clickControl, clickControl.getClickDetector().getOfflineEventDataBlock()); - tableDef = eventLogging.getTableDefinition(); + tableDef = (PamTableDefinition) eventLogging.getTableDefinition(); ok = checkTable(pamConnection, tableDef); if (!ok) { System.out.println("Error in Pamguard events table"); diff --git a/src/difar/trackedGroups/TrackedGroupSqlLogging.java b/src/difar/trackedGroups/TrackedGroupSqlLogging.java index 54bd708b..e3b8b15b 100644 --- a/src/difar/trackedGroups/TrackedGroupSqlLogging.java +++ b/src/difar/trackedGroups/TrackedGroupSqlLogging.java @@ -125,7 +125,7 @@ public class TrackedGroupSqlLogging extends SQLLogging { */ protected void updateData(SQLTypes sqlTypes, PamDataUnit pamDataUnit) { - PamTableDefinition tableDef = getTableDefinition(); + PamTableDefinition tableDef = (PamTableDefinition) getTableDefinition(); PamTableItem tableItem; tableDef.getIndexItem().setValue(pamDataUnit.getDatabaseIndex()); diff --git a/src/generalDatabase/DBControl.java b/src/generalDatabase/DBControl.java index eb2697d5..1dc9584a 100644 --- a/src/generalDatabase/DBControl.java +++ b/src/generalDatabase/DBControl.java @@ -572,10 +572,16 @@ PamSettingsSource { */ @Override public boolean saveStartSettings(long timeNow) { - return dbProcess.saveStartSettings(); + return dbProcess.saveStartSettings(timeNow); } + @Override + public boolean saveEndSettings(long timeNow) { + // TODO Auto-generated method stub + return true; + } + @Override public int getNumSettings() { if (dbSettingsStore == null) { diff --git a/src/generalDatabase/DBProcess.java b/src/generalDatabase/DBProcess.java index 9e3bf699..5e62f6a3 100644 --- a/src/generalDatabase/DBProcess.java +++ b/src/generalDatabase/DBProcess.java @@ -96,6 +96,8 @@ public class DBProcess extends PamProcess { dbSpecials.add(logSettings = new LogSettings(databaseControll, "Pamguard Settings", false)); dbSpecials.add(logLastSettings = new LogSettings(databaseControll, "Pamguard Settings Last", true)); dbSpecials.add(logViewerSettings = new LogSettings(databaseControll, "Pamguard Settings Viewer", true)); + + dbSpecials.add(new LogXMLSettings(databaseControll)); } @@ -107,9 +109,13 @@ public class DBProcess extends PamProcess { } } - protected boolean saveStartSettings() { + protected boolean saveStartSettings(long timeNow) { PamConnection con = databaseControll.getConnection(); if (con != null) { + /** + * This first one is the 'old' pre 2022 method which saves a serialised lump of all + * the settings in the database. It ain't broke, so not fixing it. + */ for (int i = 0; i < dbSpecials.size(); i++) { dbSpecials.get(i).pamStart(con); } @@ -118,6 +124,11 @@ public class DBProcess extends PamProcess { return false; } + protected boolean saveEndSettings(long timeNow) { + + return true; + } + @Override public void pamStop() { PamConnection con = databaseControll.getConnection(); @@ -206,7 +217,7 @@ public class DBProcess extends PamProcess { } dataBlocks = PamController.getInstance().getDataBlocks(); - PamTableDefinition tableDefinition; + EmptyTableDefinition tableDefinition; SQLLogging logging; // for each datablock, check that the process can log (ignoring GPS process) diff --git a/src/generalDatabase/DBSchemaWriter.java b/src/generalDatabase/DBSchemaWriter.java index f602ad5c..213601fe 100644 --- a/src/generalDatabase/DBSchemaWriter.java +++ b/src/generalDatabase/DBSchemaWriter.java @@ -48,7 +48,7 @@ public class DBSchemaWriter { } - PamTableDefinition tableDef = logging.getTableDefinition(); + EmptyTableDefinition tableDef = logging.getTableDefinition(); tableDef = logging.getBaseTableDefinition(); if (tableDef instanceof PamTableDefinition) { @@ -63,7 +63,7 @@ public class DBSchemaWriter { return true; } - private void exportDatabaseSchema(File outputFolder, PamDataBlock dataBlock, SQLLogging logging, PamTableDefinition tableDef) { + private void exportDatabaseSchema(File outputFolder, PamDataBlock dataBlock, SQLLogging logging, EmptyTableDefinition tableDef) { /** * write a parent item, e.g. if tableDef is a sub class of PamTableDefinition diff --git a/src/generalDatabase/DbSpecial.java b/src/generalDatabase/DbSpecial.java index 05400f7a..401eac1a 100644 --- a/src/generalDatabase/DbSpecial.java +++ b/src/generalDatabase/DbSpecial.java @@ -9,7 +9,7 @@ import PamguardMVC.PamDataUnit; * @author Doug Gillespie * */ -abstract public class DbSpecial extends SQLLogging{ +abstract public class DbSpecial extends SQLLogging { private DBControl dbControl; diff --git a/src/generalDatabase/EmptyTableDefinition.java b/src/generalDatabase/EmptyTableDefinition.java index 9e10753e..53cfd1fb 100644 --- a/src/generalDatabase/EmptyTableDefinition.java +++ b/src/generalDatabase/EmptyTableDefinition.java @@ -300,7 +300,7 @@ public class EmptyTableDefinition implements Cloneable { * @param tableName * @return reference to the database deinition if it exists, or null */ - static PamTableDefinition findTableDefinition(String tableName) { + static EmptyTableDefinition findTableDefinition(String tableName) { String searchName = EmptyTableDefinition.deblankString(tableName); SQLLogging log = SQLLogging.findLogger(searchName); if (log == null) return null; @@ -389,6 +389,15 @@ public class EmptyTableDefinition implements Cloneable { this.updatePolicy = updatePolicy; } + public PamConnection getCheckedConnection() { + return checkedConnection; + } + + public void setCheckedConnection(PamConnection checkedConnection) { + this.checkedConnection = checkedConnection; + } + + @Override protected EmptyTableDefinition clone() { try { diff --git a/src/generalDatabase/LogSettings.java b/src/generalDatabase/LogSettings.java index af5305e9..23b713be 100644 --- a/src/generalDatabase/LogSettings.java +++ b/src/generalDatabase/LogSettings.java @@ -23,7 +23,7 @@ import PamUtils.PamCalendar; import PamguardMVC.PamDataUnit; /** - * Functions for writing Pamguard Settings into any database as character data + * Functions for writing serialised Pamguard Settings into any database as character data * Runs at DAQ start, goes through the settings manager list and for each * set of settings, it serialises the settings data into a binary array, this * is then converted from binary data to 6 bit ascii data (using the character set @@ -185,6 +185,7 @@ public class LogSettings extends DbSpecial { DeserialisationWarning dsWarning = new DeserialisationWarning(getDbControl().getDatabaseName()); SQLTypes sqlTypes = con.getSqlTypes(); + boolean haveData; if (result != null) try { haveData = result.next(); @@ -193,7 +194,7 @@ public class LogSettings extends DbSpecial { // transfer data back into the tableItems store. transferDataFromResult(sqlTypes, result); - tableItem = getTableDefinition().getTimeStampItem(); + tableItem = tableDef.getTimeStampItem(); // timestamp = (Timestamp) tableItem.getTimestampValue(); timeMillis = sqlTypes.millisFromTimeStamp(tableItem.getValue()); diff --git a/src/generalDatabase/LogXMLDataUnit.java b/src/generalDatabase/LogXMLDataUnit.java new file mode 100644 index 00000000..63189784 --- /dev/null +++ b/src/generalDatabase/LogXMLDataUnit.java @@ -0,0 +1,75 @@ +package generalDatabase; + +import PamController.PamSettings; +import PamguardMVC.PamDataUnit; + +/** + * simple data unit for use with the LogXMLSettings class + * @author dg50 + * + */ +public class LogXMLDataUnit extends PamDataUnit { + + private long processTime; + private PamSettings pamSettings; + private String xml; + private Long dataEnd, processEnd; + + public LogXMLDataUnit(long timeMilliseconds, long processTime, PamSettings pamSettings, String xml) { + super(timeMilliseconds); + this.processTime = processTime; + this.pamSettings = pamSettings; + this.xml = xml; + } + + /** + * @return the dataEnd + */ + public Long getDataEnd() { + return dataEnd; + } + + /** + * @param dataEnd the dataEnd to set + */ + public void setDataEnd(Long dataEnd) { + this.dataEnd = dataEnd; + } + + /** + * @return the processEnd + */ + public Long getProcessEnd() { + return processEnd; + } + + /** + * @param processEnd the processEnd to set + */ + public void setProcessEnd(Long processEnd) { + this.processEnd = processEnd; + } + + /** + * @return the processTime + */ + public long getProcessTime() { + return processTime; + } + + /** + * @return the pamSettings + */ + public PamSettings getPamSettings() { + return pamSettings; + } + + /** + * @return the xml + */ + public String getXml() { + return xml; + } + + +} diff --git a/src/generalDatabase/LogXMLSettings.java b/src/generalDatabase/LogXMLSettings.java new file mode 100644 index 00000000..76a576b5 --- /dev/null +++ b/src/generalDatabase/LogXMLSettings.java @@ -0,0 +1,123 @@ +package generalDatabase; + +import java.io.Serializable; +import java.util.HashMap; + +import org.w3c.dom.Document; + +import PamController.PamControlledUnit; +import PamController.PamController; +import PamController.PamSettings; +import PamController.PamguardVersionInfo; +import PamController.settings.output.xml.PamguardXMLWriter; +import PamUtils.PamCalendar; +import PamguardMVC.PamDataUnit; +/** + * 2022 Additional say of saving settings for each module into the database in more human readable + * XML format.

+ * In other ways, similar to LogSettings which saves serialised Java. This will write a line + * per module. A main difference is that on pamStop it will update the end time for each line, so + * that we have a record of analysis effort for each module. Will therefore need to store the last + * index of the entry for each module, so that we can update the appropriate row. + * @author dg50 + * + */ +public class LogXMLSettings extends DbSpecial { + + private XMLSettingsTableDefinition xmlTableDef; + + private HashMap moduleRows; + + private PamguardXMLWriter xmlWriter; + + public LogXMLSettings(DBControl dbControl) { + super(dbControl); + xmlTableDef = new XMLSettingsTableDefinition("Module Effort"); + setTableDefinition(xmlTableDef); + moduleRows = new HashMap<>(); + xmlWriter = PamguardXMLWriter.getXMLWriter(); + } + + @Override + public void pamStart(PamConnection con) { + long time = PamCalendar.getTimeInMillis(); + saveModuleSettings(con, time); + } + + @Override + public void pamStop(PamConnection con) { + long time = PamCalendar.getTimeInMillis(); + updateModuleSettings(con, time); + } + + private void saveModuleSettings(PamConnection con, long dataTime) { + int n = PamController.getInstance().getNumControlledUnits(); + long now = System.currentTimeMillis(); + for (int i = 0; i < n; i++) { + saveModuleSettings(con, dataTime, now, PamController.getInstance().getControlledUnit(i)); + } + + } + + private void saveModuleSettings(PamConnection con, long dataTime, long now, PamControlledUnit controlledUnit) { + if (controlledUnit instanceof PamSettings == false) { + return; + } + PamSettings pamSettings = (PamSettings) controlledUnit; + Serializable settings = pamSettings.getSettingsReference(); + Document doc = xmlWriter.writeOneModule(pamSettings, dataTime); + String xmlString = xmlWriter.getAsString(doc, true); + LogXMLDataUnit logXMLDataUnit = new LogXMLDataUnit(dataTime, now, pamSettings, xmlString); + + logData(logXMLDataUnit); + int dbIndex = logXMLDataUnit.getDatabaseIndex(); + moduleRows.put(getModuleHash(pamSettings), logXMLDataUnit); + } + + private void updateModuleSettings(PamConnection con, long dataTime) { + int n = PamController.getInstance().getNumControlledUnits(); + long now = System.currentTimeMillis(); + for (int i = 0; i < n; i++) { + updateModuleSettings(con, dataTime, now, PamController.getInstance().getControlledUnit(i)); + } + + } + + private void updateModuleSettings(PamConnection con, long dataTime, long now, PamControlledUnit controlledUnit) { + if (controlledUnit instanceof PamSettings == false) { + return; + } + PamSettings pamSettings = (PamSettings) controlledUnit; + LogXMLDataUnit logXMLDataUnit = moduleRows.get(getModuleHash(pamSettings)); + if (logXMLDataUnit == null) { + return; + } + logXMLDataUnit.setDataEnd(dataTime); + logXMLDataUnit.setProcessEnd(now); + reLogData(con, logXMLDataUnit); + } + + private String getModuleHash(PamSettings pamSettings) { + if (pamSettings == null) { + return null; + } + return pamSettings.getUnitName()+pamSettings.getUnitType(); + } + + @Override + public void setTableData(SQLTypes sqlTypes, PamDataUnit pamDataUnit) { + LogXMLDataUnit logXMLDataUnit = (LogXMLDataUnit) pamDataUnit; + PamSettings pamSettings = logXMLDataUnit.getPamSettings(); + + xmlTableDef.getDataStart().setValue(sqlTypes.getTimeStamp(pamDataUnit.getTimeMilliseconds())); + xmlTableDef.getDataEnd().setValue(sqlTypes.getTimeStamp(logXMLDataUnit.getDataEnd())); + xmlTableDef.getProcessStart().setValue(sqlTypes.getTimeStamp(logXMLDataUnit.getProcessTime())); + xmlTableDef.getProcessEnd().setValue(sqlTypes.getTimeStamp(logXMLDataUnit.getProcessEnd())); + xmlTableDef.getName().setValue(pamSettings.getUnitName()); + xmlTableDef.getType().setValue(pamSettings.getUnitType()); + xmlTableDef.getPamGuardVersion().setValue(PamguardVersionInfo.version); + xmlTableDef.getSettingsVersion().setValue(pamSettings.getSettingsVersion()); + xmlTableDef.getXmlSettings().setValue(logXMLDataUnit.getXml()); + } + +} diff --git a/src/generalDatabase/PamTableDefinition.java b/src/generalDatabase/PamTableDefinition.java index 6456671d..fe4c3019 100644 --- a/src/generalDatabase/PamTableDefinition.java +++ b/src/generalDatabase/PamTableDefinition.java @@ -192,14 +192,7 @@ public class PamTableDefinition extends EmptyTableDefinition implements Cloneabl public PamTableItem getUidItem() { return uid; } - public PamConnection getCheckedConnection() { - return checkedConnection; - } - - public void setCheckedConnection(PamConnection checkedConnection) { - this.checkedConnection = checkedConnection; - } - + public PamTableItem getUpdateReference() { return updateReference; } diff --git a/src/generalDatabase/PamTableItem.java b/src/generalDatabase/PamTableItem.java index dc523083..5e206242 100644 --- a/src/generalDatabase/PamTableItem.java +++ b/src/generalDatabase/PamTableItem.java @@ -374,7 +374,7 @@ public class PamTableItem implements Cloneable { * column for use in cross referencing. */ public static PamTableItem findTableItem(String tableName, String columnName) { - PamTableDefinition tableDef = EmptyTableDefinition. + EmptyTableDefinition tableDef = EmptyTableDefinition. findTableDefinition(EmptyTableDefinition.deblankString(tableName)); if (tableDef == null) return null; return tableDef.findTableItem(EmptyTableDefinition.deblankString(columnName)); diff --git a/src/generalDatabase/SQLLogging.java b/src/generalDatabase/SQLLogging.java index 7cbd086d..154e1df1 100644 --- a/src/generalDatabase/SQLLogging.java +++ b/src/generalDatabase/SQLLogging.java @@ -92,7 +92,7 @@ public abstract class SQLLogging { * Reference to the table definition object. * This MUST be set from within the concrete logging class. */ - private PamTableDefinition pamTableDefinition; + private EmptyTableDefinition pamTableDefinition; /** * More and more data blocks are starting to use annotations, which require @@ -102,7 +102,7 @@ public abstract class SQLLogging { * table definition is set, so that it can be got and modified by the * annotation handler shortly after the main table is created. */ - private PamTableDefinition baseTableDefinition; + private EmptyTableDefinition baseTableDefinition; // private long selectT1, selectT2; private PamViewParameters currentViewParameters; @@ -190,7 +190,7 @@ public abstract class SQLLogging { ArrayList blockList = PamController.getInstance() .getDataBlocks(); SQLLogging logger; - PamTableDefinition tableDef; + EmptyTableDefinition tableDef; for (int i = 0; i < blockList.size(); i++) { if ((logger = blockList.get(i).getLogging()) != null) { tableDef = logger.getTableDefinition(); @@ -234,7 +234,7 @@ public abstract class SQLLogging { * @return a Pamguard database table definition object * @see PamTableDefinition */ - public final PamTableDefinition getTableDefinition() { + public final EmptyTableDefinition getTableDefinition() { return pamTableDefinition; } @@ -243,7 +243,7 @@ public abstract class SQLLogging { * * @param pamTableDefinition PamTableDefinition to set */ - public void setTableDefinition(PamTableDefinition pamTableDefinition) { + public void setTableDefinition(EmptyTableDefinition pamTableDefinition) { this.pamTableDefinition = pamTableDefinition; if (baseTableDefinition == null && pamTableDefinition != null) { baseTableDefinition = pamTableDefinition.clone(); @@ -293,37 +293,42 @@ public abstract class SQLLogging { * @param superDetection */ protected void fillTableData(SQLTypes sqlTypes, PamDataUnit pamDataUnit, PamDataUnit superDetection) { + + EmptyTableDefinition emptyTableDef = getTableDefinition(); - PamTableDefinition tableDef = getTableDefinition(); PamTableItem tableItem; - tableDef.getIndexItem().setValue(pamDataUnit.getDatabaseIndex()); - /* - * All tables have a timestamp near the front of the table. And all data - * units have a time in milliseconds, so always fill this in ! - */ - tableDef.getTimeStampItem().setValue( - sqlTypes.getTimeStamp(pamDataUnit.getTimeMilliseconds())); + emptyTableDef.getIndexItem().setValue(pamDataUnit.getDatabaseIndex()); + + if (emptyTableDef instanceof PamTableDefinition) { + PamTableDefinition tableDef = (PamTableDefinition) emptyTableDef; + /* + * All tables have a timestamp near the front of the table. And all data + * units have a time in milliseconds, so always fill this in ! + */ + tableDef.getTimeStampItem().setValue( + sqlTypes.getTimeStamp(pamDataUnit.getTimeMilliseconds())); - tableDef.getTimeStampMillis().setValue((int) (pamDataUnit.getTimeMilliseconds()%1000)); + tableDef.getTimeStampMillis().setValue((int) (pamDataUnit.getTimeMilliseconds()%1000)); - tableDef.getLocalTimeItem().setValue(sqlTypes.getLocalTimeStamp(pamDataUnit.getTimeMilliseconds())); + tableDef.getLocalTimeItem().setValue(sqlTypes.getLocalTimeStamp(pamDataUnit.getTimeMilliseconds())); - tableDef.getPCTimeItem().setValue(sqlTypes.getTimeStamp(System.currentTimeMillis())); + tableDef.getPCTimeItem().setValue(sqlTypes.getTimeStamp(System.currentTimeMillis())); - tableDef.getUidItem().setValue(pamDataUnit.getUID()); + tableDef.getUidItem().setValue(pamDataUnit.getUID()); - tableDef.getChannelBitmap().setValue(pamDataUnit.getChannelBitmap()); + tableDef.getChannelBitmap().setValue(pamDataUnit.getChannelBitmap()); - tableDef.getSequenceBitmap().setValue(pamDataUnit.getSequenceBitmapObject()); + tableDef.getSequenceBitmap().setValue(pamDataUnit.getSequenceBitmapObject()); - if (tableDef.getUpdateReference() != null) { - tableDef.getUpdateReference().setValue(pamDataUnit.getDatabaseIndex()); + if (tableDef.getUpdateReference() != null) { + tableDef.getUpdateReference().setValue(pamDataUnit.getDatabaseIndex()); + } } - for (int i = 0; i < tableDef.getTableItemCount(); i++) { + for (int i = 0; i < emptyTableDef.getTableItemCount(); i++) { - tableItem = tableDef.getTableItem(i); + tableItem = emptyTableDef.getTableItem(i); // if (tableItem.isCounter()) { // tableItem.setValue(1); // } @@ -333,8 +338,8 @@ public abstract class SQLLogging { } } - if (tableDef instanceof PamSubtableDefinition) { - PamSubtableDefinition subTableDef = (PamSubtableDefinition) tableDef; + if (emptyTableDef instanceof PamSubtableDefinition) { + PamSubtableDefinition subTableDef = (PamSubtableDefinition) emptyTableDef; fillSubTableData(subTableDef, pamDataUnit, superDetection); } @@ -525,7 +530,7 @@ public abstract class SQLLogging { } // now put some sql into the statement // if (resultSet == null) { - PamTableDefinition tableDef = getTableDefinition(); + EmptyTableDefinition tableDef = getTableDefinition(); String sqlString = tableDef.getSQLSelectString(con.getSqlTypes()); // sqlString = "select \"comment\" from userinput"; try { @@ -1067,7 +1072,7 @@ public abstract class SQLLogging { public boolean transferDataFromResult(SQLTypes sqlTypes, ResultSet resultSet) { - PamTableDefinition tableDef = getTableDefinition(); + EmptyTableDefinition tableDef = getTableDefinition(); PamTableItem tableItem; try { for (int i = 0; i < tableDef.getTableItemCount(); i++) { @@ -1078,17 +1083,20 @@ public abstract class SQLLogging { // Timestamp ts = (Timestamp) getTableDefinition().getTimeStampItem().getValue(); // Timestamp ts = getTableDefinition().getTimeStampItem().getTimestampValue(); // lastTime = sqlTypes.millisFromTimeStamp(ts); - lastTime = sqlTypes.millisFromTimeStamp(getTableDefinition().getTimeStampItem().getValue()); - if (lastTime%1000 == 0) { - // some databases may have stored the milliseconds, in which - // case this next bit is redundant. - lastTime += getTableDefinition().getTimeStampMillis().getIntegerValue(); - } - lastLoadIndex = getTableDefinition().getIndexItem().getIntegerValue(); - lastLoadUID = getTableDefinition().getUidItem().getLongObject(); - lastChannelBitmap = getTableDefinition().getChannelBitmap().getIntegerValue(); - lastSequenceBitmap = getTableDefinition().getSequenceBitmap().getIntegerObject(); + if (tableDef instanceof PamTableDefinition) { + PamTableDefinition pamTableDef = (PamTableDefinition) tableDef; + lastTime = sqlTypes.millisFromTimeStamp(pamTableDef.getTimeStampItem().getValue()); + if (lastTime%1000 == 0) { + // some databases may have stored the milliseconds, in which + // case this next bit is redundant. + lastTime += pamTableDef.getTimeStampMillis().getIntegerValue(); + } + + lastLoadUID = pamTableDef.getUidItem().getLongObject(); + lastChannelBitmap = pamTableDef.getChannelBitmap().getIntegerValue(); + lastSequenceBitmap = pamTableDef.getSequenceBitmap().getIntegerObject(); + } return true; } catch (SQLException ex) { @@ -1745,7 +1753,7 @@ public abstract class SQLLogging { * annotation handler shortly after the main table is created. * @return the baseTableDefinition */ - public PamTableDefinition getBaseTableDefinition() { + public EmptyTableDefinition getBaseTableDefinition() { return baseTableDefinition; } diff --git a/src/generalDatabase/SQLLoggingAddon.java b/src/generalDatabase/SQLLoggingAddon.java index 6d347fb4..ff8bd561 100644 --- a/src/generalDatabase/SQLLoggingAddon.java +++ b/src/generalDatabase/SQLLoggingAddon.java @@ -15,7 +15,7 @@ public interface SQLLoggingAddon { * Add a load of columns to an existing table definition * @param pamTableDefinition */ - public void addTableItems(PamTableDefinition pamTableDefinition); + public void addTableItems(EmptyTableDefinition pamTableDefinition); /** * Save data - that is transfer data from the pamDataUnit to the data objects @@ -24,7 +24,7 @@ public interface SQLLoggingAddon { * @param pamDataUnit data unit * @return true if successful */ - public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit); + public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit); /** * Load data - that is read data from the table definition and turn it into something sensible @@ -33,7 +33,7 @@ public interface SQLLoggingAddon { * @param pamDataUnit data unit * @return true if successful */ - public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit); + public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit); /** * Get a name for the SQLLogging Addon. this is used diff --git a/src/generalDatabase/XMLSettingsTableDefinition.java b/src/generalDatabase/XMLSettingsTableDefinition.java new file mode 100644 index 00000000..d09b8f05 --- /dev/null +++ b/src/generalDatabase/XMLSettingsTableDefinition.java @@ -0,0 +1,94 @@ +package generalDatabase; + +import java.sql.Types; + +import PamguardMVC.PamConstants; + +public class XMLSettingsTableDefinition extends EmptyTableDefinition { + + private PamTableItem dataStart, dataEnd, processStart, processEnd, type, name, pamGuardVersion, settingsVersion, xmlSettings; + + public XMLSettingsTableDefinition(String tableName) { + super(tableName, SQLLogging.UPDATE_POLICY_WRITENEW); + pamTableItems.add(dataStart = new PamTableItem("Data Start", Types.TIMESTAMP, "Data start time")); + pamTableItems.add(dataEnd = new PamTableItem("Data End", Types.TIMESTAMP, "Data end time")); + pamTableItems.add(processStart = new PamTableItem("Process Start", Types.TIMESTAMP, "Process start time")); + pamTableItems.add(processEnd = new PamTableItem("Process End", Types.TIMESTAMP, "Process end time")); + addTableItem(type = new PamTableItem("unitType", Types.CHAR, PamConstants.MAX_ITEM_NAME_LENGTH)); + addTableItem(name = new PamTableItem("unitName", Types.CHAR, PamConstants.MAX_ITEM_NAME_LENGTH)); + addTableItem(pamGuardVersion = new PamTableItem("PAMGuardVersion", Types.INTEGER)); + addTableItem(settingsVersion = new PamTableItem("SettingsVersion", Types.INTEGER)); + addTableItem(xmlSettings = new PamTableItem("XMLSettings", Types.VARCHAR)); + setUseCheatIndexing(false); + } + + + /** + * @return the dataStart + */ + public PamTableItem getDataStart() { + return dataStart; + } + + + /** + * @return the dataEnd + */ + public PamTableItem getDataEnd() { + return dataEnd; + } + + + /** + * @return the processStart + */ + public PamTableItem getProcessStart() { + return processStart; + } + + + /** + * @return the processEnd + */ + public PamTableItem getProcessEnd() { + return processEnd; + } + + + /** + * @return the type + */ + public PamTableItem getType() { + return type; + } + + /** + * @return the name + */ + public PamTableItem getName() { + return name; + } + + /** + * @return the pamGuardVersion + */ + public PamTableItem getPamGuardVersion() { + return pamGuardVersion; + } + + /** + * @return the settingsVersion + */ + public PamTableItem getSettingsVersion() { + return settingsVersion; + } + + /** + * @return the xmlSettings + */ + public PamTableItem getXmlSettings() { + return xmlSettings; + } + + +} diff --git a/src/gpl/io/GPLLogging.java b/src/gpl/io/GPLLogging.java index d8817bdc..c407193f 100644 --- a/src/gpl/io/GPLLogging.java +++ b/src/gpl/io/GPLLogging.java @@ -5,6 +5,7 @@ import java.sql.Types; import PamDetection.AcousticSQLLogging; import PamguardMVC.PamDataBlock; import PamguardMVC.PamDataUnit; +import generalDatabase.EmptyTableDefinition; import generalDatabase.PamTableDefinition; import generalDatabase.PamTableItem; import generalDatabase.SQLTypes; @@ -22,7 +23,7 @@ public class GPLLogging extends AcousticSQLLogging { super(gplDetectionBlock, gplControlledUnit.getUnitName() + " Detections"); this.gplControlledUnit = gplControlledUnit; - PamTableDefinition pamTable = getTableDefinition(); + EmptyTableDefinition pamTable = getTableDefinition(); pamTable.addTableItem(peakValue = new PamTableItem("PeakValue", Types.REAL)); pamTable.addTableItem(contourArea = new PamTableItem("ContourArea", Types.REAL)); } diff --git a/src/loc3d_Thode/TowedArray3DSQLLogging.java b/src/loc3d_Thode/TowedArray3DSQLLogging.java index c5a8b1f7..108c000c 100644 --- a/src/loc3d_Thode/TowedArray3DSQLLogging.java +++ b/src/loc3d_Thode/TowedArray3DSQLLogging.java @@ -1,5 +1,6 @@ package loc3d_Thode; +import generalDatabase.EmptyTableDefinition; import generalDatabase.PamDetectionLogging; import generalDatabase.PamTableDefinition; import generalDatabase.PamTableItem; @@ -17,7 +18,6 @@ public class TowedArray3DSQLLogging extends PamDetectionLogging { TowedArray3DController towedArray3DController; - PamTableDefinition tableDefinition; PamTableItem dateItem, range_boat_Item, range_f_Item, range_r_Item, depthItem, azi_boat_Item,azi_f_Item, azi_r_Item, tdd_Item, bearing_f_Item,bearing_r_Item, tds_f_Item, tds_r_Item, za_f_Item, za_r_Item; @@ -34,14 +34,14 @@ public class TowedArray3DSQLLogging extends PamDetectionLogging { this.towedArray3DController = towedArray3DController; // create the table definition. - tableDefinition = createTableDefinition(); + EmptyTableDefinition tableDefinition = createTableDefinition(); } - public PamTableDefinition createTableDefinition() { + public EmptyTableDefinition createTableDefinition() { // PamTableDefinition tableDef = new PamTableDefinition(towedArray3DController.getUnitName(), getUpdatePolicy()); - PamTableDefinition tableDef = super.getTableDefinition(); + EmptyTableDefinition tableDef = super.getTableDefinition(); tableDef.setUpdatePolicy(SQLLogging.UPDATE_POLICY_WRITENEW); // PamTableItem tableItem; diff --git a/src/matchedTemplateClassifer/annotation/MatchedClickAnnotationSQL.java b/src/matchedTemplateClassifer/annotation/MatchedClickAnnotationSQL.java index acf38f67..3b248ea9 100644 --- a/src/matchedTemplateClassifer/annotation/MatchedClickAnnotationSQL.java +++ b/src/matchedTemplateClassifer/annotation/MatchedClickAnnotationSQL.java @@ -7,6 +7,7 @@ import java.util.List; import PamUtils.PamArrayUtils; import PamguardMVC.PamDataUnit; import PamguardMVC.debug.Debug; +import generalDatabase.EmptyTableDefinition; import generalDatabase.PamTableDefinition; import generalDatabase.PamTableItem; import generalDatabase.SQLLoggingAddon; @@ -49,7 +50,7 @@ public class MatchedClickAnnotationSQL implements SQLLoggingAddon { } @Override - public void addTableItems(PamTableDefinition pamTableDefinition) { + public void addTableItems(EmptyTableDefinition pamTableDefinition) { pamTableDefinition.addTableItem(typeTable); pamTableDefinition.addTableItem(mtThresholdsTable); pamTableDefinition.addTableItem(mtMatchCorrsTable); @@ -58,7 +59,7 @@ public class MatchedClickAnnotationSQL implements SQLLoggingAddon { } @Override - public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { + public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { MatchedClickAnnotation clickAnnotation = (MatchedClickAnnotation) pamDataUnit.findDataAnnotation(MatchedClickAnnotation.class); @@ -95,7 +96,7 @@ public class MatchedClickAnnotationSQL implements SQLLoggingAddon { } @Override - public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { + public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { String threshold = mtThresholdsTable.getDeblankedStringValue(); String mtMatchCorrs = mtMatchCorrsTable.getDeblankedStringValue(); diff --git a/src/nidaqdev/networkdaq/NIDaqLogging.java b/src/nidaqdev/networkdaq/NIDaqLogging.java index dc12309b..75022e5c 100644 --- a/src/nidaqdev/networkdaq/NIDaqLogging.java +++ b/src/nidaqdev/networkdaq/NIDaqLogging.java @@ -3,6 +3,7 @@ package nidaqdev.networkdaq; import java.sql.Types; import PamguardMVC.PamDataUnit; +import generalDatabase.EmptyTableDefinition; import generalDatabase.PamTableDefinition; import generalDatabase.PamTableItem; import generalDatabase.SQLLoggingAddon; @@ -20,12 +21,12 @@ public class NIDaqLogging implements SQLLoggingAddon { } @Override - public void addTableItems(PamTableDefinition pamTableDefinition) { + public void addTableItems(EmptyTableDefinition pamTableDefinition) { pamTableDefinition.addTableItem(crioTemperature); } @Override - public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { + public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { Double lastTemp = niNetworkDaq.getLastTemperature(); if (lastTemp == null) { crioTemperature.setValue(null); @@ -38,7 +39,7 @@ public class NIDaqLogging implements SQLLoggingAddon { } @Override - public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { + public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { // TODO Auto-generated method stub return false; } diff --git a/src/rawDeepLearningClassifier/logging/DLAnnotationSQL.java b/src/rawDeepLearningClassifier/logging/DLAnnotationSQL.java index 72761199..b046b27b 100644 --- a/src/rawDeepLearningClassifier/logging/DLAnnotationSQL.java +++ b/src/rawDeepLearningClassifier/logging/DLAnnotationSQL.java @@ -1,6 +1,7 @@ package rawDeepLearningClassifier.logging; import PamguardMVC.PamDataUnit; +import generalDatabase.EmptyTableDefinition; import generalDatabase.PamTableDefinition; import generalDatabase.SQLLoggingAddon; import generalDatabase.SQLTypes; @@ -12,19 +13,19 @@ public class DLAnnotationSQL implements SQLLoggingAddon { } @Override - public void addTableItems(PamTableDefinition pamTableDefinition) { + public void addTableItems(EmptyTableDefinition pamTableDefinition) { // TODO Auto-generated method stub } @Override - public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { + public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { // TODO Auto-generated method stub return false; } @Override - public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { + public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { // TODO Auto-generated method stub return false; } diff --git a/src/targetMotionOld/TargetMotionSQLLogging.java b/src/targetMotionOld/TargetMotionSQLLogging.java index 6017a12b..4f4f133e 100644 --- a/src/targetMotionOld/TargetMotionSQLLogging.java +++ b/src/targetMotionOld/TargetMotionSQLLogging.java @@ -15,6 +15,7 @@ import PamDetection.AbstractLocalisation; import PamDetection.LocContents; import PamUtils.LatLong; import PamguardMVC.PamDataUnit; +import generalDatabase.EmptyTableDefinition; import generalDatabase.PamTableDefinition; import generalDatabase.PamTableItem; import generalDatabase.SQLLoggingAddon; @@ -119,7 +120,7 @@ public class TargetMotionSQLLogging implements SQLLoggingAddon { } @Override - public void addTableItems(PamTableDefinition pamTableDefinition) { + public void addTableItems(EmptyTableDefinition pamTableDefinition) { pamTableDefinition.addTableItem(modelName); @@ -146,7 +147,7 @@ public class TargetMotionSQLLogging implements SQLLoggingAddon { } @Override - public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, + public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { AbstractLocalisation tmResult = pamDataUnit.getLocalisation(); clearEverything(); @@ -218,7 +219,7 @@ public class TargetMotionSQLLogging implements SQLLoggingAddon { return true; } - private boolean saveGroupLocalisation(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, + private boolean saveGroupLocalisation(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit, GroupLocalisation groupLocalisation) { int nAmbiguities = groupLocalisation.getAmbiguityCount(); @@ -239,7 +240,7 @@ public class TargetMotionSQLLogging implements SQLLoggingAddon { return true; } - private boolean saveGroupLocalisation(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, + private boolean saveGroupLocalisation(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit, int resultIndex, GroupLocResult tmResult) { @@ -323,7 +324,7 @@ public class TargetMotionSQLLogging implements SQLLoggingAddon { } @Override - public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, + public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) { GroupLocalisation tml = new GroupLocalisation(pamDataUnit, null); @@ -341,7 +342,7 @@ public class TargetMotionSQLLogging implements SQLLoggingAddon { return true; } - private GroupLocResult loadLocResult(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, + private GroupLocResult loadLocResult(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit, GroupLocalisation tml, int resultIndex) { double latVal, longVal; diff --git a/src/whistleDetector/WhistleLogger.java b/src/whistleDetector/WhistleLogger.java index 0bbb03d7..34345e88 100644 --- a/src/whistleDetector/WhistleLogger.java +++ b/src/whistleDetector/WhistleLogger.java @@ -1,5 +1,6 @@ package whistleDetector; +import generalDatabase.EmptyTableDefinition; import generalDatabase.PamDetectionLogging; import generalDatabase.PamTableDefinition; import generalDatabase.PamTableItem; @@ -24,7 +25,7 @@ public class WhistleLogger extends PamDetectionLogging { this.whistleControl = whistleControl; - PamTableDefinition tableDefinition = getTableDefinition(); + EmptyTableDefinition tableDefinition = getTableDefinition(); tableDefinition.addTableItem(sliceCount = new PamTableItem("SliceCount", Types.INTEGER)); tableDefinition.addTableItem(length = new PamTableItem("WhistleLength", Types.DOUBLE)); tableDefinition.addTableItem(minFreq = new PamTableItem("MinFreq", Types.DOUBLE)); From 5e6cd42eea0d02cf150f35ef604d054f6f3f4a41 Mon Sep 17 00:00:00 2001 From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com> Date: Thu, 15 Dec 2022 18:21:17 +0000 Subject: [PATCH 3/5] Tethys Export A bit of fun writing some outline functions to export data to Tethys. --- src/PamModel/PamModel.java | 8 + src/generalDatabase/DBSchemaWriter.java | 28 ++- src/tethys/TethysControl.java | 82 +++++++++ src/tethys/TethysExporter.java | 133 ++++++++++++++ src/tethys/output/StreamExportParams.java | 27 +++ src/tethys/output/TethysExportParams.java | 54 ++++++ .../output/swing/TethysExportDialog.java | 171 ++++++++++++++++++ 7 files changed, 496 insertions(+), 7 deletions(-) create mode 100644 src/tethys/TethysControl.java create mode 100644 src/tethys/TethysExporter.java create mode 100644 src/tethys/output/StreamExportParams.java create mode 100644 src/tethys/output/TethysExportParams.java create mode 100644 src/tethys/output/swing/TethysExportDialog.java diff --git a/src/PamModel/PamModel.java b/src/PamModel/PamModel.java index 00be884a..5c467719 100644 --- a/src/PamModel/PamModel.java +++ b/src/PamModel/PamModel.java @@ -49,6 +49,7 @@ import networkTransfer.receive.BuoyStatusDataUnit; import networkTransfer.receive.NetworkReceiver; import printscreen.PrintScreenControl; import rockBlock.RockBlockControl; +import tethys.TethysControl; import turbineops.TurbineOperationControl; import GPS.GpsDataUnit; import Map.MapController; @@ -459,6 +460,13 @@ final public class PamModel implements PamModelInterface, PamSettings { mi.setToolTipText("Manage automated data backups"); mi.setModulesMenuGroup(utilitiesGroup); mi.setMaxNumber(1); + + if (isViewer) { + mi = PamModuleInfo.registerControlledUnit(TethysControl.class.getName(), TethysControl.defaultName); + mi.setToolTipText("Interface to Tethys Database"); + mi.setModulesMenuGroup(utilitiesGroup); + mi.setMaxNumber(1); + } diff --git a/src/generalDatabase/DBSchemaWriter.java b/src/generalDatabase/DBSchemaWriter.java index 213601fe..a29a90b5 100644 --- a/src/generalDatabase/DBSchemaWriter.java +++ b/src/generalDatabase/DBSchemaWriter.java @@ -63,13 +63,14 @@ public class DBSchemaWriter { return true; } - private void exportDatabaseSchema(File outputFolder, PamDataBlock dataBlock, SQLLogging logging, EmptyTableDefinition tableDef) { - - /** - * write a parent item, e.g. if tableDef is a sub class of PamTableDefinition - */ - // String parentName = writeParentTableSchema(outputFolder, dataBlock, tableDef); - + /** + * Generate an xml schema for a datablock. + * @param dataBlock + * @param logging + * @param tableDef + * @return + */ + public Document generateDatabaseSchema(PamDataBlock dataBlock, SQLLogging logging, EmptyTableDefinition tableDef) { String tableName = tableDef.getTableName(); Document doc = PamUtils.XMLUtils.createBlankDoc(); Element schemaEl = doc.createElement("xs:schema"); @@ -95,7 +96,20 @@ public class DBSchemaWriter { } } } + return doc; + } + + private void exportDatabaseSchema(File outputFolder, PamDataBlock dataBlock, SQLLogging logging, EmptyTableDefinition tableDef) { + /** + * write a parent item, e.g. if tableDef is a sub class of PamTableDefinition + */ + // String parentName = writeParentTableSchema(outputFolder, dataBlock, tableDef); + + Document doc = generateDatabaseSchema(dataBlock, logging, tableDef); + + String tableName = tableDef.getTableName(); + try { File outputFile = new File(outputFolder, tableName+".xsd"); XMLUtils.writeToFile(doc, outputFile); diff --git a/src/tethys/TethysControl.java b/src/tethys/TethysControl.java new file mode 100644 index 00000000..dc0a46f2 --- /dev/null +++ b/src/tethys/TethysControl.java @@ -0,0 +1,82 @@ +package tethys; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; + +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuItem; + +import PamController.PamControlledUnit; +import PamController.PamController; +import PamguardMVC.PamDataBlock; +import tethys.output.StreamExportParams; +import tethys.output.TethysExportParams; +import tethys.output.swing.TethysExportDialog; + +/** + * Quick play with a simple system for outputting data to Tethys. At it's start + * this is simply going to offer a dialog and have a few functions which show how + * to access data within PAMGuard. + * @author dg50 + * + */ +public class TethysControl extends PamControlledUnit { + + public static final String unitType = "Tethys Interface"; + public static String defaultName = "Tethys"; + + + private TethysExportParams tethysExportParams = new TethysExportParams(); + + + public TethysControl(String unitName) { + super(unitType, unitName); + } + + @Override + public JMenuItem createFileMenu(JFrame parentFrame) { + JMenu tethysMenu = new JMenu("Tethys"); + JMenuItem tethysExport = new JMenuItem("Export ..."); + tethysMenu.add(tethysExport); + tethysExport.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + tethysExport(parentFrame); + } + }); + return tethysMenu; + } + + /** + * @return the tethysExportParams + */ + public TethysExportParams getTethysExportParams() { + return tethysExportParams; + } + + /** + * We'll probably want to + * @param parentFrame + */ + protected void tethysExport(JFrame parentFrame) { + TethysExportParams newExportParams = TethysExportDialog.showDialog(parentFrame, this); + if (newExportParams != null) { + // dialog returns null if cancel was pressed. + tethysExportParams = newExportParams; + exportTethysData(tethysExportParams); + } + } + + /** + * We'll arrive here if the dialog has been opened and we want to export Tethys data. + * @param tethysExportParams2 + */ + private void exportTethysData(TethysExportParams tethysExportParams) { + TethysExporter tethysExporter = new TethysExporter(this, tethysExportParams); + tethysExporter.doExport(); + } + +} diff --git a/src/tethys/TethysExporter.java b/src/tethys/TethysExporter.java new file mode 100644 index 00000000..6dc816a0 --- /dev/null +++ b/src/tethys/TethysExporter.java @@ -0,0 +1,133 @@ +package tethys; + +import java.util.ArrayList; + +import org.w3c.dom.Document; + +import PamController.PamControlledUnit; +import PamController.PamController; +import PamController.settings.output.xml.PamguardXMLWriter; +import PamguardMVC.PamDataBlock; +import generalDatabase.DBSchemaWriter; +import generalDatabase.SQLLogging; +import tethys.output.StreamExportParams; +import tethys.output.TethysExportParams; + +public class TethysExporter { + + private TethysControl tethysControl; + private TethysExportParams tethysExportParams; + + public TethysExporter(TethysControl tethysControl, TethysExportParams tethysExportParams) { + this.tethysControl = tethysControl; + this.tethysExportParams = tethysExportParams; + } + + /** + * Does the work. In reality this will need an awful lot of changing, for instance + * to provide feedback to an observer class to show progress on the display. + * @return OK if success. + */ + public boolean doExport() { + /* + * Call some general export function + */ + exportGeneralData(tethysExportParams); + /* + * go through the export params and call something for every + * data block that's enabled. + */ + ArrayList allDataBlocks = PamController.getInstance().getDataBlocks(); + for (PamDataBlock aDataBlock : allDataBlocks) { + StreamExportParams streamExportParams = tethysExportParams.getStreamParams(aDataBlock); + if (streamExportParams == null || streamExportParams.selected == false) { + continue; // not interested in this one. + } + exportDataStream(aDataBlock, tethysExportParams, streamExportParams); + } + /* + * Then do whatever else is needed to complete the document. + */ + + return true; + } + + /** + * No idea if we need this or not. May want to return something different to void, e.g. + * a reference to the main object for a tethys export. I've no idea ! + * @param tethysExportParams2 + */ + private void exportGeneralData(TethysExportParams tethysExportParams) { + // TODO Auto-generated method stub + + } + + /** + * Here is where we export data for a specific data stream to Tethys. + * + * @param aDataBlock + * @param tethysExportParams + * @param streamExportParams + */ + private void exportDataStream(PamDataBlock aDataBlock, TethysExportParams tethysExportParams, + StreamExportParams streamExportParams) { + /** + * This will probably need to be passed additional parameters and may also want to return something + * other than void in order to build a bigger Tethys document. + */ + /* + * Some examples of how to do whatever is needed to get schema and data out of PAMGuard. + */ + /* + * first we'll probably want a reference to the module containing the data. + * in principle this can't get null, since the datablock was found be searching in + * the other direction. + */ + PamControlledUnit pamControlledUnit = aDataBlock.getParentProcess().getPamControlledUnit(); + /* + * Get the XML settings for that datablock. + */ + PamguardXMLWriter pamXMLWriter = PamguardXMLWriter.getXMLWriter(); + Document doc = pamXMLWriter.writeOneModule(pamXMLWriter, System.currentTimeMillis()); + String moduleXML = null; + if (doc != null) { + // this string should be XML of all the settings for the module controlling this datablock. + moduleXML = pamXMLWriter.getAsString(doc, true); // change to false to get smaller xml + System.out.printf("Module settings for datablock %s are:\n", moduleXML); + System.out.println(moduleXML); + } + /* + * This also should never be null, because we only selected datablocks that had a database + * interface. + * Future versions may need to change this to use binary stores. This will require + * the overriding datablock to return something different to SQLLogging - probably a TethysLogging + * interface, which can probably by default just wrap the SQLLogging , but does allow the + * option of modifying behaviour and of making something work for binary stores. + */ + SQLLogging logging = aDataBlock.getLogging(); + if (logging == null) return; + /** + * From the logging, it's possible to automatically generate a XML schema. This may not + * be entirely right, but will be easy to fix. + */ + DBSchemaWriter schemaWriter = new DBSchemaWriter(); + Document schemaDoc = schemaWriter.generateDatabaseSchema(aDataBlock, logging, logging.getTableDefinition()); + String schemaXML = null; + if (schemaDoc != null) { + schemaXML = pamXMLWriter.getAsString(schemaDoc, true); + } + System.out.printf("Database schema for Module Type %s Name %s are:\n", pamControlledUnit.getUnitType(), pamControlledUnit.getUnitName()); + System.out.println(schemaXML); + + /** + * Now can go through the data. Probably, we'll want to go through all the data in + * the project, but we can hold off on that for now and just go for data that + * are in memory. We'll also have to think a lot about updating parts of the + * database which have been reprocessed - what we want to do, should eventually all + * be options set in the dialog and available within TethysExportParams + * For now though, we're just going to export data that are in memory. + */ + + } + +} diff --git a/src/tethys/output/StreamExportParams.java b/src/tethys/output/StreamExportParams.java new file mode 100644 index 00000000..b19af599 --- /dev/null +++ b/src/tethys/output/StreamExportParams.java @@ -0,0 +1,27 @@ +package tethys.output; + +import java.io.Serializable; + +/** + * Parameters controlling export of a single stream. + * Starts just with a boolean 'selected', but may grow. + * These all contain data names rather than references to a Datablock so that + * they can be serialised. + * @author dg50 + * + */ +public class StreamExportParams implements Serializable { + + public static final long serialVersionUID = 1L; + + public StreamExportParams(String longDataName, boolean selected) { + super(); + this.longDataName = longDataName; + this.selected = selected; + } + + public String longDataName; + + public boolean selected; + +} diff --git a/src/tethys/output/TethysExportParams.java b/src/tethys/output/TethysExportParams.java new file mode 100644 index 00000000..6b43d0df --- /dev/null +++ b/src/tethys/output/TethysExportParams.java @@ -0,0 +1,54 @@ +package tethys.output; + +import java.io.Serializable; +import java.util.HashMap; + +import PamguardMVC.PamDataBlock; + +public class TethysExportParams implements Serializable, Cloneable{ + + public static final long serialVersionUID = 1L; + + /* + * Need to add lots of other parameters here, such as the connection detils + * for the tethys database. + */ + + private HashMap streamParamsMap = new HashMap(); + + @Override + public TethysExportParams clone() { + try { + return (TethysExportParams) super.clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + return null; + } + } + + /** + * Set stream export parameters for a given datablock. + * @param dataBlock + * @param exportParams + */ + public void setStreamParams(PamDataBlock dataBlock, StreamExportParams exportParams) { + setStreamParams(dataBlock.getLongDataName(), exportParams); + } + /** + * Set stream export parameters for a given data name. + * @param dataBlock + * @param exportParams + */ + public void setStreamParams(String longDataName, StreamExportParams exportParams) { + streamParamsMap.put(longDataName, exportParams); + } + + public StreamExportParams getStreamParams(PamDataBlock dataBlock) { + return getStreamParams(dataBlock.getLongDataName()); + } + + private StreamExportParams getStreamParams(String longDataName) { + return streamParamsMap.get(longDataName); + } + +} diff --git a/src/tethys/output/swing/TethysExportDialog.java b/src/tethys/output/swing/TethysExportDialog.java new file mode 100644 index 00000000..d9477c52 --- /dev/null +++ b/src/tethys/output/swing/TethysExportDialog.java @@ -0,0 +1,171 @@ +package tethys.output.swing; + +import java.awt.BorderLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Window; +import java.util.ArrayList; + +import javax.swing.JCheckBox; +import javax.swing.JPanel; +import javax.swing.border.TitledBorder; + +import PamController.PamController; +import PamView.dialog.PamDialog; +import PamView.dialog.PamGridBagContraints; +import PamguardMVC.PamDataBlock; +import tethys.TethysControl; +import tethys.output.StreamExportParams; +import tethys.output.TethysExportParams; + +/** + * Start of a dialog for controlling the export of Tethys data. For first iteration + * this will just be a list of output streams (PamDataBlocks) which have a database + * connection. Each will have a checkbox. On OK it will return back a class listing + * what to output and the calling function can do as it will. Future versions will + * probably want to push the functionality into a SwingWorker to show progress, etc. + * but that can come later. + * + * Normally, I use single instance dialogs for this sort of thing. + * @author dg50 + * + */ +public class TethysExportDialog extends PamDialog { + + private static TethysExportDialog singleInstance; + + private TethysControl tethysControl; + + private TethysExportParams exportParams; + + private JPanel streamsPanel; + + private ArrayList dataStreamSets = new ArrayList<>(); + + private TethysExportDialog(Window parentFrame, TethysControl tethysControl) { + super(parentFrame, "Tethys Export", false); + this.tethysControl = tethysControl; + + JPanel mainPanel = new JPanel(new BorderLayout()); + /* + * Expect to add at least one more panel at the top of this to have options + * for things like connection details to the database. If not another panel, + * then they can be arranged on tabs, as a wizard, etc. + */ + streamsPanel = new JPanel(); + streamsPanel.setBorder(new TitledBorder("Data Streams")); + mainPanel.add(BorderLayout.CENTER, streamsPanel); + + setDialogComponent(mainPanel); + setResizable(true); + + } + + public static TethysExportParams showDialog(Window parentFrame, TethysControl tethysControl) { + if (singleInstance == null || singleInstance.getOwner() != parentFrame || singleInstance.tethysControl != tethysControl) { + singleInstance = new TethysExportDialog(parentFrame, tethysControl); + } + singleInstance.makeStreamsPanel(); + singleInstance.setParams(); + singleInstance.setVisible(true); + return singleInstance.exportParams; + } + + + /** + * remake the panel. Gets rebuilt whenever dialog opens in case + * the list of available data has changed. + */ + private void makeStreamsPanel() { + streamsPanel.removeAll(); + streamsPanel.setLayout(new GridBagLayout()); + GridBagConstraints c = new PamGridBagContraints(); + dataStreamSets = findDataStreams(); + for (DataStreamSet aSet : dataStreamSets) { + streamsPanel.add(aSet.checkBox, c); + c.gridy++; + } + pack(); + } + + /** + * Get a set of data blocks that have SQLLogging. + * @return + */ + private ArrayList findDataStreams() { + ArrayList sets = new ArrayList<>(); + ArrayList allDataBlocks = PamController.getInstance().getDataBlocks(); + for (PamDataBlock aDataBlock : allDataBlocks) { + if (aDataBlock.getLogging() != null) { + sets.add(new DataStreamSet(aDataBlock)); + } + } + return sets; + } + + private void setParams() { + this.exportParams = tethysControl.getTethysExportParams(); + if (exportParams == null) { + exportParams = new TethysExportParams(); + } + else { + exportParams = exportParams.clone(); + } + setParams(exportParams); + } + + private void setParams(TethysExportParams exportParams) { + if (exportParams == null || dataStreamSets == null) { + return; + } + for (DataStreamSet streamSet : dataStreamSets) { + StreamExportParams streamOpts = exportParams.getStreamParams(streamSet.dataBlock); + if (streamOpts == null) { + continue; + } + streamSet.checkBox.setSelected(streamOpts.selected); + } + + } + + @Override + public boolean getParams() { + if (exportParams == null || dataStreamSets == null) { + return false; + } + int nSel = 0; + for (DataStreamSet streamSet : dataStreamSets) { + StreamExportParams streamOpts = new StreamExportParams(streamSet.dataBlock.getLongDataName(), streamSet.checkBox.isSelected()); + exportParams.setStreamParams(streamSet.dataBlock, streamOpts); + nSel++; + } + return nSel > 0; + } + + @Override + public void cancelButtonPressed() { + exportParams = null; + } + + @Override + public void restoreDefaultSettings() { + // TODO Auto-generated method stub + + } + + private class DataStreamSet { + + private PamDataBlock dataBlock; + + private JCheckBox checkBox; + + public DataStreamSet(PamDataBlock dataBlock) { + super(); + this.dataBlock = dataBlock; + checkBox = new JCheckBox(dataBlock.getDataName()); + checkBox.setToolTipText(dataBlock.getLongDataName()); + } + + + } +} From f02001a6fc2d721966f7e0f86410cb6af26ef762 Mon Sep 17 00:00:00 2001 From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com> Date: Wed, 25 Jan 2023 16:40:03 +0000 Subject: [PATCH 4/5] Changes for Tethys integration --- .classpath | 7 +- pom.xml | 23 +- src/PamModel/PamModel.java | 7 + .../parametermanager/PamParameterData.java | 52 +++- .../PamParameterDataGetter.java | 7 +- .../parametermanager/PamParameterSet.java | 1 + .../parametermanager/ParameterSetManager.java | 73 +++++ .../PrivatePamParameterData.java | 42 ++- .../swing/ManagedParameterDialog.java | 49 ++++ .../swing/ManagedParameterPanel.java | 149 ++++++++++ .../ParameterDatabaseStore.java | 187 ++++++++++++ src/metadata/MetaDataContol.java | 30 ++ src/metadata/deployment/DeploymentData.java | 266 ++++++++++++++++++ src/metadata/deployment/QAData.java | 40 +++ src/tethys/TethysControl.java | 15 + src/tethys/deployment/DeploymentWrapper.java | 85 ++++++ src/tethys/deployment/PamDeployment.java | 64 +++++ src/tethys/exchange/TethysExchange.java | 5 + 18 files changed, 1096 insertions(+), 6 deletions(-) create mode 100644 src/PamModel/parametermanager/ParameterSetManager.java create mode 100644 src/PamModel/parametermanager/swing/ManagedParameterDialog.java create mode 100644 src/PamModel/parametermanager/swing/ManagedParameterPanel.java create mode 100644 src/generalDatabase/parameterstore/ParameterDatabaseStore.java create mode 100644 src/metadata/MetaDataContol.java create mode 100644 src/metadata/deployment/DeploymentData.java create mode 100644 src/metadata/deployment/QAData.java create mode 100644 src/tethys/deployment/DeploymentWrapper.java create mode 100644 src/tethys/deployment/PamDeployment.java create mode 100644 src/tethys/exchange/TethysExchange.java diff --git a/.classpath b/.classpath index 26c568d7..daee38d4 100644 --- a/.classpath +++ b/.classpath @@ -6,7 +6,7 @@ - + @@ -17,5 +17,10 @@ + + + + + diff --git a/pom.xml b/pom.xml index 62ccf835..b0c17c13 100644 --- a/pom.xml +++ b/pom.xml @@ -555,8 +555,29 @@ com.sun.xml.bind jaxb-impl 2.3.2 + --> + + + org.eclipse.persistence + org.eclipse.persistence.moxy + 2.5.0 + + + javax.xml.bind + jaxb-api + 2.4.0-b180830.0359 - --> + + org.glassfish.jaxb + jaxb-runtime + 2.4.0-b180830.0438 + + + org.glassfish.jaxb + jaxb-xjc + 2.4.0-b180830.0438 + + diff --git a/src/PamModel/PamModel.java b/src/PamModel/PamModel.java index 5c467719..005c16d0 100644 --- a/src/PamModel/PamModel.java +++ b/src/PamModel/PamModel.java @@ -44,6 +44,7 @@ import whistlesAndMoans.AbstractWhistleDataUnit; import fftManager.FFTDataUnit; import fftManager.PamFFTControl; import group3dlocaliser.Group3DLocaliserControl; +import metadata.MetaDataContol; import meygenturbine.MeygenTurbine; import networkTransfer.receive.BuoyStatusDataUnit; import networkTransfer.receive.NetworkReceiver; @@ -461,6 +462,12 @@ final public class PamModel implements PamModelInterface, PamSettings { mi.setModulesMenuGroup(utilitiesGroup); mi.setMaxNumber(1); + + mi = PamModuleInfo.registerControlledUnit(MetaDataContol.class.getName(), MetaDataContol.unitType); + mi.setToolTipText("Deployment Meta Data"); + mi.setModulesMenuGroup(utilitiesGroup); + mi.setMaxNumber(1); + if (isViewer) { mi = PamModuleInfo.registerControlledUnit(TethysControl.class.getName(), TethysControl.defaultName); mi.setToolTipText("Interface to Tethys Database"); diff --git a/src/PamModel/parametermanager/PamParameterData.java b/src/PamModel/parametermanager/PamParameterData.java index a15a3c15..79944a90 100644 --- a/src/PamModel/parametermanager/PamParameterData.java +++ b/src/PamModel/parametermanager/PamParameterData.java @@ -34,6 +34,11 @@ abstract public class PamParameterData { */ private String postTitle; + /** + * field length for automatic dialogs. + */ + private int fieldLength; + /** * @param parentObject @@ -45,6 +50,21 @@ abstract public class PamParameterData { this.field = field; } + /** + * @param parentObject + * @param field + * @param shortName + * @param toolTip + * @param fieldLength length of text in automatic dialogs. + */ + public PamParameterData(Object parentObject, Field field, String shortName, String toolTip, int fieldLength) { + super(); + this.field = field; + this.shortName = shortName; + this.toolTip = toolTip; + this.fieldLength = fieldLength; + } + /** * @param parentObject * @param field @@ -58,7 +78,6 @@ abstract public class PamParameterData { this.toolTip = toolTip; } - /** * @param shortName the shortName to set */ @@ -66,6 +85,20 @@ abstract public class PamParameterData { this.shortName = shortName; } + /** + * Set info about a parameter + * @param shortName short name, e.g. to use in a dialog + * @param postTitle post title, e.g. text coming after a data entry field in a dialog + * @param toolTip tool tip to display over the component in a dialog. + * @param fieldLength length of text in automatic dialogs. + */ + public void setInfo(String shortName, String postTitle, String toolTip, int fieldLength) { + this.shortName = shortName; + this.postTitle = postTitle; + this.toolTip = toolTip; + this.fieldLength = fieldLength; + } + /** * Set info about a parameter * @param shortName short name, e.g. to use in a dialog @@ -136,6 +169,9 @@ abstract public class PamParameterData { * @return a short name for the field, suitable for use in dialogs. */ public String getShortName() { + if (shortName == null) { + return getFieldName(); + } return shortName; } @@ -166,5 +202,19 @@ abstract public class PamParameterData { return String.format("Param %s class %s", getFieldName(), getDataClass()); } + /** + * @return the fieldLength + */ + public int getFieldLength() { + return fieldLength; + } + + /** + * @param fieldLength the fieldLength to set + */ + public void setFieldLength(int fieldLength) { + this.fieldLength = fieldLength; + } + } diff --git a/src/PamModel/parametermanager/PamParameterDataGetter.java b/src/PamModel/parametermanager/PamParameterDataGetter.java index 3947f2dc..9a3e99b0 100644 --- a/src/PamModel/parametermanager/PamParameterDataGetter.java +++ b/src/PamModel/parametermanager/PamParameterDataGetter.java @@ -59,9 +59,12 @@ public class PamParameterDataGetter extends PrivatePamParameterData { if (setter == null) { return false; } + // need to convert the type + Object convObj = convertStringType(data); try { - setter.invoke(getParentObject(), data); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + Object parentObj = getParentObject(); + setter.invoke(parentObj, convObj); + } catch (InvocationTargetException e) { e.printStackTrace(); return false; } diff --git a/src/PamModel/parametermanager/PamParameterSet.java b/src/PamModel/parametermanager/PamParameterSet.java index 751f3d27..e4c37c24 100644 --- a/src/PamModel/parametermanager/PamParameterSet.java +++ b/src/PamModel/parametermanager/PamParameterSet.java @@ -286,4 +286,5 @@ public class PamParameterSet { public PamParameterData removeParameterData(String paramName) { return parameterDatas.remove(paramName); } + } diff --git a/src/PamModel/parametermanager/ParameterSetManager.java b/src/PamModel/parametermanager/ParameterSetManager.java new file mode 100644 index 00000000..3420a7c4 --- /dev/null +++ b/src/PamModel/parametermanager/ParameterSetManager.java @@ -0,0 +1,73 @@ +package PamModel.parametermanager; + +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JMenuItem; + +import PamModel.parametermanager.swing.ManagedParameterDialog; +import generalDatabase.parameterstore.ParameterDatabaseStore; + +/** + * Just about everything giving overall control of some managed parameters. + * May be a bit too specific on first cut and need to be abstracted. + * Testing on 'Deployment' data. + * @author dg50 + * + * @param + */ +public class ParameterSetManager { + + private T managedParams; + private String name; + + public ParameterSetManager(T defaultParams, String name) { + setManagedParams(defaultParams); + this.name = name; +// if (managedParams == null) { +// managedParams = new T(); +// } + } + + /** + * @return the managedParams + */ + public T getManagedParams() { + return managedParams; + } + + /** + * @param managedParams the managedParams to set + */ + public void setManagedParams(T managedParams) { + this.managedParams = managedParams; + } + + public JMenuItem getMenuItem(Window parent) { + if (managedParams == null) { + return null; + } + JMenuItem menuItem = new JMenuItem(name + " ..."); + menuItem.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + showDialog(parent); + } + }); + + return menuItem; + } + + protected void showDialog(Window parent) { + ManagedParameterDialog dialog = new ManagedParameterDialog(parent, name, managedParams); + T newParams = dialog.showDialog(parent, name, managedParams); + + if (newParams != null) { + ParameterDatabaseStore paramDatabase = new ParameterDatabaseStore("MetaData"); + paramDatabase.saveParameterSet(newParams); + } + } + +} diff --git a/src/PamModel/parametermanager/PrivatePamParameterData.java b/src/PamModel/parametermanager/PrivatePamParameterData.java index e3fed547..6b29d9cd 100644 --- a/src/PamModel/parametermanager/PrivatePamParameterData.java +++ b/src/PamModel/parametermanager/PrivatePamParameterData.java @@ -1,6 +1,7 @@ package PamModel.parametermanager; import java.lang.reflect.Field; +import java.lang.reflect.Type; /** * Abstract instance of PamParameterDataInterface which implements everything @@ -36,9 +37,48 @@ public abstract class PrivatePamParameterData extends PamParameterData { * This should really be implemented in every concrete class, but no time to do that now. Aim to delete * this function here, then go through and implement everywhere ... */ - return false; +// return false; + Object convData = convertStringType(data); + getField().set(this, convData); + + return true; } + /** + * convert a string type to a different type appropriate for the field in + * question. + * @param value + * @return + */ + public Object convertStringType(Object value) { + if (value == null) { + return null; + } + if (value instanceof String == false) { + return value; + } + String str = (String) value; + Type type = getField().getGenericType(); + Class cls = getField().getType(); + String clsName = cls.getName(); + switch (clsName) { + case "int": + case "Integer": + return Integer.valueOf(str); + case "double": + case "Double": + return Double.valueOf(str); + case "float": + case "Float": + return Float.valueOf(str); + case "short": + case "Short": + return Short.valueOf(str); + + } + + return value; + } } diff --git a/src/PamModel/parametermanager/swing/ManagedParameterDialog.java b/src/PamModel/parametermanager/swing/ManagedParameterDialog.java new file mode 100644 index 00000000..9a3aa995 --- /dev/null +++ b/src/PamModel/parametermanager/swing/ManagedParameterDialog.java @@ -0,0 +1,49 @@ +package PamModel.parametermanager.swing; + +import java.awt.Window; + +import PamModel.parametermanager.ManagedParameters; +import PamView.dialog.PamDialog; + +public class ManagedParameterDialog extends PamDialog { + + private T params; + + private ManagedParameterPanel parameterPanel; + + public ManagedParameterDialog(Window parentFrame, String title, T params) { + super(parentFrame, title, false); + parameterPanel = new ManagedParameterPanel(params); + setDialogComponent(parameterPanel.getPanel()); + } + + public T showDialog(Window parentFrame, String title, T parameters) { +// ManagedParameterDialog dialog = new ManagedParameterDialog<>(parentFrame, title, parameters); + setParams(parameters); + setVisible(true); + + return params; + } + + private void setParams(T params) { + this.params = params; + this.parameterPanel.setParams(params); + } + + @Override + public boolean getParams() { + return parameterPanel.getParams(params); + } + + @Override + public void cancelButtonPressed() { + params = null; + } + + @Override + public void restoreDefaultSettings() { + // TODO Auto-generated method stub + + } + +} diff --git a/src/PamModel/parametermanager/swing/ManagedParameterPanel.java b/src/PamModel/parametermanager/swing/ManagedParameterPanel.java new file mode 100644 index 00000000..416bef77 --- /dev/null +++ b/src/PamModel/parametermanager/swing/ManagedParameterPanel.java @@ -0,0 +1,149 @@ +package PamModel.parametermanager.swing; + +import java.awt.Color; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.util.Collection; + +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.text.JTextComponent; + +import PamModel.parametermanager.FieldNotFoundException; +import PamModel.parametermanager.ManagedParameters; +import PamModel.parametermanager.PamParameterData; +import PamModel.parametermanager.PamParameterSet; +import PamView.dialog.PamDialog; +import PamView.dialog.PamGridBagContraints; + +public class ManagedParameterPanel { + + private JPanel mainPanel; + private Collection parameterSet; + + private static final int DEFAULT_TEXT_LENGTH = 6; + private static final int MAX_SINGLE_LINE_LENGTH = 40; + + private JTextComponent[] textComponents; + + public ManagedParameterPanel(T parameterExample) { + + mainPanel = new JPanel(new GridBagLayout()); + GridBagConstraints c = new PamGridBagContraints(); + PamParameterSet exampleSet = parameterExample.getParameterSet(); + parameterSet = exampleSet.getParameterCollection(); + int n = parameterSet.size(); + textComponents = new JTextComponent[n]; + int i = 0; + for (PamParameterData paramData : parameterSet) { + textComponents[i] = createComponent(paramData); + c.gridx = 0; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.NORTHEAST; + mainPanel.add(new JLabel(paramData.getShortName(), JLabel.RIGHT), c); + c.gridx++; + if (textComponents[i] instanceof JTextArea) { + c.fill = GridBagConstraints.HORIZONTAL; + } + else { + c.fill = GridBagConstraints.NONE; + } + c.anchor = GridBagConstraints.WEST; + mainPanel.add(textComponents[i], c); + + textComponents[i].setToolTipText(getTipText(paramData)); + + c.gridy++; + i++; + } + } + + private String getTipText(PamParameterData paramData) { + String tip = paramData.getToolTip(); + if (tip != null) { + return tip; + } + else { + return paramData.getFieldName(); + } + } + + private JTextComponent createComponent(PamParameterData paramData) { + int textLen = paramData.getFieldLength(); + if (textLen == 0) { + textLen = DEFAULT_TEXT_LENGTH; + } + if (textLen <= MAX_SINGLE_LINE_LENGTH) { + return new JTextField(textLen); + } + else { + JTextField dummyField = new JTextField(2); +// dummyField.getBorder(). + JTextArea textArea = new JTextArea(textLen/MAX_SINGLE_LINE_LENGTH+1, MAX_SINGLE_LINE_LENGTH); + textArea.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY)); + return textArea; + } + } + + public JComponent getPanel() { + return mainPanel; + } + + public void setParams(T params) { + int i = 0; + PamParameterData newParamData = null; + Object data = null; + for (PamParameterData paramData : this.parameterSet) { + // find the parameter in the new parameters (parameterSet is just a formatting placeholder) + try { + newParamData = params.getParameterSet().findParameterData(paramData.getFieldName()); + } catch (FieldNotFoundException e) { + e.printStackTrace(); + } + try { + data = newParamData.getData(); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + if (data != null) { + textComponents[i].setText(data.toString()); + } + else { + textComponents[i].setText(null); + } + i++; + } + } + + public boolean getParams(T params) { + int i = 0; + PamParameterData newParamData = null; + Object data = null; + for (PamParameterData paramData : this.parameterSet) { + // find the parameter in the new parameters (parameterSet is just a formatting placeholder) + try { + newParamData = params.getParameterSet().findParameterData(paramData.getFieldName()); + } catch (FieldNotFoundException e) { + e.printStackTrace(); + } + String txt = textComponents[i].getText(); + try { + newParamData.setData(txt); + } catch (IllegalArgumentException | IllegalAccessException e) { + String msg = "Invalid parameter. Data type should be " + paramData.getField().getType().getName(); + return PamDialog.showWarning(null, newParamData.getShortName(), msg); + } + + i++; + } + + return true; + } + +} diff --git a/src/generalDatabase/parameterstore/ParameterDatabaseStore.java b/src/generalDatabase/parameterstore/ParameterDatabaseStore.java new file mode 100644 index 00000000..29c740eb --- /dev/null +++ b/src/generalDatabase/parameterstore/ParameterDatabaseStore.java @@ -0,0 +1,187 @@ +package generalDatabase.parameterstore; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Types; +import java.util.Arrays; +import java.util.Collection; + +import PamModel.parametermanager.ManagedParameters; +import PamModel.parametermanager.PamParameterData; +import PamModel.parametermanager.PamParameterSet; +import generalDatabase.DBControlUnit; +import generalDatabase.EmptyTableDefinition; +import generalDatabase.PamConnection; +import generalDatabase.PamTableItem; +import generalDatabase.SQLTypes; + +/** + * Store parameters from a managed parameter set in the PAMGuard database. These go into a dead simple table, which has + * two columns. The first is a name, the second a string value. Each parameter can only appear once. + * This works with ManagedParameters using the same names and field names that go into the xml output. + * @author dg50 + * + */ +public class ParameterDatabaseStore { + + + private EmptyTableDefinition tableDef; + private PamTableItem nameItem, dataItem; + + public ParameterDatabaseStore(String tableName) { + tableDef = new EmptyTableDefinition(tableName); + tableDef.addTableItem(nameItem = new PamTableItem("ParameterName", Types.VARCHAR)); + tableDef.addTableItem(dataItem = new PamTableItem("Value", Types.VARCHAR)); + } + + public boolean saveParameterSet(ManagedParameters managedParameters) { + if (managedParameters == null) { + return false; + } + return saveParameterSet(managedParameters.getClass().getSimpleName(), managedParameters); + } + + private boolean saveParameterSet(String name, ManagedParameters managedParameters) { + DBControlUnit dbControl = DBControlUnit.findDatabaseControl(); + if (dbControl == null) { + return false; + } + PamConnection con = dbControl.getConnection(); + if (checkTable(con) == false) { + return false; + } + + String prefix; + if (name == null) { + prefix = ""; + } + else { + prefix = name + "."; + } + PamParameterSet paramSet = managedParameters.getParameterSet(); + Collection params = paramSet.getParameterCollection(); + for (PamParameterData paramData : params) { + String paramName = paramData.getFieldName(); + paramName = prefix + paramName; + Object data = null; + try { + data = paramData.getData();// .getField().get(managedParameters); + } catch (IllegalArgumentException | IllegalAccessException e) { + e.printStackTrace(); + } +// System.out.printf("Store param \"%s\" as \"%s\"\n", paramName, data); + saveToDatabase(con, paramName, data); + } + dbControl.commitChanges(); + + return true; + } + + private boolean saveToDatabase(PamConnection con, String name, Object data) { + int[] existing = findExistingRows(con, name); + boolean ok = true; + if (existing == null || existing.length == 0) { + ok |= newRecord(con, name, data); + } + else { + ok |= updateRecord(con, existing[0], name, data); + if (existing.length > 1) { + for (int i = 1; i < existing.length; i++) { + ok |= deleteDuplicateRow(con, existing[i]); + } + } + } + return true; + } + + private int[] findExistingRows(PamConnection con, String name) { + /** + * Find existing rows with that name. + */ + int[] rows = new int[0]; + if (con == null) { + return rows; + } + String qStr = String.format("SELECT Id FROM %s WHERE %s='%s'", tableDef.getTableName(), nameItem.getName(), name); + try { + Statement stmt = con.getConnection().createStatement(); + ResultSet res = stmt.executeQuery(qStr); + while (res.next()) { + int rowId = res.getInt(1); + rows = Arrays.copyOf(rows, rows.length+1); + rows[rows.length-1] = rowId; + } + res.close(); + stmt.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + return rows; + } + + private boolean newRecord(PamConnection con, String name, Object data) { + + String insertStr = tableDef.getSQLInsertString(con.getSqlTypes()); + try { + PreparedStatement stmt = con.getConnection().prepareStatement(insertStr); + stmt.setString(1, name); + if (data == null) { + stmt.setNull(2, Types.VARCHAR); + } + else { + stmt.setString(2, data.toString()); + } + stmt.executeUpdate(); + + } catch (SQLException e) { + e.printStackTrace(); + return false; + } + + return true; + } + + private boolean updateRecord(PamConnection con, int iRow, String name, Object data) { + SQLTypes st = con.getSqlTypes(); + String updateString = String.format("UPDATE %s SET %s = '%s' WHERE Id = %d", tableDef.getTableName(), + st.formatColumnName(dataItem.getName()), data, iRow); + + try { + PreparedStatement stmt = con.getConnection().prepareStatement(updateString); + stmt.executeUpdate(); + + } catch (SQLException e) { + e.printStackTrace(); + return false; + } + + return true; + } + + private boolean deleteDuplicateRow(PamConnection con, int rowId) { + + String delStr = String.format("DELETE FROM %s WHERE Id=%d", tableDef.getTableName(), rowId); + + try { + PreparedStatement stmt = con.getConnection().prepareStatement(delStr); + stmt.executeUpdate(); + + } catch (SQLException e) { + e.printStackTrace(); + return false; + } + return true; + } + + private boolean checkTable(PamConnection con) { + DBControlUnit dbControl = DBControlUnit.findDatabaseControl(); + if (dbControl == null) { + return false; + } + dbControl.commitChanges(); + return dbControl.getDbProcess().checkTable(tableDef); + } + +} diff --git a/src/metadata/MetaDataContol.java b/src/metadata/MetaDataContol.java new file mode 100644 index 00000000..42993911 --- /dev/null +++ b/src/metadata/MetaDataContol.java @@ -0,0 +1,30 @@ +package metadata; + +import javax.swing.JFrame; +import javax.swing.JMenuItem; + +import PamController.PamControlledUnit; +import PamModel.parametermanager.ParameterSetManager; +import generalDatabase.parameterstore.ParameterDatabaseStore; +import metadata.deployment.DeploymentData; + +public class MetaDataContol extends PamControlledUnit { + + public static final String unitType = "Meta Data"; + + private DeploymentData deploymentData = new DeploymentData(); + + private ParameterSetManager deploymentSetManager; + + + public MetaDataContol(String unitName) { + super(unitType, unitName); + deploymentSetManager = new ParameterSetManager(deploymentData, "Deployment Data"); + } + + @Override + public JMenuItem createFileMenu(JFrame parentFrame) { + return deploymentSetManager.getMenuItem(parentFrame); + } + +} diff --git a/src/metadata/deployment/DeploymentData.java b/src/metadata/deployment/DeploymentData.java new file mode 100644 index 00000000..d42df884 --- /dev/null +++ b/src/metadata/deployment/DeploymentData.java @@ -0,0 +1,266 @@ +package metadata.deployment; + +import java.io.Serializable; + +import PamModel.parametermanager.FieldNotFoundException; +import PamModel.parametermanager.ManagedParameters; +import PamModel.parametermanager.PamParameterSet; + +/** + * Class to hold Deployment data in a form consistent with the ANSI PAM + * Standard. This has been keep separate from the Tethys Interface to keep it + * easy to benefit from these data without using Tethys itself. + * + * @author dg50 + * + */ +public class DeploymentData implements Serializable, Cloneable, ManagedParameters { + + public static final long serialVersionUID = 1L; + + /** + * String that uniquely identifies this deployment. + */ + private String id; + + /** + * Name of project associated with this deployment. Can be related to a + * geographic region, funding source, etc + */ + private String project; + + /** + * Deployment identifier, a number related to either the Nth deployment + * operation in a series of deployments or the Nth deployment at a specific + * site. This is different from Id which is unique across all deployments + */ + private int deploymentId; + + /** + * Alternative deployment description. + */ + private String deploymentAlias; + + /** + * Name for current location. + */ + private String site; + + /** + * Alternative names for the deployment location + */ + private String siteAliases; + + /** + * Name of deployment cruise. + */ + private String cruise; + + /** + * On what platform is the instrument deployed? (e.g. mooring, tag) + */ + private String platform = "Unknown"; + + /** + * Name of geographic region. + */ + private String region; + + /** + * Instrument type, e.g. HARP, EAR, Popup, DMON, etc. + */ + private String instrumentType; + + /** + * Instrument identifier, e.g. serial number + */ + private String instrumentId; + + public DeploymentData() { + } + + @Override + protected DeploymentData clone() { + try { + return (DeploymentData) super.clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + return null; + } + } + + @Override + public PamParameterSet getParameterSet() { + PamParameterSet ps = PamParameterSet.autoGenerate(this); + try { + ps.findParameterData("id").setInfo("Unique Id", null, "String that uniquely identifies this deployment", 128); +// ps.setOrder("id", 0); + ps.findParameterData("project").setInfo("Project Name", null, "Name of project associated with this deployment. Can be related to a geographic region, funding source, etc", 200); + ps.findParameterData("deploymentId").setInfo("Deployment Identifier", null, "Deployment identifier, a number related to either the Nth deployment operation in a series of deployments or the Nth deployment at a specific site. This is different from Id which is unique across all deployments"); + ps.findParameterData("deploymentAlias").setInfo("Alternative deployment description", null, "Alternative deployment description", 20); + ps.findParameterData("site").setInfo("Site name", null, "Name for current location", 40); + ps.findParameterData("siteAliases").setInfo("Alternative site name", null, "Alternative site description", 40); + ps.findParameterData("cruise").setInfo("Deployment cruise", null, "Name of deployment cruise"); + ps.findParameterData("platform").setInfo("Platform type", null, "On what platform is the instrument deployed? (e.g. mooring, tag)", 20); + ps.findParameterData("region").setInfo("Geographic Region", "", "Name of geographic region", 40); + } catch (FieldNotFoundException e) { + e.printStackTrace(); + } + return ps; + } + + /** + * @return the id + */ + public String getId() { + return id; + } + + /** + * @param id the id to set + */ + public void setId(String id) { + this.id = id; + } + + /** + * @return the project + */ + public String getProject() { + return project; + } + + /** + * @param project the project to set + */ + public void setProject(String project) { + this.project = project; + } + + /** + * @return the deploymentId + */ + public int getDeploymentId() { + return deploymentId; + } + + /** + * @param deploymentId the deploymentId to set + */ + public void setDeploymentId(int deploymentId) { + this.deploymentId = deploymentId; + } + + /** + * @return the deplomentAlias + */ + public String getDeploymentAlias() { + return deploymentAlias; + } + + /** + * @param deplomentAlias the deplomentAlias to set + */ + public void setDeploymentAlias(String deplomentAlias) { + this.deploymentAlias = deplomentAlias; + } + + /** + * @return the site + */ + public String getSite() { + return site; + } + + /** + * @param site the site to set + */ + public void setSite(String site) { + this.site = site; + } + + /** + * @return the siteAliases + */ + public String getSiteAliases() { + return siteAliases; + } + + /** + * @param siteAliases the siteAliases to set + */ + public void setSiteAliases(String siteAliases) { + this.siteAliases = siteAliases; + } + + /** + * @return the cruise + */ + public String getCruise() { + return cruise; + } + + /** + * @param cruise the cruise to set + */ + public void setCruise(String cruise) { + this.cruise = cruise; + } + + /** + * @return the platform + */ + public String getPlatform() { + return platform; + } + + /** + * @param platform the platform to set + */ + public void setPlatform(String platform) { + this.platform = platform; + } + + /** + * @return the region + */ + public String getRegion() { + return region; + } + + /** + * @param region the region to set + */ + public void setRegion(String region) { + this.region = region; + } + + /** + * @return the instrumentType + */ + public String getInstrumentType() { + return instrumentType; + } + + /** + * @param instrumentType the instrumentType to set + */ + public void setInstrumentType(String instrumentType) { + this.instrumentType = instrumentType; + } + + /** + * @return the instrumentId + */ + public String getInstrumentId() { + return instrumentId; + } + + /** + * @param instrumentId the instrumentId to set + */ + public void setInstrumentId(String instrumentId) { + this.instrumentId = instrumentId; + } + +} diff --git a/src/metadata/deployment/QAData.java b/src/metadata/deployment/QAData.java new file mode 100644 index 00000000..368db614 --- /dev/null +++ b/src/metadata/deployment/QAData.java @@ -0,0 +1,40 @@ +package metadata.deployment; + +import java.io.Serializable; + +import PamModel.parametermanager.ManagedParameters; +import PamModel.parametermanager.PamParameterSet; + +/** + * Largely the content of the Tethys QualityAssurance schema + * @author dg50 + * + */ +public class QAData implements Serializable, Cloneable, ManagedParameters { + + public static final long serialVersionUID = 1L; + + private String objectives; + + private String qaAbstract; + + private String method; + + private String responsibleName; + private String responsibleOrganisation; + private String responsiblePosition; + private String responsiblePhone; + private String responsibleAddress; + private String responsibleEmail; + + public QAData() { + // TODO Auto-generated constructor stub + } + + @Override + public PamParameterSet getParameterSet() { + PamParameterSet ps = PamParameterSet.autoGenerate(this); + return ps; + } + +} diff --git a/src/tethys/TethysControl.java b/src/tethys/TethysControl.java index dc0a46f2..f700ebb0 100644 --- a/src/tethys/TethysControl.java +++ b/src/tethys/TethysControl.java @@ -11,6 +11,8 @@ import javax.swing.JMenuItem; import PamController.PamControlledUnit; import PamController.PamController; import PamguardMVC.PamDataBlock; +import nilus.Deployment; +import nilus.Deployment.Instrument; import tethys.output.StreamExportParams; import tethys.output.TethysExportParams; import tethys.output.swing.TethysExportDialog; @@ -56,6 +58,19 @@ public class TethysControl extends PamControlledUnit { public TethysExportParams getTethysExportParams() { return tethysExportParams; } + + /** + * Get a nilus deployment document, as full populated as possible. + * @return + */ + public Deployment getDeployment() { + Deployment deployment = new Deployment(); + Deployment.Instrument instrument = new Instrument(); +// instrument. +// deployment. + + return null; + } /** * We'll probably want to diff --git a/src/tethys/deployment/DeploymentWrapper.java b/src/tethys/deployment/DeploymentWrapper.java new file mode 100644 index 00000000..1d1d98ca --- /dev/null +++ b/src/tethys/deployment/DeploymentWrapper.java @@ -0,0 +1,85 @@ +package tethys.deployment; + +import java.io.ByteArrayOutputStream; +import java.io.Serializable; +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedType; +import java.util.List; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.Marshaller; +import javax.xml.namespace.QName; +import javax.xml.validation.Schema; + +import nilus.Deployment.Data.Audio; +import nilus.Deployment; +import nilus.Deployment.Data; +import nilus.Deployment.Instrument; + +public class DeploymentWrapper { + + public DeploymentWrapper(T tethysObject) { + + } + + public List getFieldNames() { + return null; + } + + public List getComplexObjects() { + + return null; + } + + public static void main(String[] args) { + // quick play with some JAXB objects to see what they can do. + Deployment deployment = new Deployment(); + + Class deploymentClass = deployment.getClass(); + Annotation[] annots = deploymentClass.getAnnotations(); + AnnotatedType[] annotInterfaces = deploymentClass.getAnnotatedInterfaces(); + Annotation[] declAnnots = deploymentClass.getDeclaredAnnotations(); + + Instrument instrument = new Instrument(); + instrument.setID("22"); + instrument.setType("SoundTrap"); + QName qName = new QName("Instrument"); + JAXBElement jInst = new JAXBElement(qName, Instrument.class, instrument); + deployment.getContent().add(jInst); + + Deployment.Data data = new Data(); + Audio audio = new Audio(); + audio.setProcessed("??"); + data.setAudio(audio); + JAXBElement jData = new JAXBElement(new QName("Data"), Data.class, data); + deployment.getContent().add(jData); + + String project = "Project Name"; + JAXBElement jProj = new JAXBElement(new QName("Project"), String.class, project); + deployment.getContent().add(jProj); + + String aaa = "Project Something else"; + JAXBElement jProj2 = new JAXBElement(new QName("Region"), String.class, aaa); + deployment.getContent().add(jProj2); + + + try { + JAXBContext jContext = JAXBContext.newInstance(Deployment.class); + Marshaller mar = (Marshaller) jContext.createMarshaller(); + mar.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, true); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + mar.marshal(deployment, bos); + String xml = new String(bos.toByteArray()); + System.out.println(xml); +// Schema schema = mar.getSchema(); // is null. Can't generate it's own it seems. + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + +} diff --git a/src/tethys/deployment/PamDeployment.java b/src/tethys/deployment/PamDeployment.java new file mode 100644 index 00000000..4d1a2d43 --- /dev/null +++ b/src/tethys/deployment/PamDeployment.java @@ -0,0 +1,64 @@ +package tethys.deployment; + +import java.io.Serializable; + +import nilus.DeploymentRecoveryDetails; + +/** + * Wrapper and functions associated with the Tethys Deployment object which can + * exchange these with the PAMGuard database and display Everything is just held + * within a list, in no particular order, which getContent public + * + * This is from the Deployment JavaDoc. TBH it's pretty horrible, since it's possible to have + * more than one of each type of object in the list, so not sure what to do about that. Would be nicer + * as a HashTable. however we are where we're are for now. Start by focussing on getting the + * content saved for each type + * + * List getContent() + * + * Gets the value of the content property. This accessor method returns a + * reference to the live list,not a snapshot. Therefore any modification you + * make to the returned list will be present inside the JAXB object.This is why + * there is not a set method for the content property. + * + * For example, to add a new item, do as follows: getContent().add(newItem); + * + * + * Objects of the following type(s) are allowed in the list JAXBElement + * JAXBElement + * JAXBElement + * JAXBElement + * JAXBElement + * JAXBElement + * JAXBElement + * JAXBElement + * JAXBElement + * JAXBElement + * JAXBElement String + * JAXBElement + * JAXBElement + * JAXBElement + * JAXBElement + * + * + * @author dg50 + * + */ +public class PamDeployment { + + public PamDeployment() { + + } + + public DeploymentRecoveryDetails getDeploymentRecoveryDetails() { + DeploymentRecoveryDetails drd = new DeploymentRecoveryDetails(); + + return null; + } + + private void ripApart(Serializable object) { + Class cls = object.getClass(); +// cls.get + } + +} diff --git a/src/tethys/exchange/TethysExchange.java b/src/tethys/exchange/TethysExchange.java new file mode 100644 index 00000000..79f24ce5 --- /dev/null +++ b/src/tethys/exchange/TethysExchange.java @@ -0,0 +1,5 @@ +package tethys.exchange; + +public interface TethysExchange { +// JAXB +} From 1c11e3da15048f49c1e3268e8cd5b6e7a6e8788f Mon Sep 17 00:00:00 2001 From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com> Date: Fri, 27 Jan 2023 11:11:02 +0000 Subject: [PATCH 5/5] DBXM Export A few functions to help find data. --- .classpath | 2 +- src/PamController/PamguardVersionInfo.java | 2 +- src/PamguardMVC/PamDataBlock.java | 26 ++ .../SweepClassifierSetPaneFX.java | 96 +++---- src/metadata/MetaDataContol.java | 14 + src/tethys/TethysControl.java | 9 + src/tethys/TethysExporter.java | 133 ---------- src/tethys/dbxml/DBXMLConnect.java | 24 ++ src/tethys/exchange/TethysExchange.java | 5 - src/tethys/output/TethysExporter.java | 244 ++++++++++++++++++ .../output/swing/TethysExportDialog.java | 24 +- src/tethys/pamdata/AutoTethysProvider.java | 42 +++ src/tethys/pamdata/TethysDataPoint.java | 18 ++ src/tethys/pamdata/TethysDataProvider.java | 32 +++ src/tethys/pamdata/TethysSchema.java | 32 +++ 15 files changed, 511 insertions(+), 192 deletions(-) delete mode 100644 src/tethys/TethysExporter.java create mode 100644 src/tethys/dbxml/DBXMLConnect.java delete mode 100644 src/tethys/exchange/TethysExchange.java create mode 100644 src/tethys/output/TethysExporter.java create mode 100644 src/tethys/pamdata/AutoTethysProvider.java create mode 100644 src/tethys/pamdata/TethysDataPoint.java create mode 100644 src/tethys/pamdata/TethysDataProvider.java create mode 100644 src/tethys/pamdata/TethysSchema.java diff --git a/.classpath b/.classpath index daee38d4..d60e2620 100644 --- a/.classpath +++ b/.classpath @@ -6,7 +6,7 @@ - + diff --git a/src/PamController/PamguardVersionInfo.java b/src/PamController/PamguardVersionInfo.java index 67b45c46..072ba3de 100644 --- a/src/PamController/PamguardVersionInfo.java +++ b/src/PamController/PamguardVersionInfo.java @@ -24,7 +24,7 @@ public class PamguardVersionInfo { * PAMGuard can work with. */ static public final String minJavaVersion = "11.0.0"; - static public final String maxJavaVersion = "18.99.99"; + static public final String maxJavaVersion = "19.99.99"; /** diff --git a/src/PamguardMVC/PamDataBlock.java b/src/PamguardMVC/PamDataBlock.java index b6056e9c..f26f24c9 100644 --- a/src/PamguardMVC/PamDataBlock.java +++ b/src/PamguardMVC/PamDataBlock.java @@ -50,6 +50,8 @@ import org.w3c.dom.Element; import Acquisition.AcquisitionControl; import Acquisition.AcquisitionProcess; import pamScrollSystem.ViewLoadObserver; +import tethys.pamdata.AutoTethysProvider; +import tethys.pamdata.TethysDataProvider; import dataGram.DatagramProvider; import dataMap.BespokeDataMapGraphic; import dataMap.OfflineDataMap; @@ -64,6 +66,7 @@ import PamController.PamController; import PamController.PamControllerInterface; import PamDetection.LocContents; import PamDetection.LocalisationInfo; +import PamDetection.PamDetection; import PamUtils.PamCalendar; import PamUtils.PamUtils; import PamView.symbol.PamSymbolManager; @@ -2835,8 +2838,11 @@ public class PamDataBlock extends PamObservable { private Vector offlineDataMaps = null; private SQLLogging logging; + + private TethysDataProvider tethysDataProvider; private JSONObjectDataSource jsonDataSource; + public Vector getProcessAnnotations() { return processAannotations; @@ -3046,6 +3052,26 @@ public class PamDataBlock extends PamObservable { public SQLLogging getLogging() { return logging; } + + /** + * Gets a data provider for Tethys. These will probably need + * to be bespoke, but for now will autogenerate based on the SALLogging information. + * @return the tethysDataProvider + */ + public TethysDataProvider getTethysDataProvider() { + if (tethysDataProvider == null && PamDetection.class.isAssignableFrom(unitClass) && getLogging() != null) { + tethysDataProvider = new AutoTethysProvider(this); + } + return tethysDataProvider; + } + + /** + * Set a data provider for Tethys. + * @param tethysDataProvider the tethysDataProvider to set + */ + public void setTethysDataProvider(TethysDataProvider tethysDataProvider) { + this.tethysDataProvider = tethysDataProvider; + } final public boolean getCanLog() { return (logging != null); diff --git a/src/clickDetector/layoutFX/clickClassifiers/SweepClassifierSetPaneFX.java b/src/clickDetector/layoutFX/clickClassifiers/SweepClassifierSetPaneFX.java index 477b5b78..9e8ee5c0 100644 --- a/src/clickDetector/layoutFX/clickClassifiers/SweepClassifierSetPaneFX.java +++ b/src/clickDetector/layoutFX/clickClassifiers/SweepClassifierSetPaneFX.java @@ -1600,22 +1600,22 @@ public class SweepClassifierSetPaneFX extends SettingsPane { p.setLayout(new GridBagLayout()); GridBagConstraints c = new PamGridBagContraints(); - c.gridx = 0; - addComponent(p, enableBearings, c); - c.gridx += c.gridwidth; - addComponent(p, bearingsExcludeBox, c); - c.gridx += c.gridwidth; - addComponent(p, new JLabel("bearings between ", JLabel.RIGHT), c); - c.gridx += c.gridwidth; - addComponent(p, minBearing, c); - c.gridx += c.gridwidth; - addComponent(p, new JLabel(" and ", JLabel.RIGHT), c); - c.gridx += c.gridwidth; - addComponent(p, maxBearing, c); - c.gridx += c.gridwidth; - addComponent(p, new JLabel("(\u00B0)", JLabel.LEFT), c); - - add(BorderLayout.WEST, p); +// c.gridx = 0; +// addComponent(p, enableBearings, c); +// c.gridx += c.gridwidth; +// addComponent(p, bearingsExcludeBox, c); +// c.gridx += c.gridwidth; +// addComponent(p, new JLabel("bearings between ", JLabel.RIGHT), c); +// c.gridx += c.gridwidth; +// addComponent(p, minBearing, c); +// c.gridx += c.gridwidth; +// addComponent(p, new JLabel(" and ", JLabel.RIGHT), c); +// c.gridx += c.gridwidth; +// addComponent(p, maxBearing, c); +// c.gridx += c.gridwidth; +// addComponent(p, new JLabel("(\u00B0)", JLabel.LEFT), c); +// +// add(BorderLayout.WEST, p); this.multiChan = checkMultiChan(); @@ -1661,21 +1661,21 @@ public class SweepClassifierSetPaneFX extends SettingsPane { return true; } - @Override - protected void enableControls() { - checkMultiChan(); - - enableBearings.setEnabled(multiChan); - bearingsExcludeBox.setEnabled(multiChan); - minBearing.setEnabled(multiChan); - maxBearing.setEnabled(multiChan); - - if (!multiChan) return; - - bearingsExcludeBox.setEnabled(enableBearings.isSelected()); - minBearing.setEnabled(enableBearings.isSelected()); - maxBearing.setEnabled(enableBearings.isSelected()); - } +// @Override +// protected void enableControls() { +// checkMultiChan(); +// +// enableBearings.setEnabled(multiChan); +// bearingsExcludeBox.setEnabled(multiChan); +// minBearing.setEnabled(multiChan); +// maxBearing.setEnabled(multiChan); +// +// if (!multiChan) return; +// +// bearingsExcludeBox.setEnabled(enableBearings.isSelected()); +// minBearing.setEnabled(enableBearings.isSelected()); +// maxBearing.setEnabled(enableBearings.isSelected()); +// } @Override protected void disbleControls(boolean disable) { @@ -1692,23 +1692,23 @@ public class SweepClassifierSetPaneFX extends SettingsPane { private boolean checkMultiChan() { boolean multiChan = false; //do we have multi-channel clicks? - if (clickControl!=null) { - int[] chanGroups = clickControl.getClickParameters().getGroupedSourceParameters().getChannelGroups(); - multiChan = false; - - if (chanGroups==null) return multiChan; - - for (int i=0; i1) { - multiChan = true; - break; - } - } - } - else multiChan = true; -// Debug.out.println("Check multi-channel: " + multiChan); +// if (clickControl!=null) { +// int[] chanGroups = clickControl.getClickParameters().getGroupedSourceParameters().getChannelGroups(); +// multiChan = false; +// +// if (chanGroups==null) return multiChan; +// +// for (int i=0; i1) { +// multiChan = true; +// break; +// } +// } +// } +// else multiChan = true; +//// Debug.out.println("Check multi-channel: " + multiChan); return multiChan; } diff --git a/src/metadata/MetaDataContol.java b/src/metadata/MetaDataContol.java index 42993911..98c60eb1 100644 --- a/src/metadata/MetaDataContol.java +++ b/src/metadata/MetaDataContol.java @@ -27,4 +27,18 @@ public class MetaDataContol extends PamControlledUnit { return deploymentSetManager.getMenuItem(parentFrame); } + /** + * @return the deploymentData + */ + public DeploymentData getDeploymentData() { + return deploymentData; + } + + /** + * @param deploymentData the deploymentData to set + */ + public void setDeploymentData(DeploymentData deploymentData) { + this.deploymentData = deploymentData; + } + } diff --git a/src/tethys/TethysControl.java b/src/tethys/TethysControl.java index f700ebb0..da74b248 100644 --- a/src/tethys/TethysControl.java +++ b/src/tethys/TethysControl.java @@ -15,6 +15,7 @@ import nilus.Deployment; import nilus.Deployment.Instrument; import tethys.output.StreamExportParams; import tethys.output.TethysExportParams; +import tethys.output.TethysExporter; import tethys.output.swing.TethysExportDialog; /** @@ -93,5 +94,13 @@ public class TethysControl extends PamControlledUnit { TethysExporter tethysExporter = new TethysExporter(this, tethysExportParams); tethysExporter.doExport(); } + + /** + * A name for any deta selectors. + * @return + */ + public String getDataSelectName() { + return getUnitName(); + } } diff --git a/src/tethys/TethysExporter.java b/src/tethys/TethysExporter.java deleted file mode 100644 index 6dc816a0..00000000 --- a/src/tethys/TethysExporter.java +++ /dev/null @@ -1,133 +0,0 @@ -package tethys; - -import java.util.ArrayList; - -import org.w3c.dom.Document; - -import PamController.PamControlledUnit; -import PamController.PamController; -import PamController.settings.output.xml.PamguardXMLWriter; -import PamguardMVC.PamDataBlock; -import generalDatabase.DBSchemaWriter; -import generalDatabase.SQLLogging; -import tethys.output.StreamExportParams; -import tethys.output.TethysExportParams; - -public class TethysExporter { - - private TethysControl tethysControl; - private TethysExportParams tethysExportParams; - - public TethysExporter(TethysControl tethysControl, TethysExportParams tethysExportParams) { - this.tethysControl = tethysControl; - this.tethysExportParams = tethysExportParams; - } - - /** - * Does the work. In reality this will need an awful lot of changing, for instance - * to provide feedback to an observer class to show progress on the display. - * @return OK if success. - */ - public boolean doExport() { - /* - * Call some general export function - */ - exportGeneralData(tethysExportParams); - /* - * go through the export params and call something for every - * data block that's enabled. - */ - ArrayList allDataBlocks = PamController.getInstance().getDataBlocks(); - for (PamDataBlock aDataBlock : allDataBlocks) { - StreamExportParams streamExportParams = tethysExportParams.getStreamParams(aDataBlock); - if (streamExportParams == null || streamExportParams.selected == false) { - continue; // not interested in this one. - } - exportDataStream(aDataBlock, tethysExportParams, streamExportParams); - } - /* - * Then do whatever else is needed to complete the document. - */ - - return true; - } - - /** - * No idea if we need this or not. May want to return something different to void, e.g. - * a reference to the main object for a tethys export. I've no idea ! - * @param tethysExportParams2 - */ - private void exportGeneralData(TethysExportParams tethysExportParams) { - // TODO Auto-generated method stub - - } - - /** - * Here is where we export data for a specific data stream to Tethys. - * - * @param aDataBlock - * @param tethysExportParams - * @param streamExportParams - */ - private void exportDataStream(PamDataBlock aDataBlock, TethysExportParams tethysExportParams, - StreamExportParams streamExportParams) { - /** - * This will probably need to be passed additional parameters and may also want to return something - * other than void in order to build a bigger Tethys document. - */ - /* - * Some examples of how to do whatever is needed to get schema and data out of PAMGuard. - */ - /* - * first we'll probably want a reference to the module containing the data. - * in principle this can't get null, since the datablock was found be searching in - * the other direction. - */ - PamControlledUnit pamControlledUnit = aDataBlock.getParentProcess().getPamControlledUnit(); - /* - * Get the XML settings for that datablock. - */ - PamguardXMLWriter pamXMLWriter = PamguardXMLWriter.getXMLWriter(); - Document doc = pamXMLWriter.writeOneModule(pamXMLWriter, System.currentTimeMillis()); - String moduleXML = null; - if (doc != null) { - // this string should be XML of all the settings for the module controlling this datablock. - moduleXML = pamXMLWriter.getAsString(doc, true); // change to false to get smaller xml - System.out.printf("Module settings for datablock %s are:\n", moduleXML); - System.out.println(moduleXML); - } - /* - * This also should never be null, because we only selected datablocks that had a database - * interface. - * Future versions may need to change this to use binary stores. This will require - * the overriding datablock to return something different to SQLLogging - probably a TethysLogging - * interface, which can probably by default just wrap the SQLLogging , but does allow the - * option of modifying behaviour and of making something work for binary stores. - */ - SQLLogging logging = aDataBlock.getLogging(); - if (logging == null) return; - /** - * From the logging, it's possible to automatically generate a XML schema. This may not - * be entirely right, but will be easy to fix. - */ - DBSchemaWriter schemaWriter = new DBSchemaWriter(); - Document schemaDoc = schemaWriter.generateDatabaseSchema(aDataBlock, logging, logging.getTableDefinition()); - String schemaXML = null; - if (schemaDoc != null) { - schemaXML = pamXMLWriter.getAsString(schemaDoc, true); - } - System.out.printf("Database schema for Module Type %s Name %s are:\n", pamControlledUnit.getUnitType(), pamControlledUnit.getUnitName()); - System.out.println(schemaXML); - - /** - * Now can go through the data. Probably, we'll want to go through all the data in - * the project, but we can hold off on that for now and just go for data that - * are in memory. We'll also have to think a lot about updating parts of the - * database which have been reprocessed - what we want to do, should eventually all - * be options set in the dialog and available within TethysExportParams - * For now though, we're just going to export data that are in memory. - */ - - } - -} diff --git a/src/tethys/dbxml/DBXMLConnect.java b/src/tethys/dbxml/DBXMLConnect.java new file mode 100644 index 00000000..154be543 --- /dev/null +++ b/src/tethys/dbxml/DBXMLConnect.java @@ -0,0 +1,24 @@ +package tethys.dbxml; + +import tethys.TethysControl; + +public class DBXMLConnect { + + private TethysControl tethysControl; + + public DBXMLConnect(TethysControl tethysControl) { + this.tethysControl = tethysControl; + } + + public boolean openDatabase() { + + return true; + } + + public void closeDatabase() { + + } + + // add whatever calls are necessary to set up schema's etc. + +} diff --git a/src/tethys/exchange/TethysExchange.java b/src/tethys/exchange/TethysExchange.java deleted file mode 100644 index 79f24ce5..00000000 --- a/src/tethys/exchange/TethysExchange.java +++ /dev/null @@ -1,5 +0,0 @@ -package tethys.exchange; - -public interface TethysExchange { -// JAXB -} diff --git a/src/tethys/output/TethysExporter.java b/src/tethys/output/TethysExporter.java new file mode 100644 index 00000000..f8d94061 --- /dev/null +++ b/src/tethys/output/TethysExporter.java @@ -0,0 +1,244 @@ +package tethys.output; + +import java.util.ArrayList; + +import org.w3c.dom.Document; + +import Acquisition.AcquisitionControl; +import Acquisition.AcquisitionProcess; +import Array.ArrayManager; +import Array.Hydrophone; +import Array.PamArray; +import Array.SnapshotGeometry; +import PamController.PamControlledUnit; +import PamController.PamController; +import PamController.settings.output.xml.PamguardXMLWriter; +import PamUtils.PamCalendar; +import PamguardMVC.PamDataBlock; +import PamguardMVC.PamDataUnit; +import generalDatabase.DBSchemaWriter; +import generalDatabase.SQLLogging; +import metadata.MetaDataContol; +import metadata.deployment.DeploymentData; +import tethys.TethysControl; +import tethys.dbxml.DBXMLConnect; +import tethys.pamdata.TethysDataProvider; +import tethys.pamdata.TethysSchema; + +/** + * Class sitting at the centre of all operations. It will talk to PAMGuard objects to get schemas and data + * and talk to the database connection to move data out (and possibly in). Eventually, a lot of the functionality + * in here will be moved to worker threads (SwingWorker?) so that it's easy to keep dialogs alive, show + * progress for big export jobs, etc. For now though, it's a relatively simple set of function which + * we can use to a) open the database, b) check everything such as schemas, etc. c) export data and d) clean up. + * @author dg50 + * + */ +public class TethysExporter { + + private TethysControl tethysControl; + private TethysExportParams tethysExportParams; + + private DBXMLConnect dbxmlConnect; + + public TethysExporter(TethysControl tethysControl, TethysExportParams tethysExportParams) { + this.tethysControl = tethysControl; + this.tethysExportParams = tethysExportParams; + dbxmlConnect = new DBXMLConnect(tethysControl); + } + + /** + * Does the work. In reality this will need an awful lot of changing, for instance + * to provide feedback to an observer class to show progress on the display. + * @return OK if success. + */ + public boolean doExport() { + + boolean dbOK = dbxmlConnect.openDatabase(); + if (!dbOK) { + /* + * should we set up some exceptions to throw ? Can be a lot + * more informative than a simple 'false' + */ + return false; + } + + SnapshotGeometry arrayGeometry = findArrayGeometrey(); + + /* + * Call some general export function + */ + exportGeneralData(tethysExportParams); + /* + * go through the export params and call something for every + * data block that's enabled. + */ + ArrayList allDataBlocks = PamController.getInstance().getDataBlocks(); + for (PamDataBlock aDataBlock : allDataBlocks) { + StreamExportParams streamExportParams = tethysExportParams.getStreamParams(aDataBlock); + if (streamExportParams == null || streamExportParams.selected == false) { + continue; // not interested in this one. + } + exportDataStream(aDataBlock, tethysExportParams, streamExportParams); + } + /* + * Then do whatever else is needed to complete the document. + */ + + dbxmlConnect.closeDatabase(); + + return true; + } + + /** + * find Deployment data. This is stored in a separate PAMGuard module, which may not + * be present. + * @return + */ + public DeploymentData findDeploymentData() { + /** + * What to do if this isn't present or is incomplete ? Should we be showing this in the + * main export dialog at some point ? More a Q for when we make a nicer UI later in the project. + */ + MetaDataContol metaControl = (MetaDataContol) PamController.getInstance().findControlledUnit(MetaDataContol.unitType); + if (metaControl == null) { + return null; + } + else { + return metaControl.getDeploymentData(); + } + } + + public SnapshotGeometry findArrayGeometrey() { + /* + * this should never be null, but again, we might want to put some warnings + * and exception handlers in here anyway. Really just an example to show how + * to find this. We'll need to dig a bit elsewhere to get more detailed + * hydrophone information. + */ + /* + * In PAMGuard hydrophones are assigned to streamers, which can have different methods for estimating + * their positions from GPS. The geometry is a sum of xyz in the streamer and xyz in the hydrophone object + * Within a streamer, hydrophones are considered rigid relative to each other. The stremer will floow + * a choice of modesl (rigid, threading, etc) to estimate it's position relative to the GPS track. Different + * errors are used when estimating localisation errors within and between streamers. + * The Snapshot geometry sorts a lot of this out for a point in time and will give back a single object + * which is most of what we'll be wanting. + */ + PamArray currentArray = ArrayManager.getArrayManager().getCurrentArray(); + SnapshotGeometry currentGeometry = currentArray.getSnapshotGeometry(PamCalendar.getTimeInMillis()); + /* + * The following lines of code show how to get more detailed calibration info for each + * hydrophone, but we'll have to think about the easiest way to repackage this for Tethys. + * e.g. this function could be modified to return the correct Tethys object in one go. + */ + ArrayList hydrophones = currentArray.getHydrophoneArray(); + /* + * each object in the list will have more detailed cal information for each phone. But + * for the full system calibration we'd need to go to the Acquisition module. + */ + AcquisitionControl daqControl = (AcquisitionControl) PamController.getInstance().findControlledUnit(AcquisitionControl.unitType); + if (daqControl != null) { + AcquisitionProcess daqProcess = daqControl.getAcquisitionProcess(); + for (int iPhone = 0; iPhone < hydrophones.size(); iPhone++) { + Hydrophone aPhone = hydrophones.get(iPhone); + double totalCal = -daqProcess.rawAmplitude2dB(1, iPhone, false); + System.out.printf("hydrophone %d has sensitivity %3.1fdB + gain %3.1fdB. Total calibration is %3.1fdB re1U/uPa\n", + iPhone, aPhone.getSensitivity(), aPhone.getPreampGain(), totalCal); + } + } + + + return currentGeometry; + } + + /** + * No idea if we need this or not. May want to return something different to void, e.g. + * a reference to the main object for a tethys export. I've no idea ! + * @param tethysExportParams2 + */ + private void exportGeneralData(TethysExportParams tethysExportParams) { + // TODO Auto-generated method stub + + } + + /** + * Here is where we export data for a specific data stream to Tethys. + * + * @param aDataBlock + * @param tethysExportParams + * @param streamExportParams + */ + private void exportDataStream(PamDataBlock aDataBlock, TethysExportParams tethysExportParams, + StreamExportParams streamExportParams) { + /** + * This will probably need to be passed additional parameters and may also want to return something + * other than void in order to build a bigger Tethys document. + */ + /* + * Some examples of how to do whatever is needed to get schema and data out of PAMGuard. + */ + /* + * first we'll probably want a reference to the module containing the data. + * in principle this can't get null, since the datablock was found be searching in + * the other direction. + */ + PamControlledUnit pamControlledUnit = aDataBlock.getParentProcess().getPamControlledUnit(); + + TethysDataProvider dataProvider = aDataBlock.getTethysDataProvider(); + + PamguardXMLWriter pamXMLWriter = PamguardXMLWriter.getXMLWriter(); + + if (dataProvider == null) { + return; + } + + TethysSchema tethysSchema = dataProvider.getSchema(); + /* + * the schema should have a Document object in it. If we wanted to turn + * that into an XML string we can ... + * (though I'd assume that having the Document is more useful) + */ + String schemaXMLString = pamXMLWriter.getAsString(tethysSchema.getXsd(), false); +// System.out.printf("Schema for %s is %s\n", aDataBlock.getDataName(), schemaXMLString); + + + /* + * Get the XML settings for that datablock. This is (or should be + * the parameters that were controlling that module, with adequate data about + * upstream modules). I think this has to go somewhere into the Detections document. + */ + Document doc = pamXMLWriter.writeOneModule(pamXMLWriter, System.currentTimeMillis()); + String moduleXML = null; + if (doc != null) { + // this string should be XML of all the settings for the module controlling this datablock. + moduleXML = pamXMLWriter.getAsString(doc, true); // change to false to get smaller xml + System.out.printf("Module settings for datablock %s are:\n", moduleXML); + System.out.println(moduleXML); + } + + + + + /** + * Now can go through the data. Probably, we'll want to go through all the data in + * the project, but we can hold off on that for now and just go for data that + * are in memory. We'll also have to think a lot about updating parts of the + * database which have been reprocessed - what we want to do, should eventually all + * be options set in the dialog and available within TethysExportParams + * For now though, we're just going to export data that are in memory. + * Once basic export is working, I can easily enough write something which will go + * through an entire data set, go through between two times, etc. + */ + // so this is a way of iterating through the data that are in memory, which will do for now .. + // do it with a data copy which can avoid synchronising the entire block for what may be a long time + // the copy function is itself synched, and is quite fast, so easier and safe this way + ArrayList dataCopy = aDataBlock.getDataCopy(); + for (PamDataUnit aData : dataCopy) { + // then we do whatever we need to do to convert this into + } + + + } + +} diff --git a/src/tethys/output/swing/TethysExportDialog.java b/src/tethys/output/swing/TethysExportDialog.java index d9477c52..ae86b315 100644 --- a/src/tethys/output/swing/TethysExportDialog.java +++ b/src/tethys/output/swing/TethysExportDialog.java @@ -6,7 +6,9 @@ import java.awt.GridBagLayout; import java.awt.Window; import java.util.ArrayList; +import javax.swing.JButton; import javax.swing.JCheckBox; +import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.border.TitledBorder; @@ -14,6 +16,7 @@ import PamController.PamController; import PamView.dialog.PamDialog; import PamView.dialog.PamGridBagContraints; import PamguardMVC.PamDataBlock; +import PamguardMVC.dataSelector.DataSelector; import tethys.TethysControl; import tethys.output.StreamExportParams; import tethys.output.TethysExportParams; @@ -81,22 +84,35 @@ public class TethysExportDialog extends PamDialog { streamsPanel.setLayout(new GridBagLayout()); GridBagConstraints c = new PamGridBagContraints(); dataStreamSets = findDataStreams(); + streamsPanel.add(new JLabel(" Data Stream ", JLabel.CENTER), c); + c.gridx++; + streamsPanel.add(new JLabel(" Data Select ", JLabel.CENTER), c); for (DataStreamSet aSet : dataStreamSets) { - streamsPanel.add(aSet.checkBox, c); + c.gridx = 0; c.gridy++; + streamsPanel.add(aSet.checkBox, c); + // try to add a data selector + DataSelector dataSelector = aSet.dataBlock.getDataSelector(tethysControl.getDataSelectName(), false); + if (dataSelector != null) { + c.gridx++; + JButton button = dataSelector.getDialogButton(this); + if (button != null) { + streamsPanel.add(button, c); + } + } } pack(); } /** - * Get a set of data blocks that have SQLLogging. - * @return + * Get a set of data blocks that can provide Tethys data. + * @return datablocks which can provide Tethys data */ private ArrayList findDataStreams() { ArrayList sets = new ArrayList<>(); ArrayList allDataBlocks = PamController.getInstance().getDataBlocks(); for (PamDataBlock aDataBlock : allDataBlocks) { - if (aDataBlock.getLogging() != null) { + if (aDataBlock.getTethysDataProvider() != null) { sets.add(new DataStreamSet(aDataBlock)); } } diff --git a/src/tethys/pamdata/AutoTethysProvider.java b/src/tethys/pamdata/AutoTethysProvider.java new file mode 100644 index 00000000..52243cc9 --- /dev/null +++ b/src/tethys/pamdata/AutoTethysProvider.java @@ -0,0 +1,42 @@ +package tethys.pamdata; + +import org.w3c.dom.Document; + +import PamguardMVC.PamDataBlock; +import PamguardMVC.PamDataUnit; +import generalDatabase.DBSchemaWriter; +import generalDatabase.SQLLogging; + +/** + * Automatically provides Tethys data based on the SQL database interface + * for a data block. + * @author dg50 + * + */ +public class AutoTethysProvider implements TethysDataProvider { + + private PamDataBlock pamDataBlock; + + public AutoTethysProvider(PamDataBlock pamDataBlock) { + this.pamDataBlock = pamDataBlock; + } + + @Override + public TethysSchema getSchema() { + SQLLogging logging = pamDataBlock.getLogging(); + if (logging == null) { + return null; + } + DBSchemaWriter schemaWriter = new DBSchemaWriter(); + Document doc = schemaWriter.generateDatabaseSchema(pamDataBlock, logging, logging.getTableDefinition()); + TethysSchema schema = new TethysSchema(doc); + return schema; + } + + @Override + public TethysDataPoint getDataPoint(PamDataUnit pamDataUnit) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/src/tethys/pamdata/TethysDataPoint.java b/src/tethys/pamdata/TethysDataPoint.java new file mode 100644 index 00000000..5eefdae1 --- /dev/null +++ b/src/tethys/pamdata/TethysDataPoint.java @@ -0,0 +1,18 @@ +package tethys.pamdata; + +import PamguardMVC.PamDataUnit; + +/** + * This will be a unit of Tethys Data, e.g. a Detection. + * Can it also be used for things like GPS data ? + * @author dg50 + * + */ +public class TethysDataPoint { + + public TethysDataPoint(PamDataUnit dataUnit) { + // TODO Auto-generated constructor stub + } + + +} diff --git a/src/tethys/pamdata/TethysDataProvider.java b/src/tethys/pamdata/TethysDataProvider.java new file mode 100644 index 00000000..ffa7df67 --- /dev/null +++ b/src/tethys/pamdata/TethysDataProvider.java @@ -0,0 +1,32 @@ +package tethys.pamdata; + +import PamguardMVC.PamDataUnit; + +/** + * Any PAMGuard data stream which can provide Detection data to PAMGuard will + * be able to return one of these. It will provide a schema and a function which + * can turn individual data units into data formatted for Tethys. The nature of how these + * work TBD. + * @author dg50 + * + */ +public interface TethysDataProvider { + + /** + * This gets the Tethys schema for this type of data in whatever + * form we decide it's best stored in, an XML string, or what ? + * @return + */ + public TethysSchema getSchema(); + + + /** + * This will convert a data unit for this provider into whatever format we need the + * data to be in for Tethys. Some base function but also bespoke stuff depending on the + * data type. Will probably need writing for every module individually? + * @param pamDataUnit + * @return + */ + public TethysDataPoint getDataPoint(PamDataUnit pamDataUnit); + +} diff --git a/src/tethys/pamdata/TethysSchema.java b/src/tethys/pamdata/TethysSchema.java new file mode 100644 index 00000000..4ddb9b08 --- /dev/null +++ b/src/tethys/pamdata/TethysSchema.java @@ -0,0 +1,32 @@ +package tethys.pamdata; + +import org.w3c.dom.Document; + +/** + * object for a Tethys Schema. This may just be a very simple + * wrapper around an XML string, or a JAXB object or something, + * but may get more sophisticated. TBD in discussions with SDSU + */ +public class TethysSchema { + + private Document schemaDoc; + + public TethysSchema(Document doc) { + this.setXsd(doc); + } + + /** + * @return the xsd + */ + public Document getXsd() { + return schemaDoc; + } + + /** + * @param xsd the xsd to set + */ + public void setXsd(Document xsd) { + this.schemaDoc = xsd; + } + +}