[smuxi] [Engine] Initial JsonMessageBuffer implementation



commit 8b9e03ae5f18a43a33a61b60a9e195e4b737f3c7
Author: Mirco Bauer <meebey meebey net>
Date:   Mon Feb 27 02:10:51 2012 +0100

    [Engine] Initial JsonMessageBuffer implementation

 src/Engine-Tests/JsonMessageBufferTests.cs     |   49 ++++++
 src/Engine/MessageBuffers/JsonMessageBuffer.cs |  195 ++++++++++++++++++++++++
 src/Engine/Messages/Dto/MessageDtoModelV1.cs   |   63 +++++++-
 3 files changed, 303 insertions(+), 4 deletions(-)
---
diff --git a/src/Engine-Tests/JsonMessageBufferTests.cs b/src/Engine-Tests/JsonMessageBufferTests.cs
new file mode 100644
index 0000000..24d23bf
--- /dev/null
+++ b/src/Engine-Tests/JsonMessageBufferTests.cs
@@ -0,0 +1,49 @@
+// Smuxi - Smart MUltipleXed Irc
+// 
+// Copyright (c) 2012 Mirco Bauer <meebey meebey net>
+// 
+// Full GPL License: <http://www.gnu.org/licenses/gpl.txt>
+// 
+// This program 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 2 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, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+using System;
+using System.IO;
+using NUnit.Framework;
+using Smuxi.Common;
+
+namespace Smuxi.Engine
+{
+    [TestFixture]
+    public class JsonMessageBufferTests : MessageBufferTestsBase
+    {
+        protected override IMessageBuffer CreateBuffer()
+        {
+            var dbPath = Path.Combine(Platform.GetBuffersPath("testuser"),
+                                      "testprot");
+            dbPath = Path.Combine(dbPath, "testnet");
+            dbPath = Path.Combine(dbPath, "testchat.v1.json");
+            if (Directory.Exists(dbPath)) {
+                Directory.Delete(dbPath, true);
+            }
+
+            return OpenBuffer();
+        }
+
+        protected override IMessageBuffer OpenBuffer()
+        {
+            return new JsonMessageBuffer("testuser", "testprot", "testnet", "testchat");
+        }
+
+    }
+}
diff --git a/src/Engine/MessageBuffers/JsonMessageBuffer.cs b/src/Engine/MessageBuffers/JsonMessageBuffer.cs
new file mode 100644
index 0000000..d1d4975
--- /dev/null
+++ b/src/Engine/MessageBuffers/JsonMessageBuffer.cs
@@ -0,0 +1,195 @@
+// Smuxi - Smart MUltipleXed Irc
+// 
+// Copyright (c) 2012 Mirco Bauer <meebey meebey net>
+// 
+// Full GPL License: <http://www.gnu.org/licenses/gpl.txt>
+// 
+// This program 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 2 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, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+using System;
+using System.IO;
+using System.Text;
+using System.Collections.Generic;
+using ServiceStack.Text;
+using Smuxi.Engine.Dto;
+
+namespace Smuxi.Engine
+{
+    public class JsonMessageBuffer : MessageBufferBase
+    {
+#if LOG4NET
+        static readonly log4net.ILog f_Logger = 
log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
+#endif
+        int DefaultMaxChunkSize { get; set; }
+        int MaxChunkSize { get; set; }
+        string ChunkBasePath { get; set; }
+        Int64 FirstChunkOffset { get; set; }
+        Int64 CurrentChunkOffset { get; set; }
+        string CurrentChunkPath { get; set; }
+        List<MessageDtoModelV1> CurrentChunk { get; set; }
+
+        public override int Count {
+            get {
+                return (int) CurrentChunkOffset + CurrentChunk.Count;
+            }
+        }
+
+        public override MessageModel this[int index] {
+            get {
+                throw new NotImplementedException();
+            }
+            set {
+                throw new NotImplementedException();
+            }
+        }
+
+        public JsonMessageBuffer(string sessionUsername, string protocol,
+                                 string networkId, string chatId) :
+                            base(sessionUsername, protocol, networkId, chatId)
+        {
+            DefaultMaxChunkSize = 1000;
+            MaxChunkSize = DefaultMaxChunkSize;
+            ChunkBasePath = GetBufferPath() + ".v1.json";
+            ScanChunks();
+            CurrentChunk = new List<MessageDtoModelV1>(MaxChunkSize);
+        }
+
+        string GetChunkFileName(Int64 index)
+        {
+            return null;
+        }
+
+        void ScanChunks()
+        {
+            if (!Directory.Exists(ChunkBasePath)) {
+                Directory.CreateDirectory(ChunkBasePath);
+            }
+            foreach (var filename in Directory.GetFiles(ChunkBasePath, "*.json")) {
+                var strNumber = filename.Substring(0, filename.IndexOf("."));
+                var strStartNumber = strNumber.Split('-')[0];
+                var strEndNumber = strNumber.Split('-')[1];
+                var intStartNumber = 0L;
+                var intEndNumber = 0L;
+                // find first chunk
+                Int64.TryParse(strStartNumber, out intStartNumber);
+                if (intStartNumber < FirstChunkOffset) {
+                    FirstChunkOffset = intStartNumber;
+                }
+                // find current (newest) chunk
+                if (intStartNumber > CurrentChunkOffset) {
+                    CurrentChunkOffset = intStartNumber;
+                    MaxChunkSize = (int) (intEndNumber - intStartNumber + 1L);
+                }
+            }
+            RefreshCurrentChunkPath();
+        }
+
+        void RefreshCurrentChunkPath()
+        {
+            CurrentChunkPath = Path.Combine(
+                ChunkBasePath,
+                String.Format(
+                    "{0}-{1}.json",
+                    CurrentChunkOffset,
+                    CurrentChunkOffset + MaxChunkSize - 1
+                )
+            );
+        }
+
+        void NextChunk()
+        {
+            Flush();
+            var chunk = new List<MessageDtoModelV1>(MaxChunkSize);
+            CurrentChunk = chunk;
+            CurrentChunkOffset += MaxChunkSize;
+            RefreshCurrentChunkPath();
+        }
+
+        void SerializeChunk(List<MessageDtoModelV1> chunk, TextWriter writer)
+        {
+            JsonSerializer.SerializeToWriter(chunk, writer);
+        }
+
+        List<MessageDtoModelV1> DeserializeChunk(Stream chunkStream)
+        {
+            return JsonSerializer.DeserializeFromStream<List<MessageDtoModelV1>>(chunkStream);
+        }
+
+        public override void Add(MessageModel item)
+        {
+            var chunk = CurrentChunk;
+            if (chunk.Count >= MaxChunkSize) {
+                NextChunk();
+                chunk = CurrentChunk;
+            }
+            chunk.Add(new MessageDtoModelV1(item));
+        }
+
+        public override void Clear()
+        {
+            throw new NotImplementedException ();
+        }
+
+        public override bool Contains(MessageModel item)
+        {
+            throw new NotImplementedException ();
+        }
+
+        public override void CopyTo(MessageModel[] array, int arrayIndex)
+        {
+            throw new NotImplementedException ();
+        }
+
+        public override bool Remove(MessageModel item)
+        {
+            throw new NotImplementedException ();
+        }
+
+        public override IEnumerator<MessageModel> GetEnumerator()
+        {
+            throw new NotImplementedException ();
+        }
+
+        public override int IndexOf(MessageModel item)
+        {
+            throw new NotImplementedException ();
+        }
+
+        public override void Insert(int index, MessageModel item)
+        {
+            throw new NotImplementedException ();
+        }
+
+        public override void RemoveAt(int index)
+        {
+            throw new NotImplementedException ();
+        }
+
+        public override void Flush()
+        {
+            // TODO: use compression?
+            lock (CurrentChunk) {
+                using (var writer = File.OpenWrite(CurrentChunkPath))
+                using (var textWriter = new StreamWriter(writer, Encoding.UTF8)) {
+                    SerializeChunk(CurrentChunk, textWriter);
+                }
+            }
+        }
+
+        public override void Dispose()
+        {
+            Flush();
+        }
+    }
+}
diff --git a/src/Engine/Messages/Dto/MessageDtoModelV1.cs b/src/Engine/Messages/Dto/MessageDtoModelV1.cs
index aa6598d..35ce83f 100644
--- a/src/Engine/Messages/Dto/MessageDtoModelV1.cs
+++ b/src/Engine/Messages/Dto/MessageDtoModelV1.cs
@@ -28,6 +28,25 @@ namespace Smuxi.Engine.Dto
         public List<MessagePartDtoModelV1> MessageParts { get; set; }
         public MessageType MessageType { get; set; }
 
+        public MessageDtoModelV1()
+        {
+        }
+
+        public MessageDtoModelV1(MessageModel msg)
+        {
+            if (msg == null) {
+                throw new ArgumentNullException("msg");
+            }
+
+            TimeStamp = msg.TimeStamp;
+            MessageType = msg.MessageType;
+            MessageParts = new List<MessagePartDtoModelV1>(msg.MessageParts.Count);
+            foreach (var msgPart in msg.MessageParts) {
+                var dtoPart = new MessagePartDtoModelV1(msgPart);
+                MessageParts.Add(dtoPart);
+            }
+        }
+
         public MessageModel ToMessage()
         {
             var msg = new MessageModel() {
@@ -50,9 +69,11 @@ namespace Smuxi.Engine.Dto
                         break;
                     case "URL":
                         var urlPart = new UrlMessagePartModel() {
-                            Url = msgPart.Url,
-                            Protocol = msgPart.Protocol
+                            Url = msgPart.Url
                         };
+                        if (msgPart.Protocol.HasValue) {
+                            urlPart.Protocol = msgPart.Protocol.Value;
+                        }
                         part = urlPart;
                         break;
                     case "Image":
@@ -87,10 +108,44 @@ namespace Smuxi.Engine.Dto
         public string Text { get; set; }
         // UrlMessagePartModel
         public string Url { get; set; }
-        public UrlProtocol Protocol { get; set; }
+        public UrlProtocol? Protocol { get; set; }
         // ImageMessagePartModel
         public string ImageFileName { get; set; }
         public string AlternativeText { get; set; }
+
+        public MessagePartDtoModelV1()
+        {
+        }
+
+        public MessagePartDtoModelV1(MessagePartModel part)
+        {
+            if (part == null) {
+                throw new ArgumentNullException("part");
+            }
+
+            IsHighlight = part.IsHighlight;
+            if (part is TextMessagePartModel) {
+                var textPart = (TextMessagePartModel) part;
+                Type = "Text";
+                ForegroundColor = textPart.ForegroundColor;
+                BackgroundColor = textPart.BackgroundColor;
+                Underline = textPart.Underline;
+                Bold = textPart.Bold;
+                Italic = textPart.Italic;
+                Text = textPart.Text;
+            }
+            if (part is UrlMessagePartModel) {
+                var urlPart = (UrlMessagePartModel) part;
+                Type = "URL";
+                Url = urlPart.Url;
+                Protocol = urlPart.Protocol;
+            }
+            if (part is ImageMessagePartModel) {
+                var imagePart = (ImageMessagePartModel) part;
+                Type = "Image";
+                ImageFileName = imagePart.ImageFileName;
+                AlternativeText = imagePart.AlternativeText;
+            }
+        }
     }
 }
-


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]