From 89fa2fccee28b16fa8234eccd4f97f2254e0088c Mon Sep 17 00:00:00 2001 From: Mark van Renswoude Date: Tue, 11 Jan 2022 20:28:49 +0100 Subject: [PATCH] Implemented Import functionality for Tapeti.Cmd compatible single-file JSON --- PettingZoo.Core/Connection/ISubscriber.cs | 2 + .../Export/ExportFormatProvider.cs | 16 - PettingZoo.Core/Export/IExportFormat.cs | 14 - .../Export/IExportFormatProvider.cs | 9 - .../ExportImport/BaseProgressDecorator.cs | 33 ++ .../ExportImportFormatProvider.cs | 22 + .../ExportImport/IExportImportFormat.cs | 25 ++ .../IExportImportFormatProvider.cs | 10 + .../ExportImport/ImportSubscriber.cs | 43 ++ .../ListEnumerableProgressDecorator.cs | 100 +++++ .../ExportImport/StreamProgressDecorator.cs | 157 +++++++ .../RabbitMQClientSubscriber.cs | 8 + .../Export/BaseTapetiCmdExportImportFormat.cs | 47 ++ .../Export/TapetiCmdExportFormat.cs | 50 +-- ... TapetiCmdImportExportStrings.Designer.cs} | 6 +- ...resx => TapetiCmdImportExportStrings.resx} | 0 .../Export/TapetiCmdImportFormat.cs | 75 ++++ PettingZoo.Tapeti/PettingZoo.Tapeti.csproj | 36 +- .../PettingZoo.Tapeti_ooj5vuwa_wpftmp.csproj | 325 ++++++++++++++ .../TapetiClassLibraryExampleGenerator.cs | 4 +- ...LibraryExampleGeneratorStrings.Designer.cs | 72 +++ ...tiClassLibraryExampleGeneratorStrings.resx | 123 +++++ PettingZoo.WPF/PettingZoo.WPF.csproj | 22 + .../ProgressStrings.Designer.cs | 17 +- .../ProgressWindow/ProgressStrings.resx | 3 - .../ProgressWindow/ProgressWindow.xaml | 7 +- .../ProgressWindow/ProgressWindow.xaml.cs | 9 +- PettingZoo/PettingZoo_5m1cbecx_wpftmp.csproj | 419 ++++++++++++++++++ PettingZoo/Program.cs | 9 +- PettingZoo/UI/Main/MainWindow.xaml | 7 + PettingZoo/UI/Main/MainWindow.xaml.cs | 8 +- .../UI/Main/MainWindowStrings.Designer.cs | 18 + PettingZoo/UI/Main/MainWindowStrings.resx | 10 +- PettingZoo/UI/Main/MainWindowViewModel.cs | 114 ++++- PettingZoo/UI/Tab/ITabFactory.cs | 2 +- .../UI/Tab/Subscriber/SubscriberViewModel.cs | 74 +++- .../SubscriberViewStrings.Designer.cs | 9 + .../Tab/Subscriber/SubscriberViewStrings.resx | 3 + PettingZoo/UI/Tab/ViewTabFactory.cs | 12 +- 39 files changed, 1757 insertions(+), 163 deletions(-) delete mode 100644 PettingZoo.Core/Export/ExportFormatProvider.cs delete mode 100644 PettingZoo.Core/Export/IExportFormat.cs delete mode 100644 PettingZoo.Core/Export/IExportFormatProvider.cs create mode 100644 PettingZoo.Core/ExportImport/BaseProgressDecorator.cs create mode 100644 PettingZoo.Core/ExportImport/ExportImportFormatProvider.cs create mode 100644 PettingZoo.Core/ExportImport/IExportImportFormat.cs create mode 100644 PettingZoo.Core/ExportImport/IExportImportFormatProvider.cs create mode 100644 PettingZoo.Core/ExportImport/ImportSubscriber.cs create mode 100644 PettingZoo.Core/ExportImport/ListEnumerableProgressDecorator.cs create mode 100644 PettingZoo.Core/ExportImport/StreamProgressDecorator.cs create mode 100644 PettingZoo.Tapeti/Export/BaseTapetiCmdExportImportFormat.cs rename PettingZoo.Tapeti/Export/{TapetiCmdExportStrings.Designer.cs => TapetiCmdImportExportStrings.Designer.cs} (94%) rename PettingZoo.Tapeti/Export/{TapetiCmdExportStrings.resx => TapetiCmdImportExportStrings.resx} (100%) create mode 100644 PettingZoo.Tapeti/Export/TapetiCmdImportFormat.cs create mode 100644 PettingZoo.Tapeti/PettingZoo.Tapeti_ooj5vuwa_wpftmp.csproj create mode 100644 PettingZoo.Tapeti/TapetiClassLibraryExampleGeneratorStrings.Designer.cs create mode 100644 PettingZoo.Tapeti/TapetiClassLibraryExampleGeneratorStrings.resx rename PettingZoo.Tapeti/UI/PackageProgress/PackageProgressStrings.Designer.cs => PettingZoo.WPF/ProgressWindow/ProgressStrings.Designer.cs (82%) rename PettingZoo.Tapeti/UI/PackageProgress/PackageProgressStrings.resx => PettingZoo.WPF/ProgressWindow/ProgressStrings.resx (98%) rename PettingZoo.Tapeti/UI/PackageProgress/PackageProgressWindow.xaml => PettingZoo.WPF/ProgressWindow/ProgressWindow.xaml (65%) rename PettingZoo.Tapeti/UI/PackageProgress/PackageProgressWindow.xaml.cs => PettingZoo.WPF/ProgressWindow/ProgressWindow.xaml.cs (79%) create mode 100644 PettingZoo/PettingZoo_5m1cbecx_wpftmp.csproj diff --git a/PettingZoo.Core/Connection/ISubscriber.cs b/PettingZoo.Core/Connection/ISubscriber.cs index 9beb336..e18c9e1 100644 --- a/PettingZoo.Core/Connection/ISubscriber.cs +++ b/PettingZoo.Core/Connection/ISubscriber.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace PettingZoo.Core.Connection { @@ -10,6 +11,7 @@ namespace PettingZoo.Core.Connection event EventHandler? MessageReceived; + IEnumerable GetInitialMessages(); void Start(); } diff --git a/PettingZoo.Core/Export/ExportFormatProvider.cs b/PettingZoo.Core/Export/ExportFormatProvider.cs deleted file mode 100644 index b761511..0000000 --- a/PettingZoo.Core/Export/ExportFormatProvider.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Collections.Generic; - -namespace PettingZoo.Core.Export -{ - public class ExportFormatProvider : IExportFormatProvider - { - private readonly List formats; - - public IEnumerable Formats => formats; - - public ExportFormatProvider(params IExportFormat[] formats) - { - this.formats = new List(formats); - } - } -} diff --git a/PettingZoo.Core/Export/IExportFormat.cs b/PettingZoo.Core/Export/IExportFormat.cs deleted file mode 100644 index 92afbec..0000000 --- a/PettingZoo.Core/Export/IExportFormat.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Threading.Tasks; -using PettingZoo.Core.Connection; - -namespace PettingZoo.Core.Export -{ - public interface IExportFormat - { - public string Filter { get; } - - public Task Export(Stream stream, IEnumerable messages); - } -} diff --git a/PettingZoo.Core/Export/IExportFormatProvider.cs b/PettingZoo.Core/Export/IExportFormatProvider.cs deleted file mode 100644 index de76d7a..0000000 --- a/PettingZoo.Core/Export/IExportFormatProvider.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Collections.Generic; - -namespace PettingZoo.Core.Export -{ - public interface IExportFormatProvider - { - public IEnumerable Formats { get; } - } -} diff --git a/PettingZoo.Core/ExportImport/BaseProgressDecorator.cs b/PettingZoo.Core/ExportImport/BaseProgressDecorator.cs new file mode 100644 index 0000000..8e02cc4 --- /dev/null +++ b/PettingZoo.Core/ExportImport/BaseProgressDecorator.cs @@ -0,0 +1,33 @@ +using System; + +namespace PettingZoo.Core.ExportImport +{ + public abstract class BaseProgressDecorator + { + private static readonly TimeSpan DefaultReportInterval = TimeSpan.FromMilliseconds(100); + + private readonly IProgress progress; + private readonly long reportInterval; + private long lastReport; + + protected BaseProgressDecorator(IProgress progress, TimeSpan? reportInterval = null) + { + this.progress = progress; + this.reportInterval = (int)(reportInterval ?? DefaultReportInterval).TotalMilliseconds; + } + + + protected abstract int GetProgress(); + + protected void UpdateProgress() + { + // Because this method is called pretty frequently, not having DateTime's small overhead is worth it + var now = Environment.TickCount64; + if (now - lastReport < reportInterval) + return; + + progress.Report(GetProgress()); + lastReport = now; + } + } +} diff --git a/PettingZoo.Core/ExportImport/ExportImportFormatProvider.cs b/PettingZoo.Core/ExportImport/ExportImportFormatProvider.cs new file mode 100644 index 0000000..1482bf2 --- /dev/null +++ b/PettingZoo.Core/ExportImport/ExportImportFormatProvider.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using System.Linq; + +namespace PettingZoo.Core.ExportImport +{ + public class ExportImportFormatProvider : IExportImportFormatProvider + { + private readonly List exportFormats; + private readonly List importFormats; + + + public IEnumerable ExportFormats => exportFormats; + public IEnumerable ImportFormats => importFormats; + + + public ExportImportFormatProvider(params IExportImportFormat[] formats) + { + exportFormats = new List(formats.Where(f => f is IExportFormat).Cast()); + importFormats = new List(formats.Where(f => f is IImportFormat).Cast()); + } + } +} diff --git a/PettingZoo.Core/ExportImport/IExportImportFormat.cs b/PettingZoo.Core/ExportImport/IExportImportFormat.cs new file mode 100644 index 0000000..e586348 --- /dev/null +++ b/PettingZoo.Core/ExportImport/IExportImportFormat.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using PettingZoo.Core.Connection; + +namespace PettingZoo.Core.ExportImport +{ + public interface IExportImportFormat + { + string Filter { get; } + } + + + public interface IExportFormat : IExportImportFormat + { + Task Export(Stream stream, IEnumerable messages, CancellationToken cancellationToken); + } + + + public interface IImportFormat : IExportImportFormat + { + Task> Import(Stream stream, CancellationToken cancellationToken); + } +} diff --git a/PettingZoo.Core/ExportImport/IExportImportFormatProvider.cs b/PettingZoo.Core/ExportImport/IExportImportFormatProvider.cs new file mode 100644 index 0000000..1991668 --- /dev/null +++ b/PettingZoo.Core/ExportImport/IExportImportFormatProvider.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace PettingZoo.Core.ExportImport +{ + public interface IExportImportFormatProvider + { + public IEnumerable ExportFormats { get; } + public IEnumerable ImportFormats { get; } + } +} diff --git a/PettingZoo.Core/ExportImport/ImportSubscriber.cs b/PettingZoo.Core/ExportImport/ImportSubscriber.cs new file mode 100644 index 0000000..067fee4 --- /dev/null +++ b/PettingZoo.Core/ExportImport/ImportSubscriber.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using PettingZoo.Core.Connection; + +namespace PettingZoo.Core.ExportImport +{ + public class ImportSubscriber : ISubscriber + { + private readonly IReadOnlyList messages; + + public string? QueueName { get; } + public string? Exchange => null; + public string? RoutingKey => null; + public event EventHandler? MessageReceived; + + + public ImportSubscriber(string filename, IReadOnlyList messages) + { + QueueName = Path.GetFileName(filename); + this.messages = messages; + } + + + public ValueTask DisposeAsync() + { + GC.SuppressFinalize(this); + return default; + } + + + public IEnumerable GetInitialMessages() + { + return messages; + } + + + public void Start() + { + } + } +} diff --git a/PettingZoo.Core/ExportImport/ListEnumerableProgressDecorator.cs b/PettingZoo.Core/ExportImport/ListEnumerableProgressDecorator.cs new file mode 100644 index 0000000..d74425a --- /dev/null +++ b/PettingZoo.Core/ExportImport/ListEnumerableProgressDecorator.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace PettingZoo.Core.ExportImport +{ + public class ListEnumerableProgressDecorator : BaseProgressDecorator, IEnumerable + { + private readonly IReadOnlyList decoratedList; + private int position; + + + /// + /// Wraps an IReadOnlyList and provides reports to the IProgress when it is enumerated. + /// + /// The IReadOnlyList to decorate. + /// Receives progress reports. The value will be a percentage (0 - 100). + /// The minimum time between reports. + public ListEnumerableProgressDecorator(IReadOnlyList decoratedList, IProgress progress, TimeSpan? reportInterval = null) + : base(progress, reportInterval) + { + this.decoratedList = decoratedList; + } + + + protected override int GetProgress() + { + return decoratedList.Count > 0 + ? (int)Math.Truncate((double)position / decoratedList.Count * 100) + : 0; + } + + + protected void AfterNext() + { + position++; + UpdateProgress(); + } + + + protected void Reset() + { + position = 0; + UpdateProgress(); + } + + + public IEnumerator GetEnumerator() + { + return new EnumerableWrapper(this, decoratedList.GetEnumerator()); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + + private class EnumerableWrapper : IEnumerator + { + private readonly ListEnumerableProgressDecorator owner; + private readonly IEnumerator decoratedEnumerator; + + + public EnumerableWrapper(ListEnumerableProgressDecorator owner, IEnumerator decoratedEnumerator) + { + this.owner = owner; + this.decoratedEnumerator = decoratedEnumerator; + } + + + public bool MoveNext() + { + var result = decoratedEnumerator.MoveNext(); + if (result) + owner.AfterNext(); + + return result; + } + + + public void Reset() + { + decoratedEnumerator.Reset(); + owner.Reset(); + } + + + public T Current => decoratedEnumerator.Current; + object IEnumerator.Current => decoratedEnumerator.Current!; + + + public void Dispose() + { + GC.SuppressFinalize(this); + decoratedEnumerator.Dispose(); + } + } + } +} diff --git a/PettingZoo.Core/ExportImport/StreamProgressDecorator.cs b/PettingZoo.Core/ExportImport/StreamProgressDecorator.cs new file mode 100644 index 0000000..76ee710 --- /dev/null +++ b/PettingZoo.Core/ExportImport/StreamProgressDecorator.cs @@ -0,0 +1,157 @@ +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace PettingZoo.Core.ExportImport +{ + public class StreamProgressDecorator : BaseProgressDecorator + { + private readonly StreamWrapper streamWrapper; + + public Stream Stream => streamWrapper; + + + /// + /// Wraps a Stream and provides reports to the IProgress. + /// + /// + /// Use the Stream property to pass along to the method you want to monitor the progress on. + /// If the consumer seeks around in the stream a lot the progress will not be linear, but that + /// seems to be a trend anyways with progress bars, so enjoy your modern experience! + /// + /// The stream to decorate. + /// Receives progress reports. The value will be a percentage (0 - 100). + /// The minimum time between reports. + public StreamProgressDecorator(Stream decoratedStream, IProgress progress, TimeSpan? reportInterval = null) + : base(progress, reportInterval) + { + streamWrapper = new StreamWrapper(this, decoratedStream); + } + + + protected override int GetProgress() + { + return streamWrapper.DecoratedStream.Length > 0 + ? (int)Math.Truncate((double)streamWrapper.DecoratedStream.Position / streamWrapper.DecoratedStream.Length * 100) + : 0; + } + + + private class StreamWrapper : Stream + { + private readonly StreamProgressDecorator owner; + public readonly Stream DecoratedStream; + + public override bool CanRead => DecoratedStream.CanRead; + public override bool CanSeek => DecoratedStream.CanSeek; + public override bool CanWrite => DecoratedStream.CanWrite; + public override long Length => DecoratedStream.Length; + + public override long Position + { + get => DecoratedStream.Position; + set => DecoratedStream.Position = value; + } + + + public StreamWrapper(StreamProgressDecorator owner, Stream decoratedStream) + { + this.owner = owner; + this.DecoratedStream = decoratedStream; + } + + + public override void Flush() + { + DecoratedStream.Flush(); + } + + + public override Task FlushAsync(CancellationToken cancellationToken) + { + return DecoratedStream.FlushAsync(cancellationToken); + } + + + public override int Read(byte[] buffer, int offset, int count) + { + var result = DecoratedStream.Read(buffer, offset, count); + owner.UpdateProgress(); + return result; + } + + public override int Read(Span buffer) + { + var result = DecoratedStream.Read(buffer); + owner.UpdateProgress(); + return result; + } + + + public override async Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + #pragma warning disable CA1835 // Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync' + var result = await DecoratedStream.ReadAsync(buffer, offset, count, cancellationToken); + #pragma warning restore CA1835 + owner.UpdateProgress(); + return result; + } + + + public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = new()) + { + var result = DecoratedStream.ReadAsync(buffer, cancellationToken); + owner.UpdateProgress(); + return result; + } + + + public override long Seek(long offset, SeekOrigin origin) + { + var result = DecoratedStream.Seek(offset, origin); + owner.UpdateProgress(); + return result; + } + + + public override void SetLength(long value) + { + DecoratedStream.SetLength(value); + owner.UpdateProgress(); + } + + + public override void Write(byte[] buffer, int offset, int count) + { + DecoratedStream.Write(buffer, offset, count); + owner.UpdateProgress(); + } + + + public override void Write(ReadOnlySpan buffer) + { + DecoratedStream.Write(buffer); + owner.UpdateProgress(); + } + + + public override async Task WriteAsync(byte[] buffer, int offset, int count, + CancellationToken cancellationToken) + { + #pragma warning disable CA1835 // Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync' + await DecoratedStream.WriteAsync(buffer, offset, count, cancellationToken); + #pragma warning restore CA1835 + owner.UpdateProgress(); + } + + + public override async ValueTask WriteAsync(ReadOnlyMemory buffer, + CancellationToken cancellationToken = new()) + { + await DecoratedStream.WriteAsync(buffer, cancellationToken); + owner.UpdateProgress(); + } + } + } +} diff --git a/PettingZoo.RabbitMQ/RabbitMQClientSubscriber.cs b/PettingZoo.RabbitMQ/RabbitMQClientSubscriber.cs index 2c24db9..9da4068 100644 --- a/PettingZoo.RabbitMQ/RabbitMQClientSubscriber.cs +++ b/PettingZoo.RabbitMQ/RabbitMQClientSubscriber.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using PettingZoo.Core.Connection; using RabbitMQ.Client; @@ -38,6 +40,12 @@ namespace PettingZoo.RabbitMQ } + public IEnumerable GetInitialMessages() + { + return Enumerable.Empty(); + } + + public void Start() { started = true; diff --git a/PettingZoo.Tapeti/Export/BaseTapetiCmdExportImportFormat.cs b/PettingZoo.Tapeti/Export/BaseTapetiCmdExportImportFormat.cs new file mode 100644 index 0000000..6bfd721 --- /dev/null +++ b/PettingZoo.Tapeti/Export/BaseTapetiCmdExportImportFormat.cs @@ -0,0 +1,47 @@ +using System.Collections.Generic; +using Newtonsoft.Json.Linq; +using PettingZoo.Core.ExportImport; + +namespace PettingZoo.Tapeti.Export +{ + public abstract class BaseTapetiCmdExportImportFormat : IExportImportFormat + { + public string Filter => TapetiCmdImportExportStrings.TapetiCmdFilter; + } + + + // It would be nicer if Tapeti.Cmd exposed it's file format in a NuGet package... if only I knew the author ¯\_(ツ)_/¯ + public class SerializableMessage + { + //public ulong DeliveryTag; + //public bool Redelivered; + public string? Exchange; + public string? RoutingKey; + //public string? Queue; + + // ReSharper disable once FieldCanBeMadeReadOnly.Local - must be settable by JSON deserialization + public SerializableMessageProperties? Properties; + + public JObject? Body; + public byte[]? RawBody; + } + + + public class SerializableMessageProperties + { + public string? AppId; + //public string? ClusterId; + public string? ContentEncoding; + public string? ContentType; + public string? CorrelationId; + public byte? DeliveryMode; + public string? Expiration; + public IDictionary? Headers; + public string? MessageId; + public byte? Priority; + public string? ReplyTo; + public long? Timestamp; + public string? Type; + public string? UserId; + } +} diff --git a/PettingZoo.Tapeti/Export/TapetiCmdExportFormat.cs b/PettingZoo.Tapeti/Export/TapetiCmdExportFormat.cs index 37b452d..7967827 100644 --- a/PettingZoo.Tapeti/Export/TapetiCmdExportFormat.cs +++ b/PettingZoo.Tapeti/Export/TapetiCmdExportFormat.cs @@ -3,31 +3,33 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using PettingZoo.Core.Connection; -using PettingZoo.Core.Export; +using PettingZoo.Core.ExportImport; + namespace PettingZoo.Tapeti.Export { - public class TapetiCmdExportFormat : IExportFormat + public class TapetiCmdExportFormat : BaseTapetiCmdExportImportFormat, IExportFormat { - public string Filter => TapetiCmdExportStrings.TapetiCmdFilter; - - private static readonly JsonSerializerSettings SerializerSettings = new() { NullValueHandling = NullValueHandling.Ignore }; - public async Task Export(Stream stream, IEnumerable messages) + public async Task Export(Stream stream, IEnumerable messages, CancellationToken cancellationToken) { await using var exportFile = new StreamWriter(stream, Encoding.UTF8); foreach (var message in messages) { + if (cancellationToken.IsCancellationRequested) + break; + var serializableMessage = new SerializableMessage { Exchange = message.Exchange, @@ -80,40 +82,4 @@ namespace PettingZoo.Tapeti.Export } } } - - - // It would be nicer if Tapeti.Cmd exposed it's file format in a NuGet package... if only I knew the author ¯\_(ツ)_/¯ - public class SerializableMessage - { - //public ulong DeliveryTag; - //public bool Redelivered; - public string? Exchange; - public string? RoutingKey; - //public string? Queue; - - // ReSharper disable once FieldCanBeMadeReadOnly.Local - must be settable by JSON deserialization - public SerializableMessageProperties? Properties; - - public JObject? Body; - public byte[]? RawBody; - } - - - public class SerializableMessageProperties - { - public string? AppId; - //public string? ClusterId; - public string? ContentEncoding; - public string? ContentType; - public string? CorrelationId; - public byte? DeliveryMode; - public string? Expiration; - public IDictionary? Headers; - public string? MessageId; - public byte? Priority; - public string? ReplyTo; - public long? Timestamp; - public string? Type; - public string? UserId; - } } diff --git a/PettingZoo.Tapeti/Export/TapetiCmdExportStrings.Designer.cs b/PettingZoo.Tapeti/Export/TapetiCmdImportExportStrings.Designer.cs similarity index 94% rename from PettingZoo.Tapeti/Export/TapetiCmdExportStrings.Designer.cs rename to PettingZoo.Tapeti/Export/TapetiCmdImportExportStrings.Designer.cs index e6501d1..a9d3bf5 100644 --- a/PettingZoo.Tapeti/Export/TapetiCmdExportStrings.Designer.cs +++ b/PettingZoo.Tapeti/Export/TapetiCmdImportExportStrings.Designer.cs @@ -22,14 +22,14 @@ namespace PettingZoo.Tapeti.Export { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class TapetiCmdExportStrings { + internal class TapetiCmdImportExportStrings { private static global::System.Resources.ResourceManager resourceMan; private static global::System.Globalization.CultureInfo resourceCulture; [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal TapetiCmdExportStrings() { + internal TapetiCmdImportExportStrings() { } /// @@ -39,7 +39,7 @@ namespace PettingZoo.Tapeti.Export { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PettingZoo.Tapeti.Export.TapetiCmdExportStrings", typeof(TapetiCmdExportStrings).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PettingZoo.Tapeti.Export.TapetiCmdImportExportStrings", typeof(TapetiCmdImportExportStrings).Assembly); resourceMan = temp; } return resourceMan; diff --git a/PettingZoo.Tapeti/Export/TapetiCmdExportStrings.resx b/PettingZoo.Tapeti/Export/TapetiCmdImportExportStrings.resx similarity index 100% rename from PettingZoo.Tapeti/Export/TapetiCmdExportStrings.resx rename to PettingZoo.Tapeti/Export/TapetiCmdImportExportStrings.resx diff --git a/PettingZoo.Tapeti/Export/TapetiCmdImportFormat.cs b/PettingZoo.Tapeti/Export/TapetiCmdImportFormat.cs new file mode 100644 index 0000000..58f88d4 --- /dev/null +++ b/PettingZoo.Tapeti/Export/TapetiCmdImportFormat.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Newtonsoft.Json; +using PettingZoo.Core.Connection; +using PettingZoo.Core.ExportImport; + +namespace PettingZoo.Tapeti.Export +{ + public class TapetiCmdImportFormat : BaseTapetiCmdExportImportFormat, IImportFormat + { + private const int DefaultBufferSize = 1024; + + + public async Task> Import(Stream stream, CancellationToken cancellationToken) + { + var now = DateTime.Now; + using var reader = new StreamReader(stream, Encoding.UTF8, true, DefaultBufferSize, true); + + var messages = new List(); + + while (!reader.EndOfStream && !cancellationToken.IsCancellationRequested) + { + var serialized = await reader.ReadLineAsync(); + if (string.IsNullOrEmpty(serialized)) + continue; + + var serializableMessage = JsonConvert.DeserializeObject(serialized); + if (serializableMessage == null) + continue; + + var body = serializableMessage.Body != null + ? Encoding.UTF8.GetBytes(serializableMessage.Body.ToString(Formatting.Indented)) + : serializableMessage.RawBody; + + var messageTimestamp = serializableMessage.Properties?.Timestamp != null + ? DateTimeOffset.FromUnixTimeSeconds(serializableMessage.Properties.Timestamp.Value).LocalDateTime + : now; + + messages.Add(new ReceivedMessageInfo( + serializableMessage.Exchange ?? "", + serializableMessage.RoutingKey ?? "", + body ?? Array.Empty(), + + // IReadOnlyDictionary is not compatible with IDictionary? wow. + new MessageProperties(serializableMessage.Properties?.Headers?.ToDictionary(p => p.Key, p => p.Value)) + { + AppId = serializableMessage.Properties?.AppId, + ContentEncoding = serializableMessage.Properties?.ContentEncoding, + ContentType = serializableMessage.Properties?.ContentType, + CorrelationId = serializableMessage.Properties?.CorrelationId, + DeliveryMode = serializableMessage.Properties?.DeliveryMode switch + { + 2 => MessageDeliveryMode.Persistent, + _ => MessageDeliveryMode.NonPersistent + }, + Expiration = serializableMessage.Properties?.Expiration, + MessageId = serializableMessage.Properties?.MessageId, + Priority = serializableMessage.Properties?.Priority, + ReplyTo = serializableMessage.Properties?.ReplyTo, + Timestamp = messageTimestamp, + Type = serializableMessage.Properties?.Type, + UserId = serializableMessage.Properties?.UserId + }, + messageTimestamp)); + } + + return messages; + } + } +} diff --git a/PettingZoo.Tapeti/PettingZoo.Tapeti.csproj b/PettingZoo.Tapeti/PettingZoo.Tapeti.csproj index 1b716a5..3bf7adf 100644 --- a/PettingZoo.Tapeti/PettingZoo.Tapeti.csproj +++ b/PettingZoo.Tapeti/PettingZoo.Tapeti.csproj @@ -32,24 +32,21 @@ True AssemblyParserStrings.resx - + True True - TapetiCmdExportStrings.resx + TapetiCmdImportExportStrings.resx + + + True + True + TapetiClassLibraryExampleGeneratorStrings.resx True True ClassSelectionStrings.resx - - True - True - PackageProgressStrings.resx - - - Code - True True @@ -62,29 +59,22 @@ ResXFileCodeGenerator AssemblyParserStrings.Designer.cs - + ResXFileCodeGenerator - TapetiCmdExportStrings.Designer.cs + TapetiCmdImportExportStrings.Designer.cs + + + ResXFileCodeGenerator + TapetiClassLibraryExampleGeneratorStrings.Designer.cs PublicResXFileCodeGenerator ClassSelectionStrings.Designer.cs - - PublicResXFileCodeGenerator - PackageProgressStrings.Designer.cs - PublicResXFileCodeGenerator PackageSelectionStrings.Designer.cs - - - $(DefaultXamlRuntime) - Designer - - - diff --git a/PettingZoo.Tapeti/PettingZoo.Tapeti_ooj5vuwa_wpftmp.csproj b/PettingZoo.Tapeti/PettingZoo.Tapeti_ooj5vuwa_wpftmp.csproj new file mode 100644 index 0000000..9e25216 --- /dev/null +++ b/PettingZoo.Tapeti/PettingZoo.Tapeti_ooj5vuwa_wpftmp.csproj @@ -0,0 +1,325 @@ + + + PettingZoo.Tapeti + obj\Debug\ + obj\ + P:\Development\PettingZoo\PettingZoo.Tapeti\obj\ + <_TargetAssemblyProjectName>PettingZoo.Tapeti + + + + net6.0-windows + 0.1 + true + enable + + + + + + + + + + + + + + + + + + + + + True + True + AssemblyParserStrings.resx + + + True + True + TapetiCmdImportExportStrings.resx + + + True + True + TapetiClassLibraryExampleGeneratorStrings.resx + + + True + True + ClassSelectionStrings.resx + + + True + True + PackageSelectionStrings.resx + + + + + ResXFileCodeGenerator + AssemblyParserStrings.Designer.cs + + + ResXFileCodeGenerator + TapetiCmdImportExportStrings.Designer.cs + + + ResXFileCodeGenerator + TapetiClassLibraryExampleGeneratorStrings.Designer.cs + + + PublicResXFileCodeGenerator + ClassSelectionStrings.Designer.cs + + + PublicResXFileCodeGenerator + PackageSelectionStrings.Designer.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/PettingZoo.Tapeti/TapetiClassLibraryExampleGenerator.cs b/PettingZoo.Tapeti/TapetiClassLibraryExampleGenerator.cs index 6471460..6cd0eae 100644 --- a/PettingZoo.Tapeti/TapetiClassLibraryExampleGenerator.cs +++ b/PettingZoo.Tapeti/TapetiClassLibraryExampleGenerator.cs @@ -11,8 +11,8 @@ using PettingZoo.Core.Settings; using PettingZoo.Tapeti.AssemblyLoader; using PettingZoo.Tapeti.NuGet; using PettingZoo.Tapeti.UI.ClassSelection; -using PettingZoo.Tapeti.UI.PackageProgress; using PettingZoo.Tapeti.UI.PackageSelection; +using PettingZoo.WPF.ProgressWindow; using Serilog; namespace PettingZoo.Tapeti @@ -47,7 +47,7 @@ namespace PettingZoo.Tapeti var windowBounds = selectionWindow.RestoreBounds; selectionWindow.Close(); - var progressWindow = new PackageProgressWindow(); + var progressWindow = new ProgressWindow(TapetiClassLibraryExampleGeneratorStrings.ProgressWindowTitle); progressWindow.Left = windowBounds.Left + (windowBounds.Width - progressWindow.Width) / 2; progressWindow.Top = windowBounds.Top + (windowBounds.Height - progressWindow.Height) / 2; progressWindow.Show(); diff --git a/PettingZoo.Tapeti/TapetiClassLibraryExampleGeneratorStrings.Designer.cs b/PettingZoo.Tapeti/TapetiClassLibraryExampleGeneratorStrings.Designer.cs new file mode 100644 index 0000000..935784c --- /dev/null +++ b/PettingZoo.Tapeti/TapetiClassLibraryExampleGeneratorStrings.Designer.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace PettingZoo.Tapeti { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class TapetiClassLibraryExampleGeneratorStrings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal TapetiClassLibraryExampleGeneratorStrings() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PettingZoo.Tapeti.TapetiClassLibraryExampleGeneratorStrings", typeof(TapetiClassLibraryExampleGeneratorStrings).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Reading message classes.... + /// + internal static string ProgressWindowTitle { + get { + return ResourceManager.GetString("ProgressWindowTitle", resourceCulture); + } + } + } +} diff --git a/PettingZoo.Tapeti/TapetiClassLibraryExampleGeneratorStrings.resx b/PettingZoo.Tapeti/TapetiClassLibraryExampleGeneratorStrings.resx new file mode 100644 index 0000000..6bee679 --- /dev/null +++ b/PettingZoo.Tapeti/TapetiClassLibraryExampleGeneratorStrings.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Reading message classes... + + \ No newline at end of file diff --git a/PettingZoo.WPF/PettingZoo.WPF.csproj b/PettingZoo.WPF/PettingZoo.WPF.csproj index 836a73c..3adc030 100644 --- a/PettingZoo.WPF/PettingZoo.WPF.csproj +++ b/PettingZoo.WPF/PettingZoo.WPF.csproj @@ -17,6 +17,28 @@ + + ProgressStrings.resx + True + True + + + Code + + + + + + ProgressStrings.Designer.cs + PublicResXFileCodeGenerator + + + + + + $(DefaultXamlRuntime) + Designer + $(DefaultXamlRuntime) diff --git a/PettingZoo.Tapeti/UI/PackageProgress/PackageProgressStrings.Designer.cs b/PettingZoo.WPF/ProgressWindow/ProgressStrings.Designer.cs similarity index 82% rename from PettingZoo.Tapeti/UI/PackageProgress/PackageProgressStrings.Designer.cs rename to PettingZoo.WPF/ProgressWindow/ProgressStrings.Designer.cs index 6a82b2a..3cb953b 100644 --- a/PettingZoo.Tapeti/UI/PackageProgress/PackageProgressStrings.Designer.cs +++ b/PettingZoo.WPF/ProgressWindow/ProgressStrings.Designer.cs @@ -8,7 +8,7 @@ // //------------------------------------------------------------------------------ -namespace PettingZoo.Tapeti.UI.PackageProgress { +namespace PettingZoo.WPF.ProgressWindow { using System; @@ -22,14 +22,14 @@ namespace PettingZoo.Tapeti.UI.PackageProgress { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - public class PackageProgressStrings { + public class ProgressStrings { private static global::System.Resources.ResourceManager resourceMan; private static global::System.Globalization.CultureInfo resourceCulture; [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal PackageProgressStrings() { + internal ProgressStrings() { } /// @@ -39,7 +39,7 @@ namespace PettingZoo.Tapeti.UI.PackageProgress { public static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PettingZoo.Tapeti.UI.PackageProgress.PackageProgressStrings", typeof(PackageProgressStrings).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PettingZoo.WPF.ProgressWindow.ProgressStrings", typeof(ProgressStrings).Assembly); resourceMan = temp; } return resourceMan; @@ -68,14 +68,5 @@ namespace PettingZoo.Tapeti.UI.PackageProgress { return ResourceManager.GetString("ButtonCancel", resourceCulture); } } - - /// - /// Looks up a localized string similar to Reading message classes.... - /// - public static string WindowTitle { - get { - return ResourceManager.GetString("WindowTitle", resourceCulture); - } - } } } diff --git a/PettingZoo.Tapeti/UI/PackageProgress/PackageProgressStrings.resx b/PettingZoo.WPF/ProgressWindow/ProgressStrings.resx similarity index 98% rename from PettingZoo.Tapeti/UI/PackageProgress/PackageProgressStrings.resx rename to PettingZoo.WPF/ProgressWindow/ProgressStrings.resx index eccbf8f..e527efc 100644 --- a/PettingZoo.Tapeti/UI/PackageProgress/PackageProgressStrings.resx +++ b/PettingZoo.WPF/ProgressWindow/ProgressStrings.resx @@ -120,7 +120,4 @@ Cancel - - Reading message classes... - \ No newline at end of file diff --git a/PettingZoo.Tapeti/UI/PackageProgress/PackageProgressWindow.xaml b/PettingZoo.WPF/ProgressWindow/ProgressWindow.xaml similarity index 65% rename from PettingZoo.Tapeti/UI/PackageProgress/PackageProgressWindow.xaml rename to PettingZoo.WPF/ProgressWindow/ProgressWindow.xaml index aef7232..029fae9 100644 --- a/PettingZoo.Tapeti/UI/PackageProgress/PackageProgressWindow.xaml +++ b/PettingZoo.WPF/ProgressWindow/ProgressWindow.xaml @@ -1,17 +1,16 @@ - - + +