First version of File Properties window. Works with random file
[pithos-ms-client] / trunk / Pithos.Network / TreeHash.cs
index e35b399..4b9f967 100644 (file)
@@ -1,10 +1,13 @@
 using System;
+using System.Collections.Concurrent;
 using System.Collections.Generic;
+using System.Diagnostics.Contracts;
 using System.IO;
 using System.Text;
 using System.Threading.Tasks;
-using Newtonsoft.Json;
+
 using System.Linq;
+using Newtonsoft.Json;
 using Newtonsoft.Json.Linq;
 
 namespace Pithos.Network
@@ -15,7 +18,27 @@ namespace Pithos.Network
         private const int DEFAULT_BLOCK_SIZE = 4*1024*1024;
         public string BlockHash { get; set; }
         public int BlockSize { get; set; }
-        public long Bytes { get; set; }
+        
+        private long _bytes;
+        public long Bytes
+        {
+            get
+            {
+                Contract.Ensures(Contract.Result<long>() >= 0);
+                return _bytes;
+            }
+            set
+            {
+                if (value<0)
+                    throw new ArgumentOutOfRangeException("Bytes");
+                Contract.Requires(value >= 0);
+                Contract.EndContractBlock();
+                
+                _bytes = value;
+            }
+        }
+        
+
 
         public Guid FileId { get; set; }
 
@@ -24,14 +47,10 @@ namespace Pithos.Network
         {
             get { return _topHash.Value; }
         }
-        private readonly Lazy<string> _topHash2;        
-        public string TopHash2
-        {
-            get { return _topHash2.Value; }
-        }
 
-        private IEnumerable<byte[]> _hashes;
-        public IEnumerable<byte[]> Hashes
+        private IList<byte[]> _hashes;
+
+        public IList<byte[]> Hashes
         {
             get { return _hashes; }
             set
@@ -41,7 +60,14 @@ namespace Pithos.Network
             }
         }
 
-        public TreeHash(string algorithm)
+        [ContractInvariantMethod]
+        private void Invariants()
+        {
+            Contract.Invariant(_bytes>=0);
+        }
+        
+
+       public TreeHash(string algorithm)
         {
             BlockHash = algorithm;            
             _topHash = new Lazy<byte[]>(() =>
@@ -63,7 +89,7 @@ namespace Pithos.Network
             
             string[] hashes=null ;
             if (Hashes!=null)
-                hashes= Hashes.Select(hash=>hash.ToHashString()).ToArray();
+                hashes= GetHashesAsStrings();
             value["hashes"]= new JArray(hashes);
             value["block_size"] = BlockSize;
             value["bytes"] = Bytes;
@@ -72,9 +98,46 @@ namespace Pithos.Network
             return json;
         }
 
+        private string[] _stringHashes;
+        //Returns the hashes as an array of hash strings. Used for serialization to Json
+        public string[] GetHashesAsStrings()
+        {
+            return _stringHashes 
+                ?? (_stringHashes = Hashes.Select(hash => hash.ToHashString()).ToArray());
+        }
+
+        ConcurrentDictionary<string, int> _blocks;
+        //Retruns the hashes as a dictionary to the block location. Used to locate blocks
+        public IDictionary<string,int> HashDictionary
+        {
+            get
+            {
+                Func<ConcurrentDictionary<string, int>> blocksInit = () =>
+                {
+                    var blocks =
+                        new ConcurrentDictionary<string, int>();
+                    if (Hashes == null)
+                        return blocks;
+
+                    var blockIndex = 0;
+                    foreach (var hash in this.Hashes)
+                    {
+                        blocks[hash.ToHashString()] = blockIndex++;
+                    }
+                    return blocks;
+                };
+
+                return _blocks ?? (_blocks = blocksInit());
+            }
+        }
+
         //Saves the Json representation to a file
         public Task Save(string filePath)
         {
+            if (String.IsNullOrWhiteSpace(filePath))
+                throw new ArgumentNullException("filePath");
+            Contract.EndContractBlock();
+
             var fileName = FileId.ToString("N");
             var path = Path.Combine(filePath, fileName);
             if (!Directory.Exists(filePath))
@@ -110,9 +173,12 @@ namespace Pithos.Network
         public static TreeHash Parse(string json)
         {
             if (String.IsNullOrWhiteSpace(json))
-                return Empty;
+                return Empty;            
 
             var value = JsonConvert.DeserializeObject<JObject>(json);
+            if (value==null)
+                throw new ArgumentException("The json parameter doesn't contain any json data","json");
+            Contract.Assume(value!=null);
 
             var blockHash = (string) value["block_hash"];
             var size = value.Value<int>("block_size");
@@ -124,7 +190,7 @@ namespace Pithos.Network
             var treeHash = new TreeHash(blockHash)
                                {
                                    BlockSize = size,
-                                   Hashes = hashValues,
+                                   Hashes = hashValues.ToList(),
                                    Bytes = bytes
                                };
             return treeHash;