Some warning fixes and change of some agents from a hand-coded Agent to Dataflow...
[pithos-ms-client] / trunk / Pithos.Interfaces / ObjectInfo.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Diagnostics.Contracts;
4 using System.Dynamic;
5 using System.Globalization;
6 using System.IO;
7 using System.Linq;
8 using System.Text;
9 using Newtonsoft.Json;
10
11 namespace Pithos.Interfaces
12 {
13     public class ObjectInfo:DynamicObject 
14     {
15         private readonly List<string> _knownContainers= new List<string>{"trash"};
16         public string Name { get; set; }
17         
18         
19         public string Hash { get; set; }
20
21         public string X_Object_Hash { get { return Hash; } set { Hash = value; } }
22
23         [JsonProperty("x_object_uuid")]
24         public string UUID { get; set; }
25
26         public long Bytes { get; set; }
27         public string Content_Type { get; set; }
28         public DateTime Last_Modified { get; set; }
29
30         private Dictionary<string, string> _tags=new Dictionary<string, string>();
31         public Dictionary<string, string> Tags
32         {
33             get { return _tags; }
34             set { _tags = value; }
35         }
36
37         private Dictionary<string, string> _extensions=new Dictionary<string, string>();
38         public Dictionary<string, string> Extensions
39         {
40             get { return _extensions; }
41             set
42             {
43                 _extensions = value;
44                 ExtractKnownExtensions();
45             }
46         }
47         
48         
49         private Dictionary<string, string> _permissions=new Dictionary<string, string>();
50         [JsonProperty("x_object_sharing")]
51         [JsonConverter(typeof(PermissionConverter))]
52         public Dictionary<string, string> Permissions
53         {
54             get { return _permissions; }
55             set
56             {
57                 _permissions = value;                
58             }
59         }
60
61         /// <summary>
62         /// Version number
63         /// </summary>
64         [JsonProperty("x_object_version")]
65         public long? Version { get; set; }
66
67
68         /// <summary>
69         /// Shared object permissions can be Read or Write
70         /// </summary>
71         [JsonProperty("x_object_allowed_to")]
72         public string AllowedTo { get; set; }
73
74
75         /// <summary>
76         /// Version timestamp
77         /// </summary>
78         [JsonProperty("X_Object_Version_Timestamp"), JsonConverter(typeof(PithosDateTimeConverter))]
79         public DateTime? VersionTimestamp { get; set; }
80
81         [JsonProperty("X_Object_Modified_By")]
82         public string ModifiedBy { get; set; }
83
84
85         public Stream Stream { get; set; }
86
87         public string Account { get; set; }
88
89         public string Container { get; set; }
90
91         public string ContendDisposition { get; set; }
92
93         public string ContentEncoding { get; set; }
94
95         public string Manifest { get; set; }
96         
97         public bool IsPublic
98         {
99             get { return !String.IsNullOrWhiteSpace(PublicUrl); }
100             set
101             {
102                 if (!value)
103                     PublicUrl = null;
104                 else if (String.IsNullOrWhiteSpace(PublicUrl))
105                     PublicUrl="true";                
106             }
107         }
108
109         [JsonProperty("X_Object_Public")]
110         public string PublicUrl { get; set; }
111
112         public ObjectInfo()
113         {}
114
115         public ObjectInfo(string accountPath,string accountName,FileInfo fileInfo)
116         {
117             if (String.IsNullOrWhiteSpace(accountPath))
118                 throw new ArgumentNullException("accountPath");
119             if (string.IsNullOrWhiteSpace(accountName))
120                 throw new ArgumentNullException("accountName");
121             if (fileInfo == null)
122                 throw new ArgumentNullException("fileInfo");
123             Contract.EndContractBlock();
124
125             var relativeUrl = fileInfo.AsRelativeUrlTo(accountPath);
126             //The first part of the URL is the container
127             var slashIndex = relativeUrl.IndexOf('/');
128             var container = relativeUrl.Substring(0, slashIndex);
129             //The second is the file's url relative to the container
130             var fileUrl = relativeUrl.Substring(slashIndex + 1);
131
132             Account = accountName;
133             Container = container;
134             Name = fileUrl; 
135         }
136
137
138         private void ExtractKnownExtensions()
139         {
140             Version=GetLong(KnownExtensions.X_Object_Version);
141             VersionTimestamp = GetTimestamp(KnownExtensions.X_Object_Version_Timestamp);
142             ModifiedBy = GetString(KnownExtensions.X_Object_Modified_By);
143         }
144
145         private string GetString(string name)
146         {            
147             string value;
148             _extensions.TryGetValue(name, out value);
149             return value ;                        
150         }
151
152         private long? GetLong(string name)
153         {
154             string version;
155             long value;
156             return _extensions.TryGetValue(name, out version) && long.TryParse(version, out value)
157                        ? (long?) value
158                        : null;
159         }
160
161         private DateTime? GetTimestamp(string name)
162         {
163             string version;
164             DateTime value;
165             if (_extensions.TryGetValue(name, out version) && 
166                 DateTime.TryParse(version,CultureInfo.InvariantCulture,DateTimeStyles.AdjustToUniversal, out value))
167             {
168                 return value;
169             }
170             return null;
171         }
172
173
174         public static ObjectInfo Empty = new ObjectInfo
175         {
176             Name = String.Empty,
177             Hash = String.Empty,
178             Bytes = 0,
179             Content_Type = String.Empty,
180             Last_Modified = DateTime.MinValue
181         };
182
183         public string RelativeUrlToFilePath(string currentAccount)
184         {
185             if (Name==null)
186                 throw new InvalidOperationException("Name can't be null");
187             if (String.IsNullOrWhiteSpace(currentAccount))
188                 throw new ArgumentNullException("currentAccount");
189             Contract.EndContractBlock();
190
191             if (this == Empty)
192                 return String.Empty;
193
194             var unescaped = Uri.UnescapeDataString(Name);
195             var path = unescaped.Replace("/", "\\");
196             var pathParts=new Stack<string>();
197             pathParts.Push(path);
198             if (!String.IsNullOrWhiteSpace(Container) && !_knownContainers.Contains(Container))
199                 pathParts.Push(Container);
200             if (!currentAccount.Equals(Account, StringComparison.InvariantCultureIgnoreCase))
201             {
202                 if (Account != null)
203                 {
204                     pathParts.Push(Account);
205                     pathParts.Push("others");
206                 }
207             }
208             var finalPath=Path.Combine(pathParts.ToArray());
209             return finalPath;
210         }
211
212         public override bool TrySetMember(SetMemberBinder binder, object value)
213         {
214             if (binder.Name.StartsWith("x_object_meta"))
215             {
216                 Tags[binder.Name] = value.ToString();
217             }
218             return false;
219         }
220
221         public string GetPermissionString()
222         {
223             if (Permissions==null)
224                 throw new InvalidOperationException();
225             Contract.EndContractBlock();
226
227             var permissionBuilder = new StringBuilder();
228             var groupings = Permissions.GroupBy(pair => pair.Value, pair => pair.Key);
229             foreach (var grouping in groupings)
230             {
231                 permissionBuilder.AppendFormat("{0}={1};", grouping.Key, String.Join(",", grouping));
232             }
233             var permissions = permissionBuilder.ToString().Trim(';');
234             return permissions;
235         }
236
237         public void SetPermissions(string permissions)
238         {
239             if (String.IsNullOrWhiteSpace(permissions))
240                 return;
241
242             var permDict=new Dictionary<string, string>();
243             var perms=permissions.Split(';');
244             foreach (var perm in perms)
245             {
246                 var permPairs=perm.Split('=');
247                 var right = permPairs[0];
248                 var users= permPairs[1].Split(new[]{','},StringSplitOptions.RemoveEmptyEntries);
249                 foreach (var user in users)
250                 {
251                     permDict[user] = right;
252                 }
253             }
254             Permissions = permDict;
255         }
256     }
257 }