/src/Manos/Manos.Collections/DataDictionary.cs

http://github.com/jacksonh/manos · C# · 241 lines · 119 code · 30 blank · 92 comment · 24 complexity · 70332e8e401ec81b25c7da6f75ed5295 MD5 · raw file

  1. //
  2. // Copyright (C) 2010 Jackson Harper (jackson@manosdemono.com)
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining
  5. // a copy of this software and associated documentation files (the
  6. // "Software"), to deal in the Software without restriction, including
  7. // without limitation the rights to use, copy, modify, merge, publish,
  8. // distribute, sublicense, and/or sell copies of the Software, and to
  9. // permit persons to whom the Software is furnished to do so, subject to
  10. // the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be
  13. // included in all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  19. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  20. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  21. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. //
  23. //
  24. using System;
  25. using System.Linq;
  26. using System.Collections;
  27. using System.Collections.Generic;
  28. namespace Manos.Collections
  29. {
  30. /// <summary>
  31. /// A Heirarcical dictionary. Data can live at the "root" level, or in child dictionaries.
  32. /// DataDictionaries can store UnsafeStrings, lists of UnsafeStrings and dictionarys with
  33. /// strings as their key and UnsafeStrings as their values. To add a list to the DataDictionary
  34. /// simply add an item with a [] at the end of the keyname. To add a dictionary you
  35. /// just add an item in this format keyname[key].
  36. /// </summary>
  37. public class DataDictionary
  38. {
  39. private Dictionary<string,object> dictionary;
  40. private List<DataDictionary> children;
  41. public DataDictionary ()
  42. {
  43. dictionary = new Dictionary<string, object> ();
  44. }
  45. /// <summary>
  46. /// Get or set the string value at the specified key.
  47. /// </summary>
  48. /// <param name="key">
  49. /// A <see cref="System.String"/>
  50. /// </param>
  51. public string this [string key] {
  52. get { return GetString (key); }
  53. set { Set (key, value); }
  54. }
  55. public ICollection<string> Keys {
  56. get { return dictionary.Keys; }
  57. }
  58. /// <summary>
  59. /// The sum of child dictionaries count and the count
  60. /// of the keys in this dictionary.
  61. /// </summary>
  62. public int Count {
  63. get {
  64. int sum = 0;
  65. if (children != null)
  66. children.Sum (c => c.Count);
  67. return sum + dictionary.Count;
  68. }
  69. }
  70. /// <summary>
  71. /// The child dictionaries.
  72. /// </summary>
  73. public IList<DataDictionary> Children {
  74. get {
  75. if (children == null)
  76. children = new List<DataDictionary> ();
  77. return children;
  78. }
  79. }
  80. /// <summary>
  81. /// The "unsafe" string version of the value that is stored in this dictionary, or "null" if no value is stored for the specified key.
  82. /// </summary>
  83. /// <param name="key">
  84. /// A <see cref="System.String"/>
  85. /// </param>
  86. /// <returns>
  87. /// A <see cref="UnsafeString"/>
  88. /// </returns>
  89. public UnsafeString Get (string key)
  90. {
  91. return Get<UnsafeString> (key);
  92. }
  93. /// <summary>
  94. /// A list of unsafe strings stored with the specified
  95. /// key. Lists are created when an item is added to
  96. /// the dictionary with [] at the end of its name.
  97. /// </summary>
  98. public IList<UnsafeString> GetList (string key)
  99. {
  100. return Get<IList<UnsafeString>> (key);
  101. }
  102. /// <summary>
  103. /// A dictionary of Unsafe strings. Dictionaries are
  104. /// created when an item is added to the
  105. /// DataDictionary with a key in the format:
  106. /// foo[key].
  107. /// </summary>
  108. public IDictionary<string,UnsafeString> GetDict (string key)
  109. {
  110. return Get<IDictionary<string,UnsafeString>> (key);
  111. }
  112. private T Get<T> (string key)
  113. {
  114. object value = null;
  115. T t = default (T);
  116. if (dictionary.TryGetValue (key, out value)) {
  117. if (value is T)
  118. return (T) value;
  119. }
  120. if (children != null)
  121. children.Where (d => (t = d.Get<T> (key)) != null).FirstOrDefault ();
  122. return t;
  123. }
  124. /// <summary>
  125. /// Get a "safe" string from the dictionary, or, if the key doesn't exist in the dictionary, null.
  126. /// </summary>
  127. /// <param name="key">
  128. /// </param>
  129. /// <returns>
  130. /// The "safe" version of the value that is stored in the dictionary.
  131. /// </returns>
  132. public string GetString (string key)
  133. {
  134. UnsafeString str = Get (key);
  135. if (str == null)
  136. return null;
  137. return str.SafeValue;
  138. }
  139. /// <summary>
  140. /// Remove all elements from this dictionary, and remove all references to child dictionaries.
  141. /// </summary>
  142. public void Clear ()
  143. {
  144. dictionary.Clear ();
  145. children = null;
  146. }
  147. /// <summary>
  148. /// Assign a value into this dictionary with the specified key.
  149. /// </summary>
  150. /// <param name="key">
  151. /// A <see cref="System.String"/>
  152. /// </param>
  153. /// <param name="value">
  154. /// A <see cref="System.String"/>
  155. /// </param>
  156. public void Set (string key, string value)
  157. {
  158. Set (key, new UnsafeString (value));
  159. }
  160. /// <summary>
  161. /// Assign a value into this dictionary with the specified key.
  162. /// </summary>
  163. /// <param name="key">
  164. /// A <see cref="System.String"/>
  165. /// </param>
  166. /// <param name="value">
  167. /// A <see cref="UnsafeString"/>
  168. /// </param>
  169. public void Set (string key, UnsafeString value)
  170. {
  171. int open = key.IndexOf ('[');
  172. if (open == -1) {
  173. dictionary [key] = value;
  174. return;
  175. }
  176. string elkey = key.Substring (0, open);
  177. int close = key.IndexOf (']');
  178. if (close == -1 || close < open) {
  179. dictionary [elkey] = value;
  180. return;
  181. }
  182. object col;
  183. if (close == open + 1) {
  184. List<UnsafeString> list = null;
  185. if (dictionary.TryGetValue (elkey, out col)) {
  186. list = col as List<UnsafeString>;
  187. if (list != null) {
  188. list.Add (value);
  189. return;
  190. }
  191. }
  192. list = new List<UnsafeString> ();
  193. list.Add (value);
  194. dictionary [elkey] = list;
  195. return;
  196. }
  197. Dictionary<string,UnsafeString> dict = null;
  198. string dname = UnsafeString.Escape (key.Substring (open + 1, close - open - 1));
  199. if (dictionary.TryGetValue (elkey, out col)) {
  200. dict = col as Dictionary<string,UnsafeString>;
  201. if (dict != null) {
  202. dict [dname] = value;
  203. return;
  204. }
  205. }
  206. dict = new Dictionary<string,UnsafeString> ();
  207. dict [dname] = value;
  208. dictionary [elkey] = dict;
  209. }
  210. }
  211. }