PageRenderTime 329ms CodeModel.GetById 322ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 0ms

/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
 25
 26
 27using System;
 28using System.Linq;
 29using System.Collections;
 30using System.Collections.Generic;
 31
 32namespace Manos.Collections
 33{
 34	/// <summary>
 35	/// A Heirarcical dictionary. Data can live at the "root" level, or in child dictionaries.
 36	/// DataDictionaries can store UnsafeStrings, lists of UnsafeStrings and dictionarys with
 37	/// strings as their key and UnsafeStrings as their values.  To add a list to the DataDictionary
 38	/// simply add an item with a [] at the end of the keyname.  To add a dictionary you
 39	/// just add an item in this format keyname[key].
 40	/// </summary>
 41	public class DataDictionary
 42	{
 43		private Dictionary<string,object> dictionary;
 44		private List<DataDictionary> children;
 45		
 46		public DataDictionary ()
 47		{
 48			dictionary = new Dictionary<string, object> ();
 49		}
 50		
 51		/// <summary>
 52		/// Get or set the string value at the specified key.
 53		/// </summary>
 54		/// <param name="key">
 55		/// A <see cref="System.String"/>
 56		/// </param>
 57		public string this [string key] {
 58			get { return GetString (key); }
 59			set { Set (key, value); }
 60		}
 61
 62		public ICollection<string> Keys {
 63		       get { return dictionary.Keys; }
 64		}
 65		
 66		/// <summary>
 67		/// The sum of child dictionaries count and the count
 68		/// of the keys in this dictionary.
 69		/// </summary>
 70		public int Count {
 71			get {
 72				int sum = 0;
 73				if (children != null)
 74					children.Sum (c => c.Count);
 75				return sum + dictionary.Count;
 76			}
 77		}
 78		
 79		/// <summary>
 80		/// The child dictionaries.
 81		/// </summary>
 82		public IList<DataDictionary> Children {
 83			get {
 84				if (children == null)
 85					children = new List<DataDictionary> ();
 86				return children;
 87			}
 88		}
 89		
 90		/// <summary>
 91		/// The "unsafe" string version of the value that is stored in this dictionary, or "null" if no value is stored for the specified key.
 92		/// </summary>
 93		/// <param name="key">
 94		/// A <see cref="System.String"/>
 95		/// </param>
 96		/// <returns>
 97		/// A <see cref="UnsafeString"/>
 98		/// </returns>
 99		public UnsafeString Get (string key)
100		{
101			return Get<UnsafeString> (key);
102		}
103
104		/// <summary>
105		/// A list of unsafe strings stored with the specified
106		/// key.  Lists are created when an item is added to
107		/// the dictionary with [] at the end of its name.
108		/// </summary>  
109		public IList<UnsafeString> GetList (string key)
110		{
111			return Get<IList<UnsafeString>> (key);
112		}
113
114		/// <summary>
115		/// A dictionary of Unsafe strings.  Dictionaries are
116		/// created when an item is added to the
117		/// DataDictionary with a key in the format:
118		/// foo[key].
119		/// </summary>
120		public IDictionary<string,UnsafeString> GetDict (string key)
121		{
122			return Get<IDictionary<string,UnsafeString>> (key);
123		}
124
125		private T Get<T> (string key)
126		{
127			object value = null;
128			T t = default (T);
129			
130			if (dictionary.TryGetValue (key, out value)) {
131				if (value is T)
132					return (T) value;
133			}
134			
135			if (children != null)
136				children.Where (d => (t = d.Get<T> (key)) != null).FirstOrDefault ();
137			
138			return t;
139		}
140		
141		/// <summary>
142		/// Get a "safe" string from the dictionary, or, if the key doesn't exist in the dictionary, null.
143		/// </summary>
144		/// <param name="key">
145		/// </param>
146		/// <returns>
147		/// The "safe" version of the value that is stored in the dictionary.
148		/// </returns>
149		public string GetString (string key)
150		{
151			UnsafeString str = Get (key);
152			
153			if (str == null)
154				return null;
155			
156			return str.SafeValue;
157		}
158	
159		/// <summary>
160		/// Remove all elements from this dictionary, and remove all references to child dictionaries.
161		/// </summary>
162		public void Clear ()
163		{
164			dictionary.Clear ();
165			children = null;
166		}	
167		
168		/// <summary>
169		/// Assign a value into this dictionary with the specified key.
170		/// </summary>
171		/// <param name="key">
172		/// A <see cref="System.String"/>
173		/// </param>
174		/// <param name="value">
175		/// A <see cref="System.String"/>
176		/// </param>
177		public void Set (string key, string value)
178		{
179			Set (key, new UnsafeString (value));
180		}
181		
182		/// <summary>
183		/// Assign a value into this dictionary with the specified key.
184		/// </summary>
185		/// <param name="key">
186		/// A <see cref="System.String"/>
187		/// </param>
188		/// <param name="value">
189		/// A <see cref="UnsafeString"/>
190		/// </param>
191		public void Set (string key, UnsafeString value)
192		{
193			int open = key.IndexOf ('[');
194			if (open == -1) {
195				dictionary [key] = value;
196				return;
197			}
198
199			string elkey = key.Substring (0, open);
200			int close = key.IndexOf (']');
201			if (close == -1 || close < open) {
202				dictionary [elkey] = value;
203				return;
204			}
205
206			object col;
207			if (close == open + 1) {
208				List<UnsafeString> list = null;
209
210				if (dictionary.TryGetValue (elkey, out col)) {
211					list = col as List<UnsafeString>;
212					if (list != null) {
213						list.Add (value);
214						return;
215					}
216				}
217
218				list = new List<UnsafeString> ();
219				list.Add (value);
220				dictionary [elkey] = list;
221				
222				return;
223			}
224
225			Dictionary<string,UnsafeString> dict = null;
226			string dname = UnsafeString.Escape (key.Substring (open + 1, close - open - 1));
227			if (dictionary.TryGetValue (elkey, out col)) {
228				dict = col as Dictionary<string,UnsafeString>;
229				if (dict != null) {
230					dict [dname] = value;
231					return;
232				}
233			}
234
235			dict = new Dictionary<string,UnsafeString> ();
236			dict [dname] = value;
237			dictionary [elkey] = dict;
238		}
239	}
240}
241