0
|
1 ???using System; |
|
2 using System.Collections; |
|
3 using System.Collections.Generic; |
|
4 //using KvpType = System.Collections.Generic.KeyValuePair<string, UCIS.Pml.PmlElement>; |
|
5 using KvpType = UCIS.Pml.PmlArray.KeyValuePair; |
|
6 |
|
7 namespace UCIS.Pml { |
|
8 public class PmlArray : PmlElement, IDictionary<string, PmlElement>, IList<KvpType>, IList<PmlElement>, ICollection<String> { |
|
9 /* Internal variables */ |
|
10 private List<KvpType> _items = new List<KvpType>(); |
|
11 private int _indexed = 0; |
|
12 |
|
13 /* Internal key-value pair structure */ |
|
14 public class KeyValuePair { |
|
15 internal KeyValuePair(string key, PmlElement value) { this.Key = key; this.Value = value; } |
|
16 public string Key { get; set; } |
|
17 public PmlElement Value { get; set; } |
|
18 } |
|
19 |
|
20 /* Constructors */ |
|
21 public PmlArray() { |
|
22 } |
|
23 public PmlArray(params KeyValuePair<string, PmlElement>[] elements) { |
|
24 foreach (KeyValuePair<string, PmlElement> item in elements) Add(item); |
|
25 } |
|
26 public PmlArray(IEnumerable<KeyValuePair<string, PmlElement>> elements) { |
|
27 foreach (KeyValuePair<String, PmlElement> item in elements) Add(item); |
|
28 } |
|
29 public PmlArray(params PmlElement[] elements) { |
|
30 foreach (PmlElement item in elements) Add(item); |
|
31 } |
|
32 public PmlArray(IEnumerable<PmlElement> elements) { |
|
33 foreach (PmlElement item in elements) Add(item); |
|
34 } |
|
35 public PmlArray(String key1, PmlElement val1) { |
|
36 Add(key1, val1); |
|
37 } |
|
38 public PmlArray(String key1, PmlElement val1, String key2, PmlElement val2) { |
|
39 Add(key1, val1); |
|
40 Add(key2, val2); |
|
41 } |
|
42 public PmlArray(String key1, PmlElement val1, String key2, PmlElement val2, String key3, PmlElement val3) { |
|
43 Add(key1, val1); |
|
44 Add(key2, val2); |
|
45 Add(key3, val3); |
|
46 } |
|
47 public PmlArray(params Object[] interleavedKeyValue) { |
|
48 for (int i = 0; i < interleavedKeyValue.Length; ) { |
|
49 Add(interleavedKeyValue[i++] as String, interleavedKeyValue[i++]); |
|
50 } |
|
51 } |
|
52 public PmlArray(String[] keys, params PmlElement[] values) { |
|
53 if (keys.Length != values.Length) throw new ArgumentException("Length of keys array does not match length of values array"); |
|
54 for (int i = 0; i < keys.Length; i++) { Add(keys[i] as String, values[i]); } |
|
55 } |
|
56 |
|
57 public bool IsIndexed { |
|
58 get { |
|
59 if (_indexed == -1) { |
|
60 _indexed = 0; |
|
61 foreach (KvpType kvp in _items) { |
|
62 if (kvp.Key != null && kvp.Key.Length > 0) { |
|
63 _indexed = 1; |
|
64 break; |
|
65 } |
|
66 } |
|
67 } |
|
68 return _indexed != 0; |
|
69 } |
|
70 } |
|
71 |
|
72 /* PmlElement implementation */ |
|
73 protected override object GetValue() { return _items; } |
|
74 public override PmlElement GetChild(string Name) { return GetItem(Name); } |
|
75 public override PmlElement GetChild(int index) { return GetItem(index); } |
|
76 public override object ToNumeric() { return _items.Count; } |
|
77 public override PmlElementType Type { get { return PmlElementType.Dictionary; } } |
|
78 |
|
79 /* Internal KVP lookup */ |
|
80 private KvpType GetKVP(string name) { |
|
81 return _items.Find(delegate(KvpType kvp) { return (kvp.Key == name); }); |
|
82 } |
|
83 private KvpType GetKVP(PmlElement value) { |
|
84 return _items.Find(delegate(KvpType kvp) { return (kvp.Value == value); }); |
|
85 } |
|
86 private KvpType GetKVP(int index) { |
|
87 if (index < 0 || index >= _items.Count) return null; |
|
88 return _items[index]; |
|
89 } |
|
90 |
|
91 /* Item retrieval */ |
|
92 public PmlElement GetItem(string name) { |
|
93 KvpType kvp = GetKVP(name); |
|
94 return kvp == null ? null : kvp.Value; |
|
95 } |
|
96 public PmlElement GetItem(int index) { |
|
97 if (index < 0 || index >= _items.Count) return null; |
|
98 return _items[index].Value; |
|
99 } |
|
100 public bool TryGetValue(string key, out PmlElement value) { |
|
101 value = GetItem(key); |
|
102 return (value != null); |
|
103 } |
|
104 |
|
105 /* Array implementation */ |
|
106 public PmlElement this[string key] { |
|
107 get { return GetItem(key); } |
|
108 set { |
|
109 Remove(key); |
|
110 Add(key, value); |
|
111 } |
|
112 } |
|
113 public KvpType this[int id] { |
|
114 get { return GetKVP(id); } |
|
115 set { _items[id] = value; } |
|
116 } |
|
117 PmlElement IList<PmlElement>.this[int id] { |
|
118 get { return GetItem(id); } |
|
119 set { |
|
120 KvpType item = GetKVP(id); |
|
121 item = new KvpType(item == null ? null : item.Key, value); |
|
122 _items[id] = item; |
|
123 } |
|
124 } |
|
125 |
|
126 /* Add implementations */ |
|
127 public void Add(KvpType kvp) { //Final Add method, handles all additions (except insertions!) |
|
128 if (_indexed == 0 && kvp.Key != null && kvp.Key.Length > 0) _indexed = 1; |
|
129 _items.Add(kvp); |
|
130 } |
|
131 |
|
132 public PmlElement Add(string Key, PmlElement Element) { |
|
133 if (Element == null) Element = new PmlNull(); |
|
134 Add(new KvpType(Key, Element)); |
|
135 return Element; |
|
136 } |
|
137 |
|
138 public PmlElement Add(string key, Object value) { |
|
139 PmlElement el; |
|
140 if (value == null) { |
|
141 el = new PmlNull(); |
|
142 } else if (value is PmlElement) { |
|
143 el = value as PmlElement; |
|
144 } else if (value is String) { |
|
145 el = new PmlString(value as string); |
|
146 } else if (value is Int32 || value is Int64) { |
|
147 el = new PmlNumber((Int64)value); |
|
148 } else if (value is UInt32 || value is UInt32) { |
|
149 el = new PmlNumber((UInt64)value); |
|
150 } else { |
|
151 el = new PmlString(value.ToString()); |
|
152 } |
|
153 return Add(key, el); |
|
154 } |
|
155 public PmlElement Add(string Key, string Element) { return Add(Key, new PmlString(Element)); } |
|
156 public PmlElement Add(string Key, long Element) { return Add(Key, new PmlInteger(Element)); } |
|
157 public PmlElement Add(string Key, ulong Element) { return Add(Key, new PmlInteger(Element)); } |
|
158 |
|
159 public PmlElement Add(PmlElement Element) { return Add(null, Element); } |
|
160 public PmlElement Add(object Element) { return Add(null, Element); } |
|
161 public PmlElement Add(string Element) { return Add(new PmlString(Element)); } |
|
162 public PmlElement Add(long Element) { return Add(new PmlInteger(Element)); } |
|
163 public PmlElement Add(ulong Element) { return Add(new PmlInteger(Element)); } |
|
164 |
|
165 public void Add(KeyValuePair<string, PmlElement> item) { Add(item.Key, item.Value); } |
|
166 |
|
167 void ICollection<PmlElement>.Add(PmlElement item) { Add(item); } |
|
168 void IDictionary<String, PmlElement>.Add(string key, PmlElement value) { Add(key, value); } |
|
169 |
|
170 /* Insert implementations */ |
|
171 private void Insert(int index, KvpType kvp) { |
|
172 if (kvp.Key != null && kvp.Key.Length > 0 && _indexed == 0) _indexed = 1; |
|
173 _items.Insert(index, kvp); |
|
174 } |
|
175 void IList<KvpType>.Insert(int index, KvpType value) { Insert(index, value); } |
|
176 void IList<PmlElement>.Insert(int index, PmlElement value) { Insert(index, new KvpType(null, value)); } |
|
177 |
|
178 /* Remove */ |
|
179 public bool Remove(KvpType item) { |
|
180 _indexed = -1; |
|
181 return _items.Remove(item); |
|
182 } |
|
183 public void RemoveAt(int index) { |
|
184 _indexed = -1; |
|
185 _items.RemoveAt(index); |
|
186 } |
|
187 public bool Remove(PmlElement item) { |
|
188 KvpType kvp = GetKVP(item); |
|
189 if (kvp == null) return false; |
|
190 return Remove(kvp); |
|
191 } |
|
192 public bool Remove(string Key) { |
|
193 KvpType kvp = GetKVP(Key); |
|
194 if (kvp == null) return false; |
|
195 return Remove(kvp); |
|
196 } |
|
197 bool ICollection<KeyValuePair<string, PmlElement>>.Remove(KeyValuePair<string, PmlElement> kvp) { return Remove(kvp.Key); } |
|
198 |
|
199 public void Clear() { |
|
200 _indexed = 0; |
|
201 _items.Clear(); |
|
202 } |
|
203 |
|
204 /* Contains */ |
|
205 public bool Contains(PmlElement item) { return GetKVP(item) != null; } |
|
206 public bool Contains(string key) { return GetKVP(key) != null; } |
|
207 bool IDictionary<String, PmlElement>.ContainsKey(string key) { return Contains(key); } |
|
208 bool ICollection<KvpType>.Contains(KvpType kvp) { return _items.Contains(kvp); } |
|
209 bool ICollection<KeyValuePair<String, PmlElement>>.Contains(KeyValuePair<String, PmlElement> kvp) { return Contains(kvp.Key); } |
|
210 |
|
211 /* Index lookup */ |
|
212 public int IndexOf(PmlElement value) { return _items.FindIndex(delegate(KvpType kvp) { return (kvp.Value == value); }); } |
|
213 int IList<KvpType>.IndexOf(KvpType value) { return _items.IndexOf(value); } |
|
214 |
|
215 /* Copy operations */ |
|
216 public void CopyTo(KvpType[] array, int offset) { |
|
217 _items.CopyTo(array, offset); |
|
218 } |
|
219 public void CopyTo(PmlElement[] array, int offset) { |
|
220 foreach (KvpType kvp in _items) array[offset++] = kvp.Value; |
|
221 } |
|
222 void ICollection<String>.CopyTo(string[] array, int offset) { |
|
223 foreach (KvpType kvp in _items) array[offset++] = kvp.Key; |
|
224 } |
|
225 void ICollection<KeyValuePair<string, PmlElement>>.CopyTo(KeyValuePair<string, PmlElement>[] array, int offset) { |
|
226 foreach (KvpType kvp in _items) array[offset++] = new KeyValuePair<string,PmlElement>(kvp.Key, kvp.Value); |
|
227 } |
|
228 |
|
229 /* Dictionary props */ |
|
230 public ICollection<PmlElement> Values { get { return this as ICollection<PmlElement>; } } |
|
231 public ICollection<String> Keys { get { return this as ICollection<String>; } } |
|
232 |
|
233 /* Stuf... */ |
|
234 public int Count { get { return _items.Count; } } |
|
235 public bool IsReadOnly { get { return false; } } |
|
236 void ICollection<String>.Add(string value) { throw new NotImplementedException(); } |
|
237 |
|
238 /* Enumerators */ |
|
239 IEnumerator<KvpType> IEnumerable<KvpType>.GetEnumerator() { return _items.GetEnumerator(); } |
|
240 IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } |
|
241 public IEnumerator<PmlElement> GetEnumerator() { return new ValueEnumerator(this); } |
|
242 IEnumerator<String> IEnumerable<String>.GetEnumerator() { return new KeyEnumerator(this); } |
|
243 IEnumerator<KeyValuePair<string, PmlElement>> IEnumerable<KeyValuePair<string, PmlElement>>.GetEnumerator() { return new KvpEnumerator(this); } |
|
244 |
|
245 private class KeyEnumerator : IEnumerator<String> { |
|
246 protected IEnumerator<KvpType> _enum; |
|
247 internal KeyEnumerator(PmlArray array) { _enum = array._items.GetEnumerator(); } |
|
248 private KvpType KVP { get { return _enum.Current; } } |
|
249 public bool MoveNext() { return _enum.MoveNext(); } |
|
250 public void Reset() { _enum.Reset(); } |
|
251 public void Dispose() { _enum.Dispose(); } |
|
252 Object IEnumerator.Current { get { return Current; } } |
|
253 |
|
254 public String Current { get { return KVP == null ? null : KVP.Key; } } |
|
255 } |
|
256 private class ValueEnumerator : IEnumerator<PmlElement> { |
|
257 protected IEnumerator<KvpType> _enum; |
|
258 internal ValueEnumerator(PmlArray array) { _enum = array._items.GetEnumerator(); } |
|
259 private KvpType KVP { get { return _enum.Current; } } |
|
260 public bool MoveNext() { return _enum.MoveNext(); } |
|
261 public void Reset() { _enum.Reset(); } |
|
262 public void Dispose() { _enum.Dispose(); } |
|
263 Object IEnumerator.Current { get { return Current; } } |
|
264 |
|
265 public PmlElement Current { get { return KVP == null ? null : KVP.Value; } } |
|
266 } |
|
267 private class KvpEnumerator : IEnumerator<KeyValuePair<String, PmlElement>> { |
|
268 protected IEnumerator<KvpType> _enum; |
|
269 internal KvpEnumerator(PmlArray array) { _enum = array._items.GetEnumerator(); } |
|
270 private KvpType KVP { get { return _enum.Current; } } |
|
271 public bool MoveNext() { return _enum.MoveNext(); } |
|
272 public void Reset() { _enum.Reset(); } |
|
273 public void Dispose() { _enum.Dispose(); } |
|
274 Object IEnumerator.Current { get { return Current; } } |
|
275 |
|
276 public KeyValuePair<String, PmlElement> Current { get { |
|
277 return KVP == null ? default(KeyValuePair<String, PmlElement>) : new KeyValuePair<String, PmlElement>(KVP.Key, KVP.Value); |
|
278 } } |
|
279 } |
|
280 } |
|
281 } |