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