Merge pull request #249 from pcc/xgetinputfocus
[mono.git] / mcs / class / System.Web.Mvc3 / Mvc / TempDataDictionary.cs
1 namespace System.Web.Mvc {
2     using System;
3     using System.Collections;
4     using System.Collections.Generic;
5     using System.Diagnostics.CodeAnalysis;
6     using System.Linq;
7     using System.Runtime.Serialization;
8
9     public class TempDataDictionary : IDictionary<string, object> {
10         internal const string _tempDataSerializationKey = "__tempData";
11
12         private Dictionary<string, object> _data;
13         private HashSet<string> _initialKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
14         private HashSet<string> _retainedKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
15
16         public TempDataDictionary() {
17             _data = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
18         }
19
20         public int Count {
21             get {
22                 return _data.Count;
23             }
24         }
25
26         public ICollection<string> Keys {
27             get {
28                 return _data.Keys;
29             }
30         }
31
32         public void Keep() {
33             _retainedKeys.Clear();
34             _retainedKeys.UnionWith(_data.Keys);
35         }
36
37         public void Keep(string key) {
38             _retainedKeys.Add(key);
39         }
40
41         public void Load(ControllerContext controllerContext, ITempDataProvider tempDataProvider) {
42             IDictionary<string, object> providerDictionary = tempDataProvider.LoadTempData(controllerContext);
43             _data = (providerDictionary != null) ? new Dictionary<string, object>(providerDictionary, StringComparer.OrdinalIgnoreCase) :
44                 new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
45             _initialKeys = new HashSet<string>(_data.Keys, StringComparer.OrdinalIgnoreCase);
46             _retainedKeys.Clear();
47         }
48
49         public object Peek(string key) {
50             object value;
51             _data.TryGetValue(key, out value);
52             return value;
53         }
54
55         public void Save(ControllerContext controllerContext, ITempDataProvider tempDataProvider) {
56             string[] keysToKeep = _initialKeys.Union(_retainedKeys, StringComparer.OrdinalIgnoreCase).ToArray();
57             string[] keysToRemove = _data.Keys.Except(keysToKeep, StringComparer.OrdinalIgnoreCase).ToArray();
58             foreach (string key in keysToRemove) {
59                 _data.Remove(key);
60             }
61             tempDataProvider.SaveTempData(controllerContext, _data);
62         }
63
64         public ICollection<object> Values {
65             get {
66                 return _data.Values;
67             }
68         }
69
70         public object this[string key] {
71             get {
72                 object value;
73                 if (TryGetValue(key, out value)) {
74                     _initialKeys.Remove(key);
75                     return value;
76                 }
77                 return null;
78             }
79             set {
80                 _data[key] = value;
81                 _initialKeys.Add(key);
82             }
83         }
84
85         public void Add(string key, object value) {
86             _data.Add(key, value);
87             _initialKeys.Add(key);
88         }
89
90         public void Clear() {
91             _data.Clear();
92             _retainedKeys.Clear();
93             _initialKeys.Clear();
94         }
95
96         public bool ContainsKey(string key) {
97             return _data.ContainsKey(key);
98         }
99
100         public bool ContainsValue(object value) {
101             return _data.ContainsValue(value);
102         }
103
104         public IEnumerator<KeyValuePair<string, object>> GetEnumerator() {
105             return new TempDataDictionaryEnumerator(this);
106         }
107
108         public bool Remove(string key) {
109             _retainedKeys.Remove(key);
110             _initialKeys.Remove(key);
111             return _data.Remove(key);
112         }
113
114         public bool TryGetValue(string key, out object value) {
115             _initialKeys.Remove(key);
116             return _data.TryGetValue(key, out value);
117         }
118
119         #region ICollection<KeyValuePair<string, object>> Implementation
120         bool ICollection<KeyValuePair<string, object>>.IsReadOnly {
121             get {
122                 return ((ICollection<KeyValuePair<string, object>>)_data).IsReadOnly;
123             }
124         }
125
126         void ICollection<KeyValuePair<string, object>>.CopyTo(KeyValuePair<string, object>[] array, int index) {
127             ((ICollection<KeyValuePair<string, object>>)_data).CopyTo(array, index);
128         }
129
130         void ICollection<KeyValuePair<string, object>>.Add(KeyValuePair<string, object> keyValuePair) {
131             _initialKeys.Add(keyValuePair.Key);
132             ((ICollection<KeyValuePair<string, object>>)_data).Add(keyValuePair);
133         }
134
135         bool ICollection<KeyValuePair<string, object>>.Contains(KeyValuePair<string, object> keyValuePair) {
136             return ((ICollection<KeyValuePair<string, object>>)_data).Contains(keyValuePair);
137         }
138
139         bool ICollection<KeyValuePair<string, object>>.Remove(KeyValuePair<string, object> keyValuePair) {
140             _initialKeys.Remove(keyValuePair.Key);
141             return ((ICollection<KeyValuePair<string, object>>)_data).Remove(keyValuePair);
142         }
143         #endregion
144
145         #region IEnumerable Implementation
146         IEnumerator IEnumerable.GetEnumerator() {
147             return (IEnumerator)(new TempDataDictionaryEnumerator(this));
148         }
149         #endregion
150
151         private sealed class TempDataDictionaryEnumerator : IEnumerator<KeyValuePair<string, object>> {
152             private IEnumerator<KeyValuePair<string, object>> _enumerator;
153             private TempDataDictionary _tempData;
154
155             public TempDataDictionaryEnumerator(TempDataDictionary tempData) {
156                 _tempData = tempData;
157                 _enumerator = _tempData._data.GetEnumerator();
158             }
159
160             public KeyValuePair<string, object> Current {
161                 get {
162                     KeyValuePair<string, object> kvp = _enumerator.Current;
163                     _tempData._initialKeys.Remove(kvp.Key);
164                     return kvp;
165                 }
166             }
167
168             public bool MoveNext() {
169                 return _enumerator.MoveNext();
170             }
171
172             public void Reset() {
173                 _enumerator.Reset();
174             }
175
176             #region IEnumerator Implementation
177             object IEnumerator.Current {
178                 get {
179                     return Current;
180                 }
181             }
182             #endregion
183
184             #region IDisposable Implementation
185             void IDisposable.Dispose() {
186                 _enumerator.Dispose();
187             }
188             #endregion
189         }
190     }
191 }