Preliminary fix for #1999, incorrect deletions
[pithos-ms-client] / trunk / Pithos.Core / Agents / CloudTransferAction.cs
index bc4a7fa..d2fa100 100644 (file)
@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.Contracts;
 using System.IO;
 using System.Threading;
 using Pithos.Interfaces;
@@ -18,12 +19,15 @@ namespace Pithos.Core.Agents
 
     public class CloudAction
     {
+        public AccountInfo AccountInfo { get; set; }
         public CloudActionType Action { get; set; }
-        public FileInfo LocalFile { get; set; }
+        public FileSystemInfo LocalFile { get; set; }
         public ObjectInfo CloudFile { get; set; }
         public FileState FileState { get; set; }
         public string Container { get; set; }
 
+        public readonly DateTime Created = DateTime.Now;
+
 
         public Lazy<string> LocalHash { get; protected set; }
         private Lazy<string> _topHash;
@@ -34,51 +38,177 @@ namespace Pithos.Core.Agents
         }
 
 
-        protected CloudAction(CloudActionType action)
+        [ContractInvariantMethod]
+        private void Invariants()
+        {
+            Contract.Invariant(AccountInfo!=null);
+        }
+
+        public bool IsShared
+        {
+            get { return  CloudFile!=null && AccountInfo.UserName != CloudFile.Account; }
+        }
+
+        protected CloudAction(AccountInfo accountInfo,CloudActionType action)
         {
+            if (accountInfo==null)
+                throw new ArgumentNullException("accountInfo");
+            Contract.EndContractBlock();
+
             Action = action;
+            AccountInfo = accountInfo;
         }
 
-        public CloudAction(CloudActionType action, FileInfo localFile, ObjectInfo cloudFile,FileState state,int blockSize, string algorithm) : this(action)
+        public CloudAction(AccountInfo accountInfo, CloudActionType action, FileSystemInfo localFile, ObjectInfo cloudFile, FileState state, int blockSize, string algorithm)
+            : this(accountInfo,action)
         {
-            LocalFile = localFile;
+            LocalFile = localFile.WithProperCapitalization();
             CloudFile = cloudFile;
             FileState = state;
             if (LocalFile != null)
             {
+
                 LocalHash = new Lazy<string>(() => LocalFile.CalculateHash(blockSize,algorithm),
                                              LazyThreadSafetyMode.ExecutionAndPublication);
             }
         }
 
+        //Calculate the download path for the cloud file
+        public string GetDownloadPath()
+        {
+            if (CloudFile == null)
+                return String.Empty;
+            var filePath = CloudFile.RelativeUrlToFilePath(AccountInfo.UserName);
+            return Path.Combine(AccountInfo.AccountPath, filePath);
+        }
 
-        //Constructor for downloading files
-        public CloudAction(CloudActionType action, ObjectInfo cloudFile)
+        public override string ToString()
         {
-            Action = action;
-            CloudFile = cloudFile;
+            return String.Format("{0}:{1}->{2}", this.Action, this.LocalFile.FullName, this.CloudFile.Name);
         }
 
+        protected static ObjectInfo CreateObjectInfoFor(AccountInfo accountInfo, FileSystemInfo fileInfo)
+        {
+            Contract.Requires(accountInfo!=null);
+            Contract.Requires(fileInfo!=null);
+            Contract.Ensures(Contract.Result<ObjectInfo>()!=null);
+
+            var capitalizedFileInfo = fileInfo.WithProperCapitalization();
+            var fullLocalName = capitalizedFileInfo.FullName;
+            var othersPath = Path.Combine(accountInfo.AccountPath, FolderConstants.OthersFolder);
+            
+            var isShared = fullLocalName.StartsWith(othersPath, StringComparison.InvariantCultureIgnoreCase);
+            if (isShared)
+            {                
+                var pathRelativeToOther = fullLocalName.Substring(othersPath.Length + 1);
+                var otherParts = pathRelativeToOther.Split('\\');
+                var otherName = otherParts[0];
+                var otherContainer = otherParts[1];
+                return new ObjectInfo
+                           {
+                               Account = otherName, 
+                               Container = otherContainer, 
+                               Name = String.Join("/", otherParts.Splice(2))
+                           };
+            }
+            return new ObjectInfo(accountInfo.AccountPath, accountInfo.UserName, fileInfo);
+        }
     }    
 
+    public class CloudDownloadAction:CloudAction
+    {
+        public CloudDownloadAction(AccountInfo accountInfo, ObjectInfo cloudFile)
+            :base(accountInfo,CloudActionType.DownloadUnconditional)
+        {            
+            if (String.IsNullOrWhiteSpace(cloudFile.Container))
+                throw new ArgumentException("CloudFile.Container","cloudFile");
+            Contract.EndContractBlock();
+
+            CloudFile = cloudFile;
+        }
+
+        [ContractInvariantMethod]
+        private void Invariants()
+        {
+            Contract.Invariant(!String.IsNullOrWhiteSpace(CloudFile.Container));
+        }
+
+        public override string ToString()
+        {
+            return String.Format("{0}: _ <- {1}", this.Action, this.CloudFile.Name);
+        }
+        
+    }
+    public class CloudDeleteAction:CloudAction
+    {
+        public CloudDeleteAction(AccountInfo accountInfo,FileSystemInfo fileInfo, FileState fileState)
+            : this(accountInfo,fileInfo,CreateObjectInfoFor(accountInfo, fileInfo),fileState)
+        {            
+        }
+
+        public CloudDeleteAction(AccountInfo accountInfo, FileSystemInfo fileInfo,ObjectInfo cloudFile, FileState fileState) 
+            : base(accountInfo,CloudActionType.DeleteCloud)
+        {
+            CloudFile = cloudFile;
+            LocalFile = fileInfo;
+            FileState = fileState;
+        }
+
+        public CloudDeleteAction(CloudAction action)
+            : this(action.AccountInfo,action.LocalFile,action.CloudFile,action.FileState)
+        {}
+
+        [ContractInvariantMethod]
+        private void Invariants()
+        {
+            Contract.Invariant(!String.IsNullOrWhiteSpace(CloudFile.Container));
+        }
+
+        public override string ToString()
+        {
+            return String.Format("{0}: _ ->{1}", this.Action, this.CloudFile.Name);
+        }
+
+    }
+
+    public class CloudUploadAction:CloudAction
+    {
+        public CloudUploadAction(AccountInfo accountInfo, FileSystemInfo fileInfo, FileState state, int blockSize, string algorithm)
+            : base(accountInfo, CloudActionType.UploadUnconditional,fileInfo,CreateObjectInfoFor(accountInfo,fileInfo),state,blockSize,algorithm)             
+        {
+        }
+
+        [ContractInvariantMethod]
+        private void Invariants()
+        {
+            Contract.Invariant(!String.IsNullOrWhiteSpace(CloudFile.Container));
+        }
+
+    }
+
     public class CloudMoveAction:CloudAction
     {
-        public string OldFileName { get; set; }
-        public string OldPath { get; set; }
-        public string NewFileName { get; set; }
-        public string NewPath { get; set; }
-
-        public CloudMoveAction(CloudActionType action, string oldPath, string oldFileName, string newFileName, string newPath)
-            :base(action)
-        {
-            OldFileName = oldFileName;
-            OldPath = oldPath;
-            NewFileName = newFileName;
-            NewPath = newPath;
+        public ObjectInfo OldCloudFile { get; set; }
+
+        public FileSystemInfo OldLocalFile { get; set; }
+
+        public CloudMoveAction(AccountInfo accountInfo, CloudActionType action, FileSystemInfo oldFile, FileSystemInfo newFile)
+            :base(accountInfo,action)
+        {
+            LocalFile = newFile;
+            CloudFile = CreateObjectInfoFor(accountInfo, newFile);
+            
+            OldLocalFile = oldFile;
+            OldCloudFile = CreateObjectInfoFor(accountInfo, oldFile);
+
             //This is a rename operation, a hash will not be used
             LocalHash = new Lazy<string>(() => String.Empty, LazyThreadSafetyMode.ExecutionAndPublication);
         }
 
+        public override string ToString()
+        {
+            return String.Format("{0}:{1}->{2}", this.Action, OldCloudFile.Name, CloudFile.Name);
+        }
 
     }