// Copyright (C) Stichting Deltares 2019. All rights reserved. // // This file is part of the application DAM - Clients Library. // // DAM - UI is free software: you can redistribute it and/or modify // it under the terms of the GNU 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // All names, logos, and references to "Deltares" are registered trademarks of // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. using System; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; using System.IO; using Deltares.Dam.Data.Assemblers; using Deltares.Standard.Extensions; namespace Deltares.Dam.Data { public class TimeSerieCollection { /// /// Initializes a new instance of the class. /// public TimeSerieCollection() { this.Series = new List(); } /// /// Gets or sets the series. /// /// /// The series. /// public List Series { get; set; } /// /// Gets or sets the version. /// /// /// The version. /// public string Version { get; set; } /// /// Gets or sets the time zone. /// /// /// The time zone. /// public double TimeZone { get; set; } /// /// Loads a time serie collection from file and validates the file with the resource embedded XSD /// /// The file info object containing the file to load /// When valid a loaded time serie collection /// public static TimeSerieCollection LoadFromFile(FileInfo fileInfo) { return LoadFromFile(fileInfo.FullName, true); } /// /// Loads a time serie collection from file and validates the file with the resource embedded XSD /// /// The file to load /// When valid a loaded time serie collection /// public static TimeSerieCollection LoadFromFile(string fileName) { return LoadFromFile(fileName, true); } /// /// Loads a time serie collection from file. /// /// The file name of the time serie /// The value indicating if the file needs to be validated /// The loaded time serie collection public static TimeSerieCollection LoadFromFile(string fileName, bool validateWithEmbeddedXsd) { try { string message; var assembler = new TimeSeriesAssembler(); var doc = XDocument.Load(fileName); if (validateWithEmbeddedXsd) if (!assembler.ValidateSchema(doc, out message)) throw new TimeSerieSchemaValidationException(message); return assembler.CreateDomainObject(doc); } catch (Exception e) { throw new TimeSerieSchemaValidationException(fileName + ": " + e.Message); } } /// /// Saves the time serie collection to a specified file using the time serie assembler /// /// The name of the file public void Save(string fileName) { ThrowHelper.ThrowIfFileNameNullOrEmpty(fileName, StringResourceNames.FileNameNotValid); var timeSerieAssembler = new TimeSeriesAssembler(); XDocument doc = timeSerieAssembler.CreateDataTransferDocument(this); doc.Save(fileName); FileWriterUtil.RemoveThreeBytesFromXml(fileName); // apply this fix for FEWS! } /// /// Updates the time serie entries with new values by applying the function to each value entry /// /// The parameter ID of the time serie to update /// The function to apply to each entry public void UpdateAllEntryValues(string parameterId, Func function) { foreach (var timeSerie in this.GetSeriesByParameterId(parameterId)) { foreach (var sourceEntry in timeSerie.Entries) { if (!sourceEntry.Value.AlmostEquals(timeSerie.MissVal)) { sourceEntry.Value = function(sourceEntry.Value); } } } } /// /// Creates a shallow copy of the current time serie collection and applies the map function to each of its entries /// public IEnumerable Map(IEnumerable locations, string parameterId, IEnumerable> functionList) { return from locationId in locations from timeSerie in this.GetSeriesByLocationId(locationId).Where(x => x.ParameterId.Equals(parameterId)) from function in functionList select function(timeSerie); } /// /// Creates a shallow copy of the current time serie collection and applies the map function to each of its entries /// /// The locations to look for in this collection /// The parameter to look for in this collection /// The function to apply /// A sequence of new time series with the applied function to its entries public IEnumerable Map(IEnumerable locations, string parameterId, Func function) { return Map(locations, parameterId, new List> { function }); } /// /// Creates a shallow copy of the current time serie collection and applies the map function to each of its entries /// public IEnumerable Map(string locationId, string parameterId, Func function) { return Map(new List { locationId }, parameterId, function); } /// /// Searches for a time series matching the location and parameter id. There should be only 1 or none (null) /// /// The parameter id. /// The location id. /// The time series matching the criterium public TimeSerie FindSerie(string parameterId, string locationId) { return (from series in this.Series where series.ParameterId.Equals(parameterId, StringComparison.InvariantCultureIgnoreCase) && series.LocationId.Equals(locationId, StringComparison.InvariantCultureIgnoreCase) select series).SingleOrDefault(); } /// /// Gets all the time series with the given parameter id. /// /// The parameter id. /// The time series matching the criteria public IEnumerable GetSeriesByParameterId(string parameterId) { return from series in this.Series where series.ParameterId.Equals(parameterId, StringComparison.InvariantCultureIgnoreCase) select series; } /// /// Gets all the series with the given location id. /// /// The location id. /// The time series matching the criteria public IEnumerable GetSeriesByLocationId(string locationId) { return from series in this.Series where series.LocationId.Equals(locationId, StringComparison.InvariantCultureIgnoreCase) select series; } /// /// Gets the series containing location id and parameter id. /// /// The location id. /// The parameter id. /// The time series matching the criteria public IEnumerable GetSeriesByLocationIdAndParameterId(string locationId, string parameterId) { return from series in this.Series where series.LocationId.Equals(locationId, StringComparison.InvariantCultureIgnoreCase) && series.ParameterId.Equals(parameterId, StringComparison.InvariantCultureIgnoreCase) select series; } /// /// Gets all the series containing the combined gage and location id. (using the gage_id/location_id pattern) /// /// The combined gage and location id. /// public IEnumerable GetSeriesByGageIdAndLocationId(string combinedGageAndLocationId) { var resultSeries = new List(); foreach (var serie in this.Series) { string gaugeLocationId = serie.LocationId.Split('/')[0]; if (combinedGageAndLocationId.Equals(gaugeLocationId, StringComparison.InvariantCultureIgnoreCase)) { resultSeries.Add(serie); } } return resultSeries; } public TimeSerieCollection GetShallowCopy() { var copy = new TimeSerieCollection { Version = Version, TimeZone = TimeZone }; copy.Series.Clear(); return copy; } /// /// Clears the time series. /// public void Clear() { Series.Clear(); } public TimeSerie AddNewSeries(string locationId) { var series = TimeSerie.CreateTimeSerie(locationId); this.Series.Add(series); return series; } } }