diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 234ad500..e0fb6d7f 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -37,6 +37,7 @@ jobs: dotnet test BlueM.Wave\tests\bin\x64\Debug\Wave.Tests.dll --settings BlueM.Wave\tests\tests.runsettings - name: Upload test results + if: always() uses: actions/upload-artifact@v6 with: name: test-results diff --git a/source/CHANGELOG.md b/source/CHANGELOG.md index d0b24602..c870175c 100644 --- a/source/CHANGELOG.md +++ b/source/CHANGELOG.md @@ -3,7 +3,15 @@ BlueM.Wave Release Notes Version X.X.X ------------- +FIXED: +* WEL files extracted from WLZIP archives when processing Talsim clipboard data are now deleted after use #136 + +CHANGED: +* Automatic extraction of WEL files from WLZIP archives now only occurs when processing Talsim clipboard data + API-CHANGES: +* New namespace `Parsers` containing classes for parsing file import instructions such as WVP files and Talsim clipboard content +* New helper method `Helpers.ParseInterpretation()` for parsing interpretation from strings and integers * Renamed `TimeSeriesFile.Write_File()` functions to `writeFile()` for consistency Version 2.16.0 diff --git a/source/CLI.vb b/source/CLI.vb index ec6e3ff0..6689ecb7 100644 --- a/source/CLI.vb +++ b/source/CLI.vb @@ -152,7 +152,7 @@ Friend Class CLI Throw New NotImplementedException("TEN files are currently not supported in the CLI!") Case TimeSeriesFile.FileExtensions.WVP - Dim wvp As New Fileformats.WVP(file_in) + Dim wvp As New Parsers.WVP(file_in) Dim wvpSeries As List(Of TimeSeries) = wvp.Process() Log.AddLogEntry(Log.levels.info, $"Imported {wvpSeries.Count} time series") tsList.AddRange(wvpSeries) diff --git a/source/Classes/TimeSeriesFile.vb b/source/Classes/TimeSeriesFile.vb index 480b17d5..ef841db9 100644 --- a/source/Classes/TimeSeriesFile.vb +++ b/source/Classes/TimeSeriesFile.vb @@ -664,14 +664,7 @@ Public MustInherit Class TimeSeriesFile 'Check whether the file exists If Not IO.File.Exists(file) Then - 'A WEL/WBL file may be zipped within a WLZIP file, so try extracting it from there - If fileExt = FileExtensions.WEL Or fileExt = FileExtensions.WBL Then - If Not Fileformats.WEL.extractFromWLZIP(file) Then - Throw New IO.FileNotFoundException($"File '{file}' not found!") - End If - Else - Throw New IO.FileNotFoundException($"File '{file}' not found!") - End If + Throw New IO.FileNotFoundException($"File '{file}' not found!") End If 'set default diff --git a/source/Controllers/WaveController.vb b/source/Controllers/WaveController.vb index f7d5c705..abbe5403 100644 --- a/source/Controllers/WaveController.vb +++ b/source/Controllers/WaveController.vb @@ -561,15 +561,15 @@ Friend Class WaveController End If tsList.Add(ts) Next - Call Fileformats.WVP.writeFile(tsList, dlg.FileName, - saveRelativePaths:=dlg.SaveRelativePaths, - saveTitle:=dlg.SaveTitle, - saveUnit:=dlg.SaveUnit, - saveInterpretation:=dlg.SaveInterpretation, - saveColor:=dlg.SaveColor, - saveLineStyle:=dlg.SaveLineStyle, - saveLineWidth:=dlg.SaveLineWidth, - savePointsVisibility:=dlg.SavePointsVisibility + Call Parsers.WVP.writeFile(tsList, dlg.FileName, + saveRelativePaths:=dlg.SaveRelativePaths, + saveTitle:=dlg.SaveTitle, + saveUnit:=dlg.SaveUnit, + saveInterpretation:=dlg.SaveInterpretation, + saveColor:=dlg.SaveColor, + saveLineStyle:=dlg.SaveLineStyle, + saveLineWidth:=dlg.SaveLineWidth, + savePointsVisibility:=dlg.SavePointsVisibility ) MsgBox($"Wave project file {dlg.FileName} saved.", MsgBoxStyle.Information) End If diff --git a/source/FileFormats/WEL.vb b/source/FileFormats/WEL.vb index e8080b3c..2dd1edc3 100644 --- a/source/FileFormats/WEL.vb +++ b/source/FileFormats/WEL.vb @@ -310,56 +310,6 @@ Namespace Fileformats End Function - ''' - ''' Attempts to extract a specified WEL file from a WLZIP file of the same name - ''' - ''' path to WEL file - ''' True if successful - ''' TALSIM specific - Public Shared Function extractFromWLZIP(file As String) As Boolean - - Dim file_wlzip As String - Dim filename As String - Dim zipEntryFound As Boolean = False - Dim success As Boolean = False - - 'determine WLZIP filename for files ending with .WEL (may also be e.g. .KTR.WEL, .CHLO.WEL, etc.) - Dim m As Match = Regex.Match(file, "^(.+?)(\.[a-z]+)?\.WEL$", RegexOptions.IgnoreCase) - If m.Success Then - file_wlzip = $"{m.Groups(1)}.WLZIP" - - If IO.File.Exists(file_wlzip) Then - - Log.AddLogEntry(Log.levels.info, $"Looking for file in {file_wlzip} ...") - filename = IO.Path.GetFileName(file) - - Dim zip As IO.Compression.ZipArchive = IO.Compression.ZipFile.OpenRead(file_wlzip) - - For Each entry As IO.Compression.ZipArchiveEntry In zip.Entries - If entry.Name.ToLower() = filename.ToLower() Then - zipEntryFound = True - 'extract file from zip archive - Log.AddLogEntry(Log.levels.info, $"Extracting file from {file_wlzip} ...") - Dim fs As New IO.FileStream(file, FileMode.CreateNew) - entry.Open().CopyTo(fs) - fs.Flush() - fs.Close() - success = True - Exit For - End If - Next - - If Not zipEntryFound Then - Log.AddLogEntry(Log.levels.error, $"File {filename} not found in {file_wlzip}!") - End If - - End If - End If - - Return success - - End Function - #End Region 'Methoden End Class diff --git a/source/Helpers.vb b/source/Helpers.vb index fad32966..9f1e30b9 100644 --- a/source/Helpers.vb +++ b/source/Helpers.vb @@ -123,6 +123,36 @@ Public Module Helpers End Function + ''' + ''' Parses a string to a TimeSeries.InterpretationEnum value. + ''' If the string does not match any of the enum names, TimeSeries.InterpretationEnum.Undefined is returned and a warning is logged. + ''' + ''' The string to be parsed + ''' The corresponding TimeSeries.InterpretationEnum value + Public Function ParseInterpretation(interpretationString As String) As TimeSeries.InterpretationEnum + If Not [Enum].IsDefined(GetType(TimeSeries.InterpretationEnum), interpretationString) Then + Log.AddLogEntry(levels.warning, $"Interpretation {interpretationString} is not recognized!") + Return TimeSeries.InterpretationEnum.Undefined + Else + Return [Enum].Parse(GetType(TimeSeries.InterpretationEnum), interpretationString) + End If + End Function + + ''' + ''' Parses an integer to a TimeSeries.InterpretationEnum value. + ''' If the integer does not match any of the enum values, TimeSeries.InterpretationEnum.Undefined is returned and a warning is logged. + ''' + ''' The integer value to be parsed + ''' The corresponding TimeSeries.InterpretationEnum value + Public Function ParseInterpretation(interpretationValue As Integer) As TimeSeries.InterpretationEnum + If Not [Enum].IsDefined(GetType(TimeSeries.InterpretationEnum), interpretationValue) Then + Log.AddLogEntry(levels.warning, $"Interpretation {interpretationValue} is not recognized!") + Return TimeSeries.InterpretationEnum.Undefined + Else + Return [Enum].Parse(GetType(TimeSeries.InterpretationEnum), interpretationValue) + End If + End Function + ''' ''' Returns a specified color palette ''' diff --git a/source/Parsers/Parser.vb b/source/Parsers/Parser.vb new file mode 100644 index 00000000..301c3fb3 --- /dev/null +++ b/source/Parsers/Parser.vb @@ -0,0 +1,224 @@ +'BlueM.Wave +'Copyright (C) BlueM Dev Group +' +' +'This program is free software: you can redistribute it and/or modify +'it under the terms of the GNU Lesser General Public License as published by +'the Free Software Foundation, either version 3 of the License, or +'(at your option) any later version. +' +'This program is distributed in the hope that it will be useful, +'but WITHOUT ANY WARRANTY; without even the implied warranty of +'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +'GNU Lesser General Public License for more details. +' +'You should have received a copy of the GNU Lesser General Public License +'along with this program. If not, see . +' +Namespace Parsers + + ''' + ''' Base class for parsing file import instructions + ''' + Public MustInherit Class Parser + + ''' + ''' A reference to a file to be imported with all information needed for importing series from that file + ''' + Protected Class FileReference + + ''' + ''' The path to the file to be imported + ''' + Public path As String + + ''' + ''' The series to be imported from the file with their options, where the key is the name of the series as it appears in the file and the value is a SeriesOptions object containing options for importing that series + ''' An empty dictionary means that all series contained in the file should be imported with default options + ''' + Public series As Dictionary(Of String, SeriesOptions) + + ''' + ''' File import settings as key value pairs, e.g. separator, date format, etc. + ''' An empty dictionary means that default settings should be used for importing the file. + ''' + Public settings As Dictionary(Of String, String) + + Public Sub New() + Me.series = New Dictionary(Of String, SeriesOptions) + Me.settings = New Dictionary(Of String, String) + End Sub + + End Class + + ''' + ''' Holds options for importing a series, e.g. display options, custom title and unit, etc. + ''' + Protected Class SeriesOptions + Public title As String + Public unit As String + Public interpretation As TimeSeries.InterpretationEnum? + Public displayOptions As TimeSeriesDisplayOptions + Public Sub New() + Me.displayOptions = New TimeSeriesDisplayOptions() + End Sub + End Class + + ''' + ''' The path to the input file + ''' + Protected InputFile As String + + ''' + ''' The input text to be parsed + ''' + Protected InputText As String + + Protected FileReferences As New List(Of FileReference) + + ''' + ''' Instantiates a new Parser instance with either a file or text input and calls the Parse method to parse the input + ''' + ''' The path to the input file + ''' The input text + Public Sub New(Optional inputfile As String = Nothing, Optional inputtext As String = Nothing) + If IsNothing(inputfile) And IsNothing(inputtext) Then + Throw New ArgumentException("Either a file or text input must be provided!") + ElseIf Not IsNothing(inputfile) And Not IsNothing(inputtext) Then + Throw New ArgumentException("Only one of file or text input can be provided!") + End If + Me.InputFile = inputfile + If Not IsNothing(inputfile) Then + Me.InputText = IO.File.ReadAllText(inputfile, Text.Encoding.UTF8) + Else + Me.InputText = inputtext + End If + Call Me.Parse() + End Sub + + Public Shared Function verifyFormat() As Boolean + 'default implementation always returns true, can be overridden in subclasses to implement specific format verification + Return True + End Function + + ''' + ''' Parses the input and stores the results in the FileReferences list + ''' + Protected MustOverride Sub Parse() + + ''' + ''' Processes the FileReferences list by reading the specified series from the files and returning them as a list + ''' + ''' a list of time series + Public Function Process() As List(Of TimeSeries) + + Dim tsList As New List(Of TimeSeries) + + 'loop over file list + For Each fileRef As FileReference In FileReferences + + Log.AddLogEntry(Log.levels.info, $"Reading file {fileRef.path} ...") + + 'get an instance of the file + Dim fileInstance As TimeSeriesFile = TimeSeriesFile.getInstance(fileRef.path) + + 'apply custom file import settings + If fileRef.settings.Count > 0 Then + For Each key As String In fileRef.settings.Keys + Dim value As String = fileRef.settings(key) + Try + Select Case key.ToLower() + Case "iscolumnseparated" + fileInstance.IsColumnSeparated = If(value.ToLower() = "true", True, False) + Case "separator" + fileInstance.Separator = New Character(value) + Case "dateformat" + fileInstance.Dateformat = value + Case "decimalseparator" + fileInstance.DecimalSeparator = New Character(value) + Case "ilineheadings" + fileInstance.iLineHeadings = Convert.ToInt32(value) + Case "ilineunits" + fileInstance.iLineUnits = Convert.ToInt32(value) + Case "ilinedata" + fileInstance.iLineData = Convert.ToInt32(value) + Case "useunits" + fileInstance.UseUnits = If(value.ToLower() = "true", True, False) + Case "columnwidth" + fileInstance.ColumnWidth = Convert.ToInt32(value) + Case "datetimecolumnindex" + fileInstance.DateTimeColumnIndex = Convert.ToInt32(value) + Case Else + Log.AddLogEntry(Log.levels.warning, $"Setting '{key}' was not recognized and was ignored!") + End Select + Catch ex As Exception + Log.AddLogEntry(Log.levels.warning, $"Setting '{key}' with value '{value}' could not be parsed and was ignored!") + End Try + Next + 'reread columns with new settings + fileInstance.readSeriesInfo() + End If + + 'select series for importing + If fileRef.series.Count = 0 Then + 'read all series contained in the file + Call fileInstance.selectAllSeries() + Else + 'loop over series names + Dim seriesNames As List(Of String) = fileRef.series.Keys.ToList() + Dim seriesNotFound As New List(Of String) + For Each seriesName As String In seriesNames + Dim found As Boolean = fileInstance.selectSeries(seriesName) + If Not found Then + seriesNotFound.Add(seriesName) + Log.AddLogEntry(Log.levels.error, $"Series {seriesName} not found in file, skipping series!") + End If + Next + 'remove series that were not found from the list + For Each seriesName As String In seriesNotFound + seriesNames.Remove(seriesName) + Next + 'if no series remain to be imported, abort reading the file altogether + If seriesNames.Count = 0 Then + Log.AddLogEntry(Log.levels.error, "No series left to import, skipping file!") + Continue For + End If + + End If + + 'read the file + fileInstance.readFile() + + 'Log + Call Log.AddLogEntry(Log.levels.info, $"File '{fileRef.path}' imported successfully!") + + 'store the series + For Each ts As TimeSeries In fileInstance.TimeSeries.Values + 'set series options + If fileRef.series.ContainsKey(ts.Title) Then + Dim options As SeriesOptions = fileRef.series(ts.Title) + 'options affecting the time series itself + If Not IsNothing(options.title) Then + ts.Title = options.title + End If + If Not IsNothing(options.unit) Then + ts.Unit = options.unit + End If + If options.interpretation.HasValue Then + ts.Interpretation = options.interpretation + End If + 'display options + ts.DisplayOptions = options.displayOptions + End If + 'store the time series in the list + tsList.Add(ts) + Next + Next + + Return tsList + + End Function + + End Class + +End Namespace \ No newline at end of file diff --git a/source/Parsers/TalsimClipboard.vb b/source/Parsers/TalsimClipboard.vb new file mode 100644 index 00000000..7e5b15ff --- /dev/null +++ b/source/Parsers/TalsimClipboard.vb @@ -0,0 +1,304 @@ +'BlueM.Wave +'Copyright (C) BlueM Dev Group +' +' +'This program is free software: you can redistribute it and/or modify +'it under the terms of the GNU Lesser General Public License as published by +'the Free Software Foundation, either version 3 of the License, or +'(at your option) any later version. +' +'This program is distributed in the hope that it will be useful, +'but WITHOUT ANY WARRANTY; without even the implied warranty of +'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +'GNU Lesser General Public License for more details. +' +'You should have received a copy of the GNU Lesser General Public License +'along with this program. If not, see . +' +Imports System.Text.RegularExpressions + +Namespace Parsers + + ''' + ''' Class for parsing Talsim clipboard content + ''' + Public Class TalsimClipboard + Inherits Parser + + Public Sub New(clipboardtext As String) + MyBase.New(inputtext:=clipboardtext) + End Sub + + Public Overloads Shared Function verifyFormat(clipboardtext As String) As Boolean + 'check if content contains expected header + If clipboardtext.Contains("SydroTyp=SydroErgZre") Or + clipboardtext.Contains("SydroTyp=SydroBinZre") Then + Return True + Else + Return False + End If + End Function + + ''' + ''' Parses the clipboard content + ''' + Protected Overrides Sub Parse() + + 'Examples: + + '[SETTINGS] + 'Count = 1 + '[Zeitreihe1] + 'SydroTyp=SydroErgZre + 'ZRFormat=4 + 'ID=362 + 'Extension=.WEL + 'Kennung=S000 + 'KennungLang={S000} {1AB, HYO} Ablauf_1 + 'Zustand=1AB + 'Datei=D:\Talsim-NG\customers\WVER\projectData\felix\dataBase\Felix_data\00000362.WEL + 'GeaendertAm= + 'Modell=TALSIM + 'Herkunft=simuliert + 'Interpretation=2 + 'SimVariante=Test Langzeit/HWMerkmal_HWGK_v02 + 'Simulation=Test Langzeit + 'Einheit=m3/s + 'EndZeitreihe + + '[SETTINGS] + 'Count=2 + '[Zeitreihe1] + 'SydroTyp=SydroBinZre + 'ZRFormat=99 + 'ID=1041 + 'Extension=.BIN + 'Kennung=Sce10, E038, C38 (TA_Tekeze TK 04B) + 'KennungLang=Sce10, E038, C38 (TA_Tekeze TK 04B), m3/s + 'Datei=C:\Talsim-NG\customers\Nile\projectData\hubert\dataBase\hubert_zre\00001041.BIN + 'Einheit=m3/s + 'Modell=TALSIM + 'Interpretation=1 + 'EndZeitreihe + '[Zeitreihe2] + 'SydroTyp=SydroBinZre + 'ZRFormat=99 + 'ID=1042 + 'Extension=.BIN + 'Kennung=Sce10, E039, C39 (TA_TK5) + 'KennungLang=Sce10, E039, C39 (TA_TK5), m3/s + 'Datei=C:\Talsim-NG\customers\Nile\projectData\hubert\dataBase\hubert_zre\00001042.BIN + 'Einheit=m3/s + 'Modell=TALSIM + 'Interpretation=1 + 'EndZeitreihe + + 'parse clipboard contents + Dim m As Match + Dim i_series As Integer + Dim parts() As String + Dim zreblock As Boolean + Dim data As New List(Of Dictionary(Of String, String)) '[{zreparams1},{zreparams2},...] + Dim file, name As String + + zreblock = False + For Each line As String In InputText.Split(New String() {vbCr, vbLf}, StringSplitOptions.RemoveEmptyEntries) + + line = line.Trim() + + m = Regex.Match(line, "\[Zeitreihe(\d+)\]") + If m.Success Then + i_series = m.Groups(1).Value + data.Add(New Dictionary(Of String, String)) + zreblock = True + End If + + If zreblock Then + If line.Contains("=") Then + parts = line.Split("=") + data(i_series - 1).Add(parts(0), parts(1)) + ElseIf line = "EndZeitreihe" Then + zreblock = False + Continue For + End If + End If + + Next + + If data.Count = 0 Then + Throw New Exception("No series could be parsed from TALSIM clipboard content!") + End If + + 'initiate parsing of series + For Each params As Dictionary(Of String, String) In data + + ' check all required parameters are present + Dim expectedKeys As New List(Of String) From { + "Datei", + "ZRFormat", + "Kennung", + "Interpretation" + } + For Each key As String In expectedKeys + If Not params.ContainsKey(key) Then + Throw New Exception($"Missing required entry '{key}' in clipboard content!") + End If + Next + + file = params("Datei") + + Select Case params("ZRFormat") + Case "4" 'WEL file + + If Not params.ContainsKey("Zustand") Then + Throw New Exception("Missing required entry 'Zustand' in clipboard content!") + End If + + 'build series name + If params("Kennung") = "ZPG" Then + 'handle control groups + name = "KGRP_" & params("Zustand") + Else + name = params("Kennung").PadRight(4, " ") & "_" & params("Zustand") + End If + + Dim options As New SeriesOptions() With { + .title = name, + .interpretation = Helpers.ParseInterpretation(Integer.Parse(params("Interpretation"))) + } + If params.ContainsKey("Einheit") Then + options.unit = params("Einheit") + End If + + Dim fileRef As New FileReference() With { + .path = file, + .series = New Dictionary(Of String, SeriesOptions)() From { + {name, options} + } + } + FileReferences.Add(fileRef) + + Case "99" 'BIN file + + If Not params.ContainsKey("Einheit") Then + Throw New Exception("Missing required entry 'Einheit' in clipboard content!") + End If + + name = params("Kennung") + + Dim options As New SeriesOptions() With { + .title = name, + .unit = params("Einheit"), + .interpretation = Helpers.ParseInterpretation(Integer.Parse(params("Interpretation"))) + } + + Dim fileRef As New FileReference() With { + .path = file, + .series = New Dictionary(Of String, SeriesOptions)() From { + { + IO.Path.GetFileName(file), options + } + } + } + FileReferences.Add(fileRef) + + Case Else + Throw New Exception($"Unsupported value {params("ZRFormat")} for ZRFormat!") + + End Select + + Next + + End Sub + + ''' + ''' Wraps the base Process() method to check for WEL/WBL files that do not exist + ''' and attempt to extract them from WLZIP files if possible before processing, + ''' and then deletes any extracted files after processing + ''' + ''' A list of processed time series + Public Overloads Function Process() As List(Of TimeSeries) + + 'check for WEL/WBL that do not exist and try to extract them from WLZIP files if possible + Dim extractedFiles As New List(Of String) + For Each fileRef As FileReference In FileReferences + If Not IO.File.Exists(fileRef.path) Then + Dim fileExt As String = IO.Path.GetExtension(fileRef.path).ToUpper() + If fileExt = TimeSeriesFile.FileExtensions.WEL Or fileExt = TimeSeriesFile.FileExtensions.WBL Then + If TalsimClipboard.extractFromWLZIP(fileRef.path) Then + 'remember the file so that we can delete it later + extractedFiles.Add(fileRef.path) + End If + End If + End If + Next + + 'process the files as usual + Dim tsList As List(Of TimeSeries) = MyBase.Process() + + 'delete any extracted files + For Each file As String In extractedFiles + Try + IO.File.Delete(file) + Catch ex As Exception + Log.AddLogEntry(Log.levels.warning, $"Could not delete extracted file {file}: {ex.Message}") + End Try + Next + + Return tsList + + End Function + + ''' + ''' Attempts to extract a specified WEL file from a WLZIP file of the same name + ''' + ''' path to WEL file + ''' True if successful + ''' TALSIM specific + Public Shared Function extractFromWLZIP(file As String) As Boolean + + Dim file_wlzip As String + Dim filename As String + Dim zipEntryFound As Boolean = False + Dim success As Boolean = False + + 'determine WLZIP filename for files ending with .WEL (may also be e.g. .KTR.WEL, .CHLO.WEL, etc.) + Dim m As Match = Regex.Match(file, "^(.+?)(\.[a-z]+)?\.WEL$", RegexOptions.IgnoreCase) + If m.Success Then + file_wlzip = $"{m.Groups(1)}.WLZIP" + + If IO.File.Exists(file_wlzip) Then + + Log.AddLogEntry(Log.levels.info, $"Looking for file in {file_wlzip} ...") + filename = IO.Path.GetFileName(file) + + Dim zip As IO.Compression.ZipArchive = IO.Compression.ZipFile.OpenRead(file_wlzip) + + For Each entry As IO.Compression.ZipArchiveEntry In zip.Entries + If entry.Name.ToLower() = filename.ToLower() Then + zipEntryFound = True + 'extract file from zip archive + Log.AddLogEntry(Log.levels.info, $"Extracting file from {file_wlzip} ...") + Dim fs As New IO.FileStream(file, IO.FileMode.CreateNew) + entry.Open().CopyTo(fs) + fs.Flush() + fs.Close() + success = True + Exit For + End If + Next + + If Not zipEntryFound Then + Log.AddLogEntry(Log.levels.error, $"File {filename} not found in {file_wlzip}!") + End If + + End If + End If + + Return success + + End Function + + End Class + +End Namespace \ No newline at end of file diff --git a/source/FileFormats/WVP.vb b/source/Parsers/WVP.vb similarity index 59% rename from source/FileFormats/WVP.vb rename to source/Parsers/WVP.vb index 97b6a831..ec7103de 100644 --- a/source/FileFormats/WVP.vb +++ b/source/Parsers/WVP.vb @@ -17,54 +17,29 @@ ' Imports System.Text.RegularExpressions -Namespace Fileformats +Namespace Parsers ''' - ''' Class for importing a wave project file + ''' Class for parsing a wave project file ''' https://wiki.bluemodel.org/index.php/Wave_project_file ''' Public Class WVP - - Private projectfile As String - - Private Structure FileEntry - Dim path As String 'path to file - Dim series As Dictionary(Of String, SeriesOptions) 'series name -> options - Dim settings As Dictionary(Of String, String) 'file import settings as key value pairs, e.g. separator, date format, etc. - End Structure - - Private Structure SeriesOptions - Dim title As String - Dim unit As String - Dim color As String - Dim linestyle As String - Dim linewidth As String - Dim interpretation As String - Dim showpoints As String - End Structure - - Private fileEntries As New List(Of FileEntry) + Inherits Parser Public Sub New(file As String) - - Me.projectfile = file - - Call Me.Parse() - + MyBase.New(inputfile:=file) End Sub ''' ''' Parses the project file ''' - Private Sub Parse() + Protected Overrides Sub Parse() - Dim fstr As IO.FileStream - Dim strRead As IO.StreamReader Dim line, parts(), file, seriesName As String - Log.AddLogEntry(Log.levels.info, $"Parsing Wave project file {projectfile} ...") + Log.AddLogEntry(Log.levels.info, $"Parsing Wave project file {MyBase.InputFile} ...") - 'read project file + 'parse Wave project file 'file format (all whitespace is optional): ' @@ -76,20 +51,15 @@ Namespace Fileformats ' series=series4 ' series=series5 ' - fstr = New IO.FileStream(projectfile, IO.FileMode.Open) - strRead = New IO.StreamReader(fstr, Text.Encoding.UTF8) - file = "" - line = strRead.ReadLine() - While Not IsNothing(line) + For Each line In Me.inputText.Split({vbCrLf, vbLf}, StringSplitOptions.RemoveEmptyEntries) line = line.Trim() 'get rid of whitespace If line.StartsWith("#") Then 'skip comments - line = strRead.ReadLine() - Continue While + Continue For End If If line.ToLower().StartsWith("file=") Then @@ -97,10 +67,10 @@ Namespace Fileformats file = line.Split("=".ToCharArray(), 2)(1).Trim() If Not IO.Path.IsPathRooted(file) Then 'it's a relative path: construct the full path relative to the project file - file = IO.Path.GetFullPath(IO.Path.Combine(IO.Path.GetDirectoryName(projectfile), file)) + file = IO.Path.GetFullPath(IO.Path.Combine(IO.Path.GetDirectoryName(MyBase.InputFile), file)) End If 'store file entry - fileEntries.Add(New FileEntry With { + FileReferences.Add(New FileReference With { .path = file, .series = New Dictionary(Of String, SeriesOptions)(), .settings = New Dictionary(Of String, String)() @@ -128,15 +98,7 @@ Namespace Fileformats If m.Success Then seriesName = m.Groups("name").Value.Trim() 'check for additional series options - 'by default, series options are nothing - Dim options As New SeriesOptions With { - .title = Nothing, - .unit = Nothing, - .color = Nothing, - .linestyle = Nothing, - .linewidth = Nothing, - .interpretation = Nothing - } + Dim options As New SeriesOptions() If m.Groups("options").Success Then 'parse series options Dim optionString As String = m.Groups("optionstring").Value.Trim() @@ -156,16 +118,16 @@ Namespace Fileformats options.title = value Case "unit" options.unit = value + Case "interpretation" + options.interpretation = Helpers.ParseInterpretation(value) Case "color" - options.color = value + options.displayOptions.SetColor(value) Case "linestyle" - options.linestyle = value + options.displayOptions.SetLineStyle(value) Case "linewidth" - options.linewidth = value - Case "interpretation" - options.interpretation = value + options.displayOptions.SetLineWidth(value) Case "showpoints" - options.showpoints = value + options.displayOptions.SetShowPoints(value) Case Else Log.AddLogEntry(levels.warning, $"Series import option keyword {keyword} not recognized!") End Select @@ -173,9 +135,9 @@ Namespace Fileformats End If End If 'add series to last entry of filelist - If fileEntries.Count > 0 Then - If Not fileEntries.Last().series.ContainsKey(seriesName) Then - fileEntries.Last().series.Add(seriesName, options) + If FileReferences.Count > 0 Then + If Not FileReferences.Last().series.ContainsKey(seriesName) Then + FileReferences.Last().series.Add(seriesName, options) Else 'duplicate series Log.AddLogEntry(Log.levels.warning, $"Series {seriesName} is specified more than once, only the first mention will be processed!") @@ -195,9 +157,9 @@ Namespace Fileformats key = parts(0).Trim() value = parts(1).Trim() 'add settings to last entry of file list - If fileEntries.Count > 0 Then - If Not fileEntries.Last().settings.ContainsKey(key) Then - fileEntries.Last().settings.Add(key, value) + If FileReferences.Count > 0 Then + If Not FileReferences.Last().settings.ContainsKey(key) Then + FileReferences.Last().settings.Add(key, value) Else 'duplicate setting Log.AddLogEntry(Log.levels.warning, $"File import setting {key} is specified more than once, only the first mention will be processed!") @@ -209,141 +171,9 @@ Namespace Fileformats Else 'ignore any other lines End If - line = strRead.ReadLine() - End While - - strRead.Close() - fstr.Close() - - End Sub - - ''' - ''' Reads all timeseries from all files as specified in the project file - ''' - ''' the list of time series - Public Function Process() As List(Of TimeSeries) - - Dim tsList As New List(Of TimeSeries) - - 'loop over file list - For Each fileEntry As FileEntry In fileEntries - - Log.AddLogEntry(Log.levels.info, $"Reading file {fileEntry.path} ...") - - 'get an instance of the file - Dim fileInstance As TimeSeriesFile = TimeSeriesFile.getInstance(fileEntry.path) - - 'apply custom file import settings - If fileEntry.settings.Count > 0 Then - For Each key As String In fileEntry.settings.Keys - Dim value As String = fileEntry.settings(key) - Try - Select Case key.ToLower() - Case "iscolumnseparated" - fileInstance.IsColumnSeparated = If(value.ToLower() = "true", True, False) - Case "separator" - fileInstance.Separator = New Character(value) - Case "dateformat" - fileInstance.Dateformat = value - Case "decimalseparator" - fileInstance.DecimalSeparator = New Character(value) - Case "ilineheadings" - fileInstance.iLineHeadings = Convert.ToInt32(value) - Case "ilineunits" - fileInstance.iLineUnits = Convert.ToInt32(value) - Case "ilinedata" - fileInstance.iLineData = Convert.ToInt32(value) - Case "useunits" - fileInstance.UseUnits = If(value.ToLower() = "true", True, False) - Case "columnwidth" - fileInstance.ColumnWidth = Convert.ToInt32(value) - Case "datetimecolumnindex" - fileInstance.DateTimeColumnIndex = Convert.ToInt32(value) - Case Else - Log.AddLogEntry(Log.levels.warning, $"Setting '{key}' was not recognized and was ignored!") - End Select - Catch ex As Exception - Log.AddLogEntry(Log.levels.warning, $"Setting '{key}' with value '{value}' could not be parsed and was ignored!") - End Try - Next - 'reread columns with new settings - fileInstance.readSeriesInfo() - End If - - 'select series for importing - If fileEntry.series.Count = 0 Then - 'read all series contained in the file - Call fileInstance.selectAllSeries() - Else - 'loop over series names - Dim seriesNames As List(Of String) = fileEntry.series.Keys.ToList() - Dim seriesNotFound As New List(Of String) - For Each seriesName As String In seriesNames - Dim found As Boolean = fileInstance.selectSeries(seriesName) - If Not found Then - seriesNotFound.Add(seriesName) - Log.AddLogEntry(Log.levels.error, $"Series {seriesName} not found in file, skipping series!") - End If - Next - 'remove series that were not found from the list - For Each seriesName As String In seriesNotFound - seriesNames.Remove(seriesName) - Next - 'if no series remain to be imported, abort reading the file altogether - If seriesNames.Count = 0 Then - Log.AddLogEntry(Log.levels.error, "No series left to import, skipping file!") - Continue For - End If - - End If - - 'read the file - fileInstance.readFile() - - 'Log - Call Log.AddLogEntry(Log.levels.info, $"File '{fileEntry.path}' imported successfully!") - - 'store the series - For Each ts As TimeSeries In fileInstance.TimeSeries.Values - 'set series options - If fileEntry.series.ContainsKey(ts.Title) Then - Dim options As SeriesOptions = fileEntry.series(ts.Title) - 'options affecting the time series itself - If Not IsNothing(options.title) Then - ts.Title = options.title - End If - If Not IsNothing(options.unit) Then - ts.Unit = options.unit - End If - If Not IsNothing(options.interpretation) Then - If Not [Enum].IsDefined(GetType(TimeSeries.InterpretationEnum), options.interpretation) Then - Log.AddLogEntry(levels.warning, $"Interpretation {options.interpretation} is not recognized!") - Else - ts.Interpretation = [Enum].Parse(GetType(TimeSeries.InterpretationEnum), options.interpretation) - End If - End If - 'display options - If Not IsNothing(options.color) Then - ts.DisplayOptions.SetColor(options.color) - End If - If Not IsNothing(options.linestyle) Then - ts.DisplayOptions.SetLineStyle(options.linestyle) - End If - If Not IsNothing(options.linewidth) Then - ts.DisplayOptions.SetLineWidth(options.linewidth) - End If - If Not IsNothing(options.showpoints) Then - ts.DisplayOptions.SetShowPoints(options.showpoints) - End If - End If - 'store the time series in the list - tsList.Add(ts) - Next Next - Return tsList - - End Function + End Sub ''' ''' Write a Wave project file diff --git a/source/Wave.vb b/source/Wave.vb index 127fe8dc..df376953 100644 --- a/source/Wave.vb +++ b/source/Wave.vb @@ -196,12 +196,10 @@ Public Class Wave Private Sub Load_WVP(projectfile As String) Try - Dim tsList As List(Of TimeSeries) - Call Log.AddLogEntry(Log.levels.info, $"Loading Wave project file '{projectfile}'...") - Dim wvp As New Fileformats.WVP(projectfile) - tsList = wvp.Process() + Dim wvp As New Parsers.WVP(projectfile) + Dim tsList As List(Of TimeSeries) = wvp.Process() Call Log.AddLogEntry(Log.levels.info, $"Imported {tsList.Count} timeseries") @@ -240,30 +238,25 @@ Public Class Wave Dim clipboardtext As String clipboardtext = Clipboard.GetText(TextDataFormat.Text) - If clipboardtext.Contains("SydroTyp=SydroErgZre") Or - clipboardtext.Contains("SydroTyp=SydroBinZre") Then - 'it's a clipboard entry from TALSIM! - + If Parsers.TalsimClipboard.verifyFormat(clipboardtext) Then 'ask the user for confirmation dlgres = MessageBox.Show($"TALSIM clipboard content detected!{eol}Load series in Wave?", "Load from clipboard", MessageBoxButtons.YesNo, MessageBoxIcon.Question) - If Not dlgres = Windows.Forms.DialogResult.Yes Then - Exit Sub + If dlgres = Windows.Forms.DialogResult.Yes Then + Call Me.LoadFromClipboard_TALSIM(clipboardtext) End If - Call Me.LoadFromClipboard_TALSIM(clipboardtext) Else - 'ask the user whether to attempt plain text import + 'ask the user whether to attempt CSV import dlgres = MessageBox.Show("Attempt to load clipboard text content in Wave as CSV data?", "Load from clipboard", MessageBoxButtons.YesNo, MessageBoxIcon.Question) - If Not dlgres = Windows.Forms.DialogResult.Yes Then - Exit Sub + If dlgres = Windows.Forms.DialogResult.Yes Then + 'save as temp text file and then load file + Dim tmpfile As String = IO.Path.GetTempFileName() + Using writer As New IO.StreamWriter(tmpfile, False, Helpers.DefaultEncoding) + writer.Write(clipboardtext) + End Using + Call Me.Import_File(tmpfile) + 'delete temp file after import + IO.File.Delete(tmpfile) End If - 'save as temp text file and then load file - Dim tmpfile As String = IO.Path.GetTempFileName() - Using writer As New IO.StreamWriter(tmpfile, False, Helpers.DefaultEncoding) - writer.Write(clipboardtext) - End Using - Call Me.Import_File(tmpfile) - 'delete temp file after import - IO.File.Delete(tmpfile) End If Else MessageBox.Show("No usable clipboard content detected!", "Load from clipboard", MessageBoxButtons.OK, MessageBoxIcon.Error) @@ -285,170 +278,27 @@ Public Class Wave ''' Private Sub LoadFromClipboard_TALSIM(clipboardtext As String) - 'Examples: - - '[SETTINGS] - 'Count = 1 - '[Zeitreihe1] - 'SydroTyp=SydroErgZre - 'ZRFormat=4 - 'ID=362 - 'Extension=.WEL - 'Kennung=S000 - 'KennungLang={S000} {1AB, HYO} Ablauf_1 - 'Zustand=1AB - 'Datei=D:\Talsim-NG\customers\WVER\projectData\felix\dataBase\Felix_data\00000362.WEL - 'GeaendertAm= - 'Modell=TALSIM - 'Herkunft=simuliert - 'Interpretation=2 - 'SimVariante=Test Langzeit/HWMerkmal_HWGK_v02 - 'Simulation=Test Langzeit - 'Einheit=m3/s - 'EndZeitreihe - - '[SETTINGS] - 'Count=2 - '[Zeitreihe1] - 'SydroTyp=SydroBinZre - 'ZRFormat=99 - 'ID=1041 - 'Extension=.BIN - 'Kennung=Sce10, E038, C38 (TA_Tekeze TK 04B) - 'KennungLang=Sce10, E038, C38 (TA_Tekeze TK 04B), m3/s - 'Datei=C:\Talsim-NG\customers\Nile\projectData\hubert\dataBase\hubert_zre\00001041.BIN - 'Einheit=m3/s - 'Modell=TALSIM - 'Interpretation=1 - 'EndZeitreihe - '[Zeitreihe2] - 'SydroTyp=SydroBinZre - 'ZRFormat=99 - 'ID=1042 - 'Extension=.BIN - 'Kennung=Sce10, E039, C39 (TA_TK5) - 'KennungLang=Sce10, E039, C39 (TA_TK5), m3/s - 'Datei=C:\Talsim-NG\customers\Nile\projectData\hubert\dataBase\hubert_zre\00001042.BIN - 'Einheit=m3/s - 'Modell=TALSIM - 'Interpretation=1 - 'EndZeitreihe - - 'parse clipboard contents - Dim m As Match - Dim i_series As Integer - Dim parts() As String - Dim zreblock As Boolean - Dim data As New List(Of Dictionary(Of String, String)) '[{zreparams1},{zreparams2},...] - Dim file, name As String - Dim fileInstance As TimeSeriesFile - Dim ts As TimeSeries - - zreblock = False - For Each line As String In clipboardtext.Split(eol) - line = line.Trim() - - m = Regex.Match(line, "\[Zeitreihe(\d+)\]") - If m.Success Then - i_series = m.Groups(1).Value - data.Add(New Dictionary(Of String, String)) - zreblock = True - End If + Try + Call Log.AddLogEntry(Log.levels.info, $"Parsing Talsim clipboard content...") - If zreblock Then - If line.Contains("=") Then - parts = line.Split("=") - data(i_series - 1).Add(parts(0), parts(1)) - ElseIf line = "EndZeitreihe" Then - zreblock = False - Continue For - End If - End If + Dim wvp As New Parsers.TalsimClipboard(clipboardtext) + Dim tsList As List(Of TimeSeries) = wvp.Process() - Next - - If data.Count = 0 Then - Throw New Exception("No series could be parsed from TALSIM clipboard content!") - End If + Call Log.AddLogEntry(Log.levels.info, $"Imported {tsList.Count} timeseries") - 'initiate loading of series - For Each params As Dictionary(Of String, String) In data - - ' check all required parameters are present - Dim expectedKeys As New List(Of String) From { - "Datei", - "ZRFormat", - "Kennung", - "Interpretation" - } - For Each key As String In expectedKeys - If Not params.ContainsKey(key) Then - Throw New Exception($"Missing required entry '{key}' in clipboard content!") - End If + 'import the series + Call Log.AddLogEntry(Log.levels.info, "Loading series in chart...") + For Each ts As TimeSeries In tsList + Call Me.Import_Series(ts) Next - file = params("Datei") - - Select Case params("ZRFormat") - Case "4" 'WEL file - - If Not params.ContainsKey("Zustand") Then - Throw New Exception("Missing required entry 'Zustand' in clipboard content!") - End If - - 'build series name - If params("Kennung") = "ZPG" Then - 'handle control groups - name = "KGRP_" & params("Zustand") - Else - name = params("Kennung").PadRight(4, " ") & "_" & params("Zustand") - End If - - 'read file - Log.AddLogEntry(Log.levels.info, $"Loading file {file} ...") - fileInstance = TimeSeriesFile.getInstance(file) - - 'read series from file - ts = fileInstance.getTimeSeries(name) - - 'set interpretation - ts.Interpretation = params("Interpretation") - - 'import series - Call Me.Import_Series(ts) - - Case "99" 'BIN file - - If Not params.ContainsKey("Einheit") Then - Throw New Exception("Missing required entry 'Einheit' in clipboard content!") - End If - - name = params("Kennung") - - 'read file - Log.AddLogEntry(Log.levels.info, $"Loading file {file} ...") - fileInstance = TimeSeriesFile.getInstance(file) - - 'read series from file - fileInstance.readFile() - ts = fileInstance.TimeSeries.First.Value - - 'add metadata - ts.Title = name - ts.Unit = params("Einheit") - - 'set interpretation - ts.Interpretation = params("Interpretation") - - 'import series - Call Me.Import_Series(ts) - - Case Else - Throw New Exception($"Unsupported value {params("ZRFormat")} for ZRFormat!") - - End Select + 'Log + Call Log.AddLogEntry(Log.levels.info, $"Talsim clipboard content parsed successfully!") - Next + Catch ex As Exception + MsgBox("Error while processing Talsim clipboard content:" & eol & ex.Message, MsgBoxStyle.Critical) + Call Log.AddLogEntry(Log.levels.error, "Error while processing Talsim clipboard content:" & eol & ex.Message) + End Try End Sub diff --git a/source/Wave.vbproj b/source/Wave.vbproj index 86c75f00..15813c08 100644 --- a/source/Wave.vbproj +++ b/source/Wave.vbproj @@ -348,7 +348,6 @@ - @@ -389,6 +388,9 @@ Settings.settings True + + + MainWindow.vb @@ -643,6 +645,7 @@ 4.6.1 + copy $(ProjectDir)..\COPYING $(TargetDir)COPYING diff --git a/tests/TestData.vb b/tests/TestData.vb index de6ab3d4..fcd1cbdd 100644 --- a/tests/TestData.vb +++ b/tests/TestData.vb @@ -20,19 +20,26 @@ ''' Module TestData + ''' + ''' Returns the absolute path to the parent directory of the repository + ''' by going up 5 levels from the application directory + ''' + Friend Function getParentDir() As String + Dim appdir As String = My.Application.Info.DirectoryPath() 'e.g. BlueM.Wave\tests\bin\x64\Debug + Dim rootdir As String = appdir + For i As Integer = 1 To 5 + rootdir = IO.Directory.GetParent(rootdir).FullName + Next + Return rootdir + End Function + ''' ''' Returns the absolute path to the test data directory BlueM.Datasets\Wave ''' which is expected to be in the same directory as BlueM.Wave ''' - ''' Friend Function getTestDataDir() As String Try - Dim appdir As String = My.Application.Info.DirectoryPath() 'e.g. BlueM.Wave\tests\bin\x64\Debug - Dim testdatadir As String = appdir - For i As Integer = 1 To 5 - testdatadir = IO.Directory.GetParent(testdatadir).FullName - Next - testdatadir = IO.Path.Combine(testdatadir, "BlueM.Datasets", "Wave") + Dim testdatadir As String = IO.Path.Combine(getParentDir(), "BlueM.Datasets", "Wave") If Not IO.Directory.Exists(testdatadir) Then Throw New AssertInconclusiveException($"Directory {testdatadir} does not exist.") End If diff --git a/tests/TestImport.vb b/tests/TestImport.vb index 67c49151..a03c04ab 100644 --- a/tests/TestImport.vb +++ b/tests/TestImport.vb @@ -24,28 +24,6 @@ Imports Microsoft.VisualStudio.TestTools.UnitTesting Public Class TestImport - ''' - ''' Tests finding a WEL file within a WLZIP file and extracting it - ''' - - Public Sub TestWLZIP() - - Dim file_wel As String = IO.Path.Combine(TestData.getTestDataDir(), "Talsim", "TALSIM.WEL") - - 'delete existing file before testing - If IO.File.Exists(file_wel) Then - IO.File.Delete(file_wel) - End If - - 'attempt to extract from WLZIP - Dim success As Boolean = Fileformats.WEL.extractFromWLZIP(file_wel) - - Assert.IsTrue(success) - Assert.IsTrue(IO.File.Exists(file_wel)) - - End Sub - - ''' ''' Tests importing all supported time series file formats ''' diff --git a/tests/TestTalsim.vb b/tests/TestTalsim.vb new file mode 100644 index 00000000..c9dc1a7e --- /dev/null +++ b/tests/TestTalsim.vb @@ -0,0 +1,124 @@ +'BlueM.Wave +'Copyright (C) BlueM Dev Group +' +' +'This program is free software: you can redistribute it and/or modify +'it under the terms of the GNU Lesser General Public License as published by +'the Free Software Foundation, either version 3 of the License, or +'(at your option) any later version. +' +'This program is distributed in the hope that it will be useful, +'but WITHOUT ANY WARRANTY; without even the implied warranty of +'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +'GNU Lesser General Public License for more details. +' +'You should have received a copy of the GNU Lesser General Public License +'along with this program. If not, see . +' +Imports System.Text +Imports Microsoft.VisualStudio.TestTools.UnitTesting + +''' +''' Tests Talsim-specific functionality +''' + +Public Class TestTalsim + + + + + + + + + Public Sub TestTalsimClipboard(clipboardFile As String) + + Dim workdir = IO.Directory.GetCurrentDirectory() + Try + 'set current directory to test assemply path to ensure any relative paths in the clipboard data are correct + IO.Directory.SetCurrentDirectory(My.Application.Info.DirectoryPath()) + + Dim clipboardData As String = IO.File.ReadAllText(IO.Path.Combine(TestData.getTestDataDir(), clipboardFile)) + + Dim talsimclipboard As New Parsers.TalsimClipboard(clipboardData) + Dim tsList As List(Of TimeSeries) = talsimclipboard.Process() + + 'check that time series were created + Assert.IsTrue(tsList.Count > 0) + + Catch ex As Exception + Assert.Fail("Exception occurred: " & ex.Message) + + Finally + 'restore original working directory + IO.Directory.SetCurrentDirectory(workdir) + End Try + + End Sub + + ''' + ''' Tests finding a WEL file within a WLZIP file and extracting it + ''' + + Public Sub TestWLZIP() + + Dim file_wel As String = IO.Path.Combine(TestData.getTestDataDir(), "Talsim", "TALSIM.WEL") + + 'delete existing file before testing + If IO.File.Exists(file_wel) Then + IO.File.Delete(file_wel) + End If + + 'attempt to extract from WLZIP + Dim success As Boolean = Parsers.TalsimClipboard.extractFromWLZIP(file_wel) + + Assert.IsTrue(success) + Assert.IsTrue(IO.File.Exists(file_wel)) + + 'clean up by deleting the extracted file + IO.File.Delete(file_wel) + + End Sub + + + ''' + ''' Tests loading a WEL file within a WLZIP file when processing Talsim clipboard data + ''' + + Public Sub TestWLZIPFromTalsimClipboard() + + Dim workdir = IO.Directory.GetCurrentDirectory() + Try + 'set current directory to test assemply path to ensure any relative paths in the clipboard data are correct + IO.Directory.SetCurrentDirectory(My.Application.Info.DirectoryPath()) + + Dim file_clipboard As String = IO.Path.Combine(TestData.getTestDataDir(), "Talsim", "Clipboard_Talsim_WLZIP.txt") + Dim file_wel As String = IO.Path.Combine(TestData.getTestDataDir(), "Talsim", "TALSIM.WEL") + + 'delete existing file before testing + If IO.File.Exists(file_wel) Then + IO.File.Delete(file_wel) + End If + + Dim clipboardData As String = IO.File.ReadAllText(file_clipboard) + + Dim talsimclipboard As New Parsers.TalsimClipboard(clipboardData) + Dim tsList As List(Of TimeSeries) = talsimclipboard.Process() + + 'check that time series were created + Assert.IsTrue(tsList.Count > 0) + + 'check that extracted file was deleted + Assert.IsFalse(IO.File.Exists(file_wel)) + + Catch ex As Exception + Assert.Fail("Exception occurred: " & ex.Message) + + Finally + 'restore original working directory + IO.Directory.SetCurrentDirectory(workdir) + End Try + + End Sub + +End Class \ No newline at end of file diff --git a/tests/TestWVP.vb b/tests/TestWVP.vb index f6a9a53d..b5ced450 100644 --- a/tests/TestWVP.vb +++ b/tests/TestWVP.vb @@ -34,7 +34,7 @@ Imports Microsoft.VisualStudio.TestTools.UnitTesting } For Each file As String In filesWVP - Dim wvp As New Fileformats.WVP(file) + Dim wvp As New Parsers.WVP(file) Next End Sub @@ -46,7 +46,7 @@ Imports Microsoft.VisualStudio.TestTools.UnitTesting Dim fileWVP As String = IO.Path.Combine(TestData.getTestDataDir(), "WVP", "test_displayoptions.wvp") - Dim wvp As New Fileformats.WVP(fileWVP) + Dim wvp As New Parsers.WVP(fileWVP) Dim tsList As List(Of TimeSeries) = wvp.Process() Assert.AreEqual("AA _1AB", tsList(0).Title) @@ -71,20 +71,20 @@ Imports Microsoft.VisualStudio.TestTools.UnitTesting 'read time series using a WVP file Dim fileIn As String = IO.Path.Combine(TestData.getTestDataDir(), "WVP", "test_displayoptions.wvp") - Dim wvp As New Fileformats.WVP(fileIn) + Dim wvp As New Parsers.WVP(fileIn) Dim tsList As List(Of TimeSeries) = wvp.Process() 'write the time series to a WVP file Dim fileOut As String = IO.Path.Combine(TestData.getTestDataDir(), "WVP", "test_displayoptions_export.wvp") - Call Fileformats.WVP.writeFile(tsList, fileOut, - saveRelativePaths:=True, - saveTitle:=True, - saveUnit:=True, - saveInterpretation:=True, - saveColor:=True, - saveLineStyle:=True, - saveLineWidth:=True, - savePointsVisibility:=True + Call Parsers.WVP.writeFile(tsList, fileOut, + saveRelativePaths:=True, + saveTitle:=True, + saveUnit:=True, + saveInterpretation:=True, + saveColor:=True, + saveLineStyle:=True, + saveLineWidth:=True, + savePointsVisibility:=True ) 'check the file contents of the written WVP file @@ -123,7 +123,7 @@ Imports Microsoft.VisualStudio.TestTools.UnitTesting 'read time series using a WVP file Dim file As String = IO.Path.Combine(TestData.getTestDataDir(), "WVP", "test_preserve_order.wvp") - Dim wvp As New Fileformats.WVP(file) + Dim wvp As New Parsers.WVP(file) Dim tsList As List(Of TimeSeries) = wvp.Process() 'check the order of series diff --git a/tests/Wave.Tests.vbproj b/tests/Wave.Tests.vbproj index 75eff3b0..c69e658c 100644 --- a/tests/Wave.Tests.vbproj +++ b/tests/Wave.Tests.vbproj @@ -92,6 +92,7 @@ +