Inverness

JsonObjectStore.cs

May 9th, 2014
328
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.13 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Text;
  5. using Newtonsoft.Json;
  6. using Newtonsoft.Json.Bson;
  7.  
  8. namespace Ramp.Data
  9. {
  10.     /// <summary>
  11.     ///     An interface to a key value store that provides support for JSON object serialization.
  12.     /// </summary>
  13.     public class JsonObjectStore
  14.     {
  15.         public const string IndexBucketName = "_JS_IDX";
  16.         public const string VersionKey = "JS_Version";
  17.         public const string BinaryKey = "JS_Binary";
  18.         public const ushort Version = 1;
  19.  
  20.         private readonly IKeyValueStore _store;
  21.         private readonly bool _binary;
  22.         private readonly JsonSerializer _serializer;
  23.         private readonly Encoding _encoding = new UTF8Encoding(false, true); // do not write utf8 byte mark
  24.  
  25.         /// <summary>
  26.         ///     Initialize the store.
  27.         /// </summary>
  28.         /// <param name="store"> The underlying key value store. </param>
  29.         /// <param name="settings"> The JSON serializer settings. If null, uses default settings. </param>
  30.         /// <param name="binary"> True to serialize using the binary BSON format. </param>
  31.         public JsonObjectStore(IKeyValueStore store, JsonSerializerSettings settings = null, bool binary = false)
  32.         {
  33.             if (store == null)
  34.                 throw new ArgumentNullException("store");
  35.             _store = store;
  36.             _binary = binary;
  37.             _serializer = settings == null ? JsonSerializer.CreateDefault() : JsonSerializer.Create(settings);
  38.             Initialize();
  39.         }
  40.  
  41.         /// <summary>
  42.         ///     Gets whether BSON is being used to store objects.
  43.         /// </summary>
  44.         public bool Binary
  45.         {
  46.             get { return _binary; }
  47.         }
  48.  
  49.         /// <summary>
  50.         ///     Gets the underlying key value store.
  51.         /// </summary>
  52.         public IKeyValueStore Store
  53.         {
  54.             get { return _store; }
  55.         }
  56.  
  57.         /// <summary>
  58.         ///     Get an object from the store.
  59.         /// </summary>
  60.         /// <typeparam name="T"> The object type. </typeparam>
  61.         /// <param name="bucket"> The bucket. </param>
  62.         /// <param name="key"> The key. </param>
  63.         /// <param name="serializer"> The serializer to use for deserializing the object. If null, uses the default. </param>
  64.         /// <returns> The deserialized object. </returns>
  65.         public T GetObject<T>(string bucket, string key, JsonSerializer serializer = null)
  66.         {
  67.             serializer = serializer ?? _serializer;
  68.             byte[] data = _store.GetBytesOrDefault(bucket, key);
  69.             if (data == null)
  70.                 return default(T);
  71.             using (JsonReader jreader = GetReader(data))
  72.             {
  73.                 return serializer.Deserialize<T>(jreader);
  74.             }
  75.         }
  76.  
  77.         /// <summary>
  78.         ///     Set an object in the store.
  79.         /// </summary>
  80.         /// <typeparam name="T"> The object type. </typeparam>
  81.         /// <param name="bucket"> The bucket. </param>
  82.         /// <param name="key"> The key. </param>
  83.         /// <param name="value"> The object. </param>
  84.         /// <param name="serializer"> The serializer to use for serializing the object. If null, uses the default. </param>
  85.         public void SetObject<T>(string bucket, string key, T value, JsonSerializer serializer = null)
  86.         {
  87.             serializer = serializer ?? _serializer;
  88.             MemoryStream mstream;
  89.             using (JsonWriter jwriter = GetWriter(out mstream))
  90.             {
  91.                 serializer.Serialize(jwriter, value, typeof(T));
  92.                 jwriter.Flush();
  93.                 _store.Set(bucket, key, mstream.ToArray());
  94.             }
  95.         }
  96.  
  97.         /// <summary>
  98.         ///     Gets all objects in a bucket.
  99.         /// </summary>
  100.         /// <typeparam name="T"> The object type. </typeparam>
  101.         /// <param name="bucket"> The bucket. </param>
  102.         /// <param name="serializer"> The serializer to use for serializing the object. If null, uses the default. </param>
  103.         /// <returns> An enumerable object providing all keys and objects in the specified bucket. </returns>
  104.         public IEnumerable<KeyValuePair<string, T>> GetObjects<T>(string bucket, JsonSerializer serializer)
  105.         {
  106.             serializer = serializer ?? _serializer;
  107.             foreach (KeyValuePair<string, byte[]> item in _store.GetItemBytes(bucket))
  108.             {
  109.                 using (JsonReader jreader = GetReader(item.Value))
  110.                 {
  111.                     yield return new KeyValuePair<string, T>(item.Key, serializer.Deserialize<T>(jreader));
  112.                 }
  113.             }
  114.         }
  115.  
  116.         private void Initialize()
  117.         {
  118.             // Verison check
  119.             var version = _store.GetValueOrDefault<int>(_store.MetadataBucketName, VersionKey);
  120.             if (version > Version)
  121.                 throw new InvalidDataException("Store version is higher than current verison.");
  122.             version = 1;
  123.             _store.Set(_store.MetadataBucketName, VersionKey, version);
  124.  
  125.             // Format check
  126.             bool currentlyBinary = _store.GetValueOrDefault<bool?>(_store.MetadataBucketName, BinaryKey) ?? _binary;
  127.             if (currentlyBinary != _binary)
  128.                 throw new InvalidOperationException("Existing store has different format.");
  129.             _store.Set(_store.MetadataBucketName, BinaryKey, _binary);
  130.         }
  131.  
  132.         private JsonReader GetReader(byte[] data)
  133.         {
  134.             if (_binary)
  135.                 return new BsonReader(new BinaryReader(new MemoryStream(data, false), _encoding), false,
  136.                                       DateTimeKind.Utc);
  137.             return new JsonTextReader(new StreamReader(new MemoryStream(data, false), _encoding));
  138.         }
  139.  
  140.         private JsonWriter GetWriter(out MemoryStream stream)
  141.         {
  142.             stream = new MemoryStream();
  143.             if (_binary)
  144.                 return new BsonWriter(new BinaryWriter(stream, _encoding)) { DateTimeKindHandling = DateTimeKind.Utc };
  145.             return new JsonTextWriter(new StreamWriter(stream, _encoding));
  146.         }
  147.     }
  148. }
Advertisement
Add Comment
Please, Sign In to add comment