Release 4.0.0-preview1-00051
[platform/core/csapi/tizenfx.git] / src / Tizen.Network.IoTConnectivity / Tizen.Network.IoTConnectivity / Attributes.cs
1 /// Copyright 2016 by Samsung Electronics, Inc.,
2 ///
3  /*
4  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an AS IS BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19
20 using System;
21 using System.Collections;
22 using System.Collections.Generic;
23 using System.Runtime.InteropServices;
24
25 namespace Tizen.Network.IoTConnectivity
26 {
27     /// <summary>
28     /// This class represents current attributes of a resource.
29     /// It provides API to manage attributes.
30     /// This class is accessed by using a constructor to create a new instance of this object.
31     /// </summary>
32     /// <since_tizen> 3 </since_tizen>
33     public class Attributes : IDictionary<string, object>, IDisposable
34     {
35         internal IntPtr _resourceAttributesHandle = IntPtr.Zero;
36         private readonly IDictionary<string, object> _attributes = new Dictionary<string, object>();
37         private bool _disposed = false;
38
39         /// <summary>
40         /// The Attributes constructor.
41         /// </summary>
42         /// <since_tizen> 3 </since_tizen>
43         /// <feature>http://tizen.org/feature/iot.ocf</feature>
44         /// <exception cref="NotSupportedException">Thrown when the iotcon is not supported.</exception>
45         /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory.</exception>
46         /// <code>
47         /// Tizen.Network.IoTConnectivity.Attributes attributes = new Tizen.Network.IoTConnectivity.Attributes();
48         /// </code>
49         public Attributes()
50         {
51             int ret = Interop.IoTConnectivity.Common.Attributes.Create(out _resourceAttributesHandle);
52             if (ret != (int)IoTConnectivityError.None)
53             {
54                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to create attributes handle");
55                 throw IoTConnectivityErrorFactory.GetException(ret);
56             }
57         }
58
59         internal Attributes(IntPtr attributesHandleToClone)
60         {
61             int ret = Interop.IoTConnectivity.Common.Attributes.Clone(attributesHandleToClone, out _resourceAttributesHandle);
62             if (ret != (int)IoTConnectivityError.None)
63             {
64                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to create attributes handle");
65                 throw IoTConnectivityErrorFactory.GetException(ret);
66             }
67
68             SetAttributes(_resourceAttributesHandle);
69         }
70
71         /// <summary>
72         /// Destructor of the Attributes class.
73         /// </summary>
74         ~Attributes()
75         {
76             Dispose(false);
77         }
78
79         /// <summary>
80         /// Gets the number of keys.
81         /// </summary>
82         /// <since_tizen> 3 </since_tizen>
83         /// <value>The number of keys.</value>
84         /// <code>
85         /// Tizen.Network.IoTConnectivity.Attributes attributes = new Tizen.Network.IoTConnectivity.Attributes() {
86         /// attributes.Add("brightness", 50);
87         /// var count = attributes.Count;
88         /// Console.WriteLine("There are {0} keys in the attribute object", count);
89         /// </code>
90         public int Count
91         {
92             get
93             {
94                 return _attributes.Count;
95             }
96         }
97
98         /// <summary>
99         /// Represents whether an attribute is readonly.
100         /// </summary>
101         /// <since_tizen> 3 </since_tizen>
102         /// <value>Whether an attribute is readonly.</value>
103         /// <code>
104         /// Tizen.Network.IoTConnectivity.Attributes attributes = new Tizen.Network.IoTConnectivity.Attributes() {
105         ///     { "state", "ON" },
106         ///     { "dim", 10 }
107         /// };
108         /// if (attributes.IsReadOnly)
109         ///     Console.WriteLine("Read only attribute");
110         /// </code>
111         public bool IsReadOnly
112         {
113             get
114             {
115                 return _attributes.IsReadOnly;
116             }
117         }
118
119         /// <summary>
120         /// Contains all the attribute keys.
121         /// </summary>
122         /// <since_tizen> 3 </since_tizen>
123         /// <value>All the attribute keys.</value>
124         /// <code>
125         /// Tizen.Network.IoTConnectivity.Attributes attributes = new Tizen.Network.IoTConnectivity.Attributes() {
126         ///     { "state", "ON" },
127         ///     { "dim", 10 }
128         /// };
129         /// var keys = attributes.Keys;
130         /// Console.WriteLine("Attribute contains keys {0} and {1}", keys.ElementAt(0), keys.ElementAt(1));
131         /// </code>
132         public ICollection<string> Keys
133         {
134             get
135             {
136                 return _attributes.Keys;
137             }
138         }
139
140         /// <summary>
141         /// Contains all the attribute values.
142         /// </summary>
143         /// <since_tizen> 3 </since_tizen>
144         /// <value>All the attribute values.</value>
145         /// <code>
146         /// Tizen.Network.IoTConnectivity.Attributes attributes = new Tizen.Network.IoTConnectivity.Attributes() {
147         ///     { "state", "ON" },
148         ///     { "dim", 10 }
149         /// };
150         /// var values = attributes.Values;
151         /// Console.WriteLine("Attribute contains values {0} and {1}", values.ElementAt(0), values.ElementAt(1));
152         /// </code>
153         public ICollection<object> Values
154         {
155             get
156             {
157                 return _attributes.Values;
158             }
159         }
160
161         /// <summary>
162         /// Gets or sets the attribute with the specified key.
163         /// </summary>
164         /// <since_tizen> 3 </since_tizen>
165         /// <value>The attribute with the specified key.</value>
166         /// <param name="key">The key of the attribute to get or set.</param>
167         /// <returns>The element with the specified key.</returns>
168         /// <code>
169         /// Tizen.Network.IoTConnectivity.Attributes attributes = new Tizen.Network.IoTConnectivity.Attributes();
170         /// attributes["state"] = "ON";
171         /// Console.WriteLine("Attribute value for key 'state' : {0}", attributes["state"]);
172         /// </code>
173         public object this[string key]
174         {
175             get
176             {
177                 if (_attributes.ContainsKey(key))
178                     return _attributes[key];
179                 else
180                     return null;
181             }
182
183             set
184             {
185                 Add(key, value);
186             }
187         }
188
189         /// <summary>
190         /// Adds the attribute key and a value as a key value pair.
191         /// </summary>
192         /// <since_tizen> 3 </since_tizen>
193         /// <param name="item">The key value pair to add.</param>
194         /// <feature>http://tizen.org/feature/iot.ocf</feature>
195         /// <code>
196         /// Tizen.Network.IoTConnectivity.Attributes attributes = new Tizen.Network.IoTConnectivity.Attributes();
197         /// attributes.Add(new KeyValuePair<string, object> ("state", "ON"));
198         /// </code>
199         public void Add(KeyValuePair<string, object> item)
200         {
201             Add(item.Key, item.Value);
202         }
203
204         /// <summary>
205         /// Adds an attribute.
206         /// </summary>
207         /// <since_tizen> 3 </since_tizen>
208         /// <param name="key">The key representing the attribute.</param>
209         /// <param name="value">The value representing the attribute.</param>
210         /// <feature>http://tizen.org/feature/iot.ocf</feature>
211         /// <code>
212         /// Tizen.Network.IoTConnectivity.Attributes attributes = new Tizen.Network.IoTConnectivity.Attributes();
213         /// attributes.Add("brightness", 50);
214         /// </code>
215         public void Add(string key, object value)
216         {
217             int ret = 0;
218             if (value is int)
219             {
220                 ret = Interop.IoTConnectivity.Common.Attributes.AddInt(_resourceAttributesHandle, key, (int)value);
221                 if (ret != (int)IoTConnectivityError.None)
222                 {
223                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add int");
224                     throw IoTConnectivityErrorFactory.GetException(ret);
225                 }
226             }
227             else if (value is Attributes)
228             {
229                 Attributes attribs = (Attributes)value;
230                 ret = Interop.IoTConnectivity.Common.Attributes.AddAttributes(_resourceAttributesHandle, key, attribs._resourceAttributesHandle);
231                 if (ret != (int)IoTConnectivityError.None)
232                 {
233                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add attributes");
234                     throw IoTConnectivityErrorFactory.GetException(ret);
235                 }
236             }
237             else if (value is string)
238             {
239                 ret = Interop.IoTConnectivity.Common.Attributes.AddStr(_resourceAttributesHandle, key, (string)value);
240                 if (ret != (int)IoTConnectivityError.None)
241                 {
242                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add string");
243                     throw IoTConnectivityErrorFactory.GetException(ret);
244                 }
245             }
246             else if (value is double)
247             {
248                 ret = Interop.IoTConnectivity.Common.Attributes.AddDouble(_resourceAttributesHandle, key, (double)value);
249                 if (ret != (int)IoTConnectivityError.None)
250                 {
251                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add double");
252                     throw IoTConnectivityErrorFactory.GetException(ret);
253                 }
254             }
255             else if (value is bool)
256             {
257                 ret = Interop.IoTConnectivity.Common.Attributes.AddBool(_resourceAttributesHandle, key, (bool)value);
258                 if (ret != (int)IoTConnectivityError.None)
259                 {
260                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add bool");
261                     throw IoTConnectivityErrorFactory.GetException(ret);
262                 }
263             }
264             else if (value is byte[])
265             {
266                 byte[] val = value as byte[];
267                 if (val == null)
268                 {
269                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get byte[] val");
270                     throw new ArgumentException("Invalid Parameter");
271                 }
272                 ret = Interop.IoTConnectivity.Common.Attributes.AddByteStr(_resourceAttributesHandle, key, val, val.Length);
273                 if (ret != (int)IoTConnectivityError.None)
274                 {
275                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add bool");
276                     throw IoTConnectivityErrorFactory.GetException(ret);
277                 }
278             }
279             else if (value is IEnumerable)
280             {
281                 IntPtr listHandle = List.GetListHandle(value);
282                 ret = Interop.IoTConnectivity.Common.Attributes.AddList(_resourceAttributesHandle, key, listHandle);
283                 if (ret != (int)IoTConnectivityError.None)
284                 {
285                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add list");
286                     throw IoTConnectivityErrorFactory.GetException(ret);
287                 }
288             }
289             else
290             {
291                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to Add");
292                 throw IoTConnectivityErrorFactory.GetException((int)IoTConnectivityError.InvalidParameter);
293             }
294             _attributes.Add(key, value);
295         }
296
297         /// <summary>
298         /// Clears attributes collection.
299         /// </summary>
300         /// <since_tizen> 3 </since_tizen>
301         /// <feature>http://tizen.org/feature/iot.ocf</feature>
302         /// <exception cref="NotSupportedException">Thrown when the iotcon is not supported</exception>
303         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid</exception>
304         /// <code>
305         /// Tizen.Network.IoTConnectivity.Attributes attributes = new Tizen.Network.IoTConnectivity.Attributes();
306         /// attributes.Add("brightness", 50);
307         /// attributes.Clear();
308         /// </code>
309         public void Clear()
310         {
311             foreach (string key in _attributes.Keys)
312             {
313                 int ret = Interop.IoTConnectivity.Common.Attributes.Remove(_resourceAttributesHandle, key);
314                 if (ret != (int)IoTConnectivityError.None)
315                 {
316                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to clear attributes");
317                     throw IoTConnectivityErrorFactory.GetException(ret);
318                 }
319             }
320             _attributes.Clear();
321         }
322
323         /// <summary>
324         /// Checks whether the given key value pair exists in attributes collection.
325         /// </summary>
326         /// <since_tizen> 3 </since_tizen>
327         /// <param name="item">The status key value pair.</param>
328         /// <returns>true if exists. Otherwise, false.</returns>
329         /// <code>
330         /// Tizen.Network.IoTConnectivity.Attributes attributes = new Tizen.Network.IoTConnectivity.Attributes() {
331         ///     { "state", "ON" },
332         ///     { "dim", 10 }
333         /// };
334         /// if (attributes.Contains(new KeyValuePair<string, object> ("dim", 10))
335         ///     Console.WriteLine("Attribute conatins pair ('dim', 10)");
336         /// </code>
337         public bool Contains(KeyValuePair<string, object> item)
338         {
339             return _attributes.Contains(item);
340         }
341
342         /// <summary>
343         /// Checks whether the given key exists in attributes collection.
344         /// </summary>
345         /// <since_tizen> 3 </since_tizen>
346         /// <param name="key">The status key to look for.</param>
347         /// <returns>true if exists. Otherwise, false.</returns>
348         /// <code>
349         /// Tizen.Network.IoTConnectivity.Attributes attributes = new Tizen.Network.IoTConnectivity.Attributes() {
350         ///     { "state", "ON" },
351         ///     { "dim", 10 }
352         /// };
353         /// if (attributes.ContainsKey("dim"))
354         ///     Console.WriteLine("Attribute conatins key : dim");
355         /// </code>
356         public bool ContainsKey(string key)
357         {
358             return _attributes.ContainsKey(key);
359         }
360
361         /// <summary>
362         /// Copies the elements of the attributes to an array, starting at a particular index.
363         /// </summary>
364         /// <since_tizen> 3 </since_tizen>
365         /// <param name="array">The destination array.</param>
366         /// <param name="arrayIndex">The zero-based index in an array at which copying begins.</param>
367         /// <code>
368         /// Tizen.Network.IoTConnectivity.Attributes attributes = new Tizen.Network.IoTConnectivity.Attributes() {
369         ///     { "state", "ON" },
370         ///     { "dim", 10 }
371         /// };
372         /// KeyValuePair<string, object>[] dest = new KeyValuePair<string, object>[attributes.Count];
373         /// int index = 0;
374         /// attributes.CopyTo(dest, index);
375         /// Console.WriteLine("Dest conatins ({0}, {1})", dest[0].Key, dest[0].Value);
376         /// </code>
377         public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
378         {
379             _attributes.CopyTo(array, arrayIndex);
380         }
381
382         /// <summary>
383         /// Returns an enumerator that iterates through the collection.
384         /// </summary>
385         /// <since_tizen> 3 </since_tizen>
386         /// <returns> An enumerator that can be used to iterate through the collection.</returns>
387         /// <code>
388         /// Tizen.Network.IoTConnectivity.Attributes attributes = new Tizen.Network.IoTConnectivity.Attributes() {
389         ///     { "state", "ON" },
390         ///     { "dim", 10 }
391         /// };
392         /// foreach (KeyValuePair<string, object> pair in attributes)
393         /// {
394         ///     Console.WriteLine("key : {0}, value : {1}", pair.Key, pair.Value);
395         /// }
396         /// </code>
397         public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
398         {
399             return _attributes.GetEnumerator();
400         }
401
402         /// <summary>
403         /// Removes an attribute from collection.
404         /// </summary>
405         /// <since_tizen> 3 </since_tizen>
406         /// <param name="item">The attributes element to remove.</param>
407         /// <returns>true if operation is successful, otherwise, false.</returns>
408         /// <feature>http://tizen.org/feature/iot.ocf</feature>
409         /// <exception cref="NotSupportedException">Thrown when the iotcon is not supported</exception>
410         /// <exception cref="ArgumentException">Thrown when there is an invalid parameter</exception>
411         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid</exception>
412         /// <code>
413         /// Tizen.Network.IoTConnectivity.Attributes attributes = new Tizen.Network.IoTConnectivity.Attributes() {
414         ///     { "state", "ON" },
415         ///     { "dim", 10 }
416         /// };
417         /// if (attributes.Remove(new KeyValuePair<string, object>("dim", 10)))
418         ///     Console.WriteLine("Remove was successful");
419         /// </code>
420         public bool Remove(KeyValuePair<string, object> item)
421         {
422             return Remove(item.Key);
423         }
424
425         /// <summary>
426         /// Removes an attribute from collection using a key.
427         /// </summary>
428         /// <since_tizen> 3 </since_tizen>
429         /// <param name="key">The attributes element to remove.</param>
430         /// <returns>true if operation is successful, otherwise, false.</returns>
431         /// <feature>http://tizen.org/feature/iot.ocf</feature>
432         /// <exception cref="NotSupportedException">Thrown when the iotcon is not supported</exception>
433         /// <exception cref="ArgumentException">Thrown when there is an invalid parameter</exception>
434         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid</exception>
435         /// <code>
436         /// Tizen.Network.IoTConnectivity.Attributes attributes = new Tizen.Network.IoTConnectivity.Attributes() {
437         ///     { "state", "ON" },
438         ///     { "dim", 10 }
439         /// };
440         /// if (attributes.Remove("state"))
441         ///     Console.WriteLine("Remove was successful");
442         /// </code>
443         public bool Remove(string key)
444         {
445             int ret = Interop.IoTConnectivity.Common.Attributes.Remove(_resourceAttributesHandle, key);
446             if (ret != (int)IoTConnectivityError.None)
447             {
448                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to remove attributes");
449                 throw IoTConnectivityErrorFactory.GetException(ret);
450             }
451
452             bool isRemoved = _attributes.Remove(key);
453
454             return isRemoved;
455         }
456
457         /// <summary>
458         /// Gets the value associated with the specified key.
459         /// </summary>
460         /// <since_tizen> 3 </since_tizen>
461         /// <param name="key">The key whose value to get.</param>
462         /// <param name="value"> The value associated with the specified key.</param>
463         /// <returns> true if the attributes collection contains an element with the specified key, otherwise, false.</returns>
464         /// <code>
465         /// Tizen.Network.IoTConnectivity.Attributes attributes = new Tizen.Network.IoTConnectivity.Attributes() {
466         ///     { "state", "ON" }
467         /// };
468         /// object value;
469         /// var isPresent = attributes.TryGetValue("state", out value);
470         /// if (isPresent)
471         ///     Console.WriteLine("value : {0}", value);
472         /// </code>
473         public bool TryGetValue(string key, out object value)
474         {
475             return _attributes.TryGetValue(key, out value);
476         }
477
478         /// <summary>
479         /// Returns an enumerator that iterates through the collection.
480         /// </summary>
481         /// <since_tizen> 3 </since_tizen>
482         IEnumerator IEnumerable.GetEnumerator()
483         {
484             return _attributes.GetEnumerator();
485         }
486
487         /// <summary>
488         /// Releases any unmanaged resources used by this object.
489         /// </summary>
490         /// <since_tizen> 3 </since_tizen>
491         /// <feature>http://tizen.org/feature/iot.ocf</feature>
492         public void Dispose()
493         {
494             Dispose(true);
495             GC.SuppressFinalize(this);
496         }
497
498         /// <summary>
499         /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects.
500         /// </summary>
501         /// <since_tizen> 3 </since_tizen>
502         /// <param name="disposing">If true, disposes any disposable objects. If false, does not dispose disposable objects.</param>
503         /// <feature>http://tizen.org/feature/iot.ocf</feature>
504         protected virtual void Dispose(bool disposing)
505         {
506             if (_disposed)
507                 return;
508
509             if (disposing)
510             {
511                 // Free managed objects
512             }
513
514             Interop.IoTConnectivity.Common.Attributes.Destroy(_resourceAttributesHandle);
515             _disposed = true;
516         }
517
518         private void SetAttributes(IntPtr attributesHandle)
519         {
520             Interop.IoTConnectivity.Common.Attributes.AttributesCallback cb = (IntPtr attributes, string key, IntPtr userData) =>
521             {
522                 Interop.IoTConnectivity.Common.DataType dataType;
523                 int ret = Interop.IoTConnectivity.Common.Attributes.GetType(attributes, key, out dataType);
524                 if (ret != (int)IoTConnectivityError.None)
525                 {
526                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get type");
527                     throw IoTConnectivityErrorFactory.GetException(ret);
528                 }
529
530                 switch ((Interop.IoTConnectivity.Common.DataType)dataType)
531                 {
532                     case Interop.IoTConnectivity.Common.DataType.Int:
533                         {
534                             int value;
535                             ret = Interop.IoTConnectivity.Common.Attributes.GetInt(attributes, key, out value);
536                             if (ret != (int)IoTConnectivityError.None)
537                             {
538                                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get attributes");
539                                 throw IoTConnectivityErrorFactory.GetException(ret);
540                             }
541                             _attributes.Add(key, value);
542                             break;
543                         }
544                     case Interop.IoTConnectivity.Common.DataType.Bool:
545                         {
546                             bool value;
547                             ret = Interop.IoTConnectivity.Common.Attributes.GetBool(attributes, key, out value);
548                             if (ret != (int)IoTConnectivityError.None)
549                             {
550                                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get attributes");
551                                 throw IoTConnectivityErrorFactory.GetException(ret);
552                             }
553                             _attributes.Add(key, value);
554                             break;
555                         }
556                     case Interop.IoTConnectivity.Common.DataType.Double:
557                         {
558                             double value;
559                             ret = Interop.IoTConnectivity.Common.Attributes.GetDouble(attributes, key, out value);
560                             if (ret != (int)IoTConnectivityError.None)
561                             {
562                                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get attributes");
563                                 throw IoTConnectivityErrorFactory.GetException(ret);
564                             }
565                             _attributes.Add(key, value);
566                             break;
567                         }
568                     case Interop.IoTConnectivity.Common.DataType.String:
569                         {
570                             IntPtr value;
571                             string Str;
572                             ret = Interop.IoTConnectivity.Common.Attributes.GetStr(attributes, key, out value);
573                             if (ret != (int)IoTConnectivityError.None)
574                             {
575                                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get attributes");
576                                 throw IoTConnectivityErrorFactory.GetException(ret);
577                             }
578                             Str = (value != IntPtr.Zero) ? Marshal.PtrToStringAnsi(value) : string.Empty;
579                             _attributes.Add(key, Str);
580                             break;
581                         }
582                     case Interop.IoTConnectivity.Common.DataType.ByteStr:
583                         {
584                             IntPtr byteStrPtr;
585                             int byteStrSize;
586                             ret = Interop.IoTConnectivity.Common.Attributes.GetByteStr(attributes, key, out byteStrPtr, out byteStrSize);
587                             if (ret != (int)IoTConnectivityError.None)
588                             {
589                                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get attributes");
590                                 throw IoTConnectivityErrorFactory.GetException(ret);
591                             }
592                             byte[] byteStr = new byte[byteStrSize];
593                             Marshal.Copy(byteStrPtr, byteStr, 0, byteStrSize);
594                             _attributes.Add(key, byteStr);
595                             break;
596                         }
597                     case Interop.IoTConnectivity.Common.DataType.Null:
598                         {
599                             _attributes.Add(key, null);
600                             break;
601                         }
602                     case Interop.IoTConnectivity.Common.DataType.List:
603                         {
604                             IntPtr listHandle;
605                             ret = Interop.IoTConnectivity.Common.Attributes.GetList(attributes, key, out listHandle);
606                             if (ret != (int)IoTConnectivityError.None)
607                             {
608                                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get attributes");
609                                 throw IoTConnectivityErrorFactory.GetException(ret);
610                             }
611                             _attributes.Add(key, List.GetList(listHandle));
612                             break;
613                         }
614                     case Interop.IoTConnectivity.Common.DataType.Attributes:
615                         {
616                             IntPtr attribsHandle;
617                             ret = Interop.IoTConnectivity.Common.Attributes.GetAttributes(attributes, key, out attribsHandle);
618                             if (ret != (int)IoTConnectivityError.None)
619                             {
620                                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get attributes");
621                                 throw IoTConnectivityErrorFactory.GetException(ret);
622                             }
623                             _attributes.Add(key, new Attributes(attribsHandle));
624                             break;
625                         }
626                     default:
627                         break;
628                 }
629
630                 return true;
631             };
632
633             int res = Interop.IoTConnectivity.Common.Attributes.Foreach(attributesHandle, cb, IntPtr.Zero);
634             if (res != (int)IoTConnectivityError.None)
635             {
636                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to remove attributes");
637                 throw IoTConnectivityErrorFactory.GetException(res);
638             }
639         }
640     }
641
642     internal static class List
643     {
644         internal static IntPtr GetListHandle(object list)
645         {
646             IntPtr listHandle = IntPtr.Zero;
647             int ret;
648             int pos = 0;
649
650             if (list is IEnumerable<IEnumerable>)
651             {
652                 ret = Interop.IoTConnectivity.Common.List.Create(Interop.IoTConnectivity.Common.DataType.List, out listHandle);
653                 pos = 0;
654                 foreach (IEnumerable val in (IEnumerable<IEnumerable>)list)
655                 {
656                     IntPtr childList = GetListHandle(val);
657                     ret = Interop.IoTConnectivity.Common.List.AddList(listHandle, childList, pos++);
658                     if (ret != (int)IoTConnectivityError.None)
659                     {
660                         Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add attributes");
661                         Interop.IoTConnectivity.Common.List.Destroy(childList);
662                         throw IoTConnectivityErrorFactory.GetException(ret);
663                     }
664                 }
665             }
666             else if (list is IEnumerable<int>)
667             {
668                 ret = Interop.IoTConnectivity.Common.List.Create(Interop.IoTConnectivity.Common.DataType.Int, out listHandle);
669                 pos = 0;
670                 foreach (int val in (IEnumerable<int>)list)
671                 {
672                     ret = Interop.IoTConnectivity.Common.List.AddInt(listHandle, val, pos++);
673                     if (ret != (int)IoTConnectivityError.None)
674                     {
675                         Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add attributes");
676                         throw IoTConnectivityErrorFactory.GetException(ret);
677                     }
678                 }
679             }
680             else if (list is IEnumerable<string>)
681             {
682                 ret = Interop.IoTConnectivity.Common.List.Create(Interop.IoTConnectivity.Common.DataType.String, out listHandle);
683                 pos = 0;
684                 foreach (string val in (IEnumerable<string>)list)
685                 {
686                     ret = Interop.IoTConnectivity.Common.List.AddStr(listHandle, val, pos++);
687                     if (ret != (int)IoTConnectivityError.None)
688                     {
689                         Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add str");
690                         throw IoTConnectivityErrorFactory.GetException(ret);
691                     }
692                 }
693             }
694             else if (list is IEnumerable<double>)
695             {
696                 ret = Interop.IoTConnectivity.Common.List.Create(Interop.IoTConnectivity.Common.DataType.Double, out listHandle);
697                 pos = 0;
698                 foreach (double val in (IEnumerable<double>)list)
699                 {
700                     ret = Interop.IoTConnectivity.Common.List.AddDouble(listHandle, val, pos++);
701                     if (ret != (int)IoTConnectivityError.None)
702                     {
703                         Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add double");
704                         throw IoTConnectivityErrorFactory.GetException(ret);
705                     }
706                 }
707             }
708             else if (list is IEnumerable<bool>)
709             {
710                 ret = Interop.IoTConnectivity.Common.List.Create(Interop.IoTConnectivity.Common.DataType.Bool, out listHandle);
711                 pos = 0;
712                 foreach (bool val in (IEnumerable<bool>)list)
713                 {
714                     ret = Interop.IoTConnectivity.Common.List.AddBool(listHandle, val, pos++);
715                     if (ret != (int)IoTConnectivityError.None)
716                     {
717                         Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add bool");
718                         throw IoTConnectivityErrorFactory.GetException(ret);
719                     }
720                 }
721             }
722             else if (list is IEnumerable<Attributes>)
723             {
724                 ret = Interop.IoTConnectivity.Common.List.Create(Interop.IoTConnectivity.Common.DataType.Attributes, out listHandle);
725                 pos = 0;
726                 foreach (Attributes val in (IEnumerable<Attributes>)list)
727                 {
728                     ret = Interop.IoTConnectivity.Common.List.AddAttributes(listHandle, val._resourceAttributesHandle, pos++);
729                     if (ret != (int)IoTConnectivityError.None)
730                     {
731                         Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add attributes");
732                         throw IoTConnectivityErrorFactory.GetException(ret);
733                     }
734                 }
735             }
736             else if (list is IEnumerable<byte[]>)
737             {
738                 ret = Interop.IoTConnectivity.Common.List.Create(Interop.IoTConnectivity.Common.DataType.ByteStr, out listHandle);
739                 pos = 0;
740                 foreach (byte[] val in (IEnumerable<byte[]>)list)
741                 {
742                     ret = Interop.IoTConnectivity.Common.List.AddByteStr(listHandle, val, val.Length, pos++);
743                     if (ret != (int)IoTConnectivityError.None)
744                     {
745                         Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add byte[]");
746                         throw IoTConnectivityErrorFactory.GetException(ret);
747                     }
748                 }
749             }
750             else
751             {
752                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to GetListHandle");
753                 throw IoTConnectivityErrorFactory.GetException((int)IoTConnectivityError.InvalidParameter);
754             }
755             return listHandle;
756         }
757
758         internal static object GetList(IntPtr listHandle)
759         {
760             IList list = null;
761             int type;
762             int ret = Interop.IoTConnectivity.Common.List.GetType(listHandle, out type);
763             if (ret != (int)IoTConnectivityError.None)
764             {
765                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get type");
766                 throw IoTConnectivityErrorFactory.GetException(ret);
767             }
768             switch ((Interop.IoTConnectivity.Common.DataType)type)
769             {
770                 case Interop.IoTConnectivity.Common.DataType.Int:
771                     {
772                         list = new List<int>();
773                         Interop.IoTConnectivity.Common.List.IntCallback cb = (int pos, int value, IntPtr userData) =>
774                         {
775                             list.Add(value);
776                             return true;
777                         };
778                         ret = Interop.IoTConnectivity.Common.List.ForeachInt(listHandle, cb, IntPtr.Zero);
779                         break;
780                     }
781                 case Interop.IoTConnectivity.Common.DataType.Bool:
782                     {
783                         list = new List<bool>();
784                         Interop.IoTConnectivity.Common.List.BoolCallback cb = (int pos, bool value, IntPtr userData) =>
785                         {
786                             list.Add(value);
787                             return true;
788                         };
789                         ret = Interop.IoTConnectivity.Common.List.ForeachBool(listHandle, cb, IntPtr.Zero);
790                         break;
791                     }
792                 case Interop.IoTConnectivity.Common.DataType.Double:
793                     {
794                         list = new List<double>();
795                         Interop.IoTConnectivity.Common.List.DoubleCallback cb = (int pos, double value, IntPtr userData) =>
796                         {
797                             list.Add(value);
798                             return true;
799                         };
800                         ret = Interop.IoTConnectivity.Common.List.ForeachDouble(listHandle, cb, IntPtr.Zero);
801                         break;
802                     }
803                 case Interop.IoTConnectivity.Common.DataType.String:
804                     {
805                         list = new List<string>();
806                         Interop.IoTConnectivity.Common.List.StrCallback cb = (int pos, string value, IntPtr userData) =>
807                         {
808                             list.Add(value);
809                             return true;
810                         };
811                         ret = Interop.IoTConnectivity.Common.List.ForeachStr(listHandle, cb, IntPtr.Zero);
812                         break;
813                     }
814                 case Interop.IoTConnectivity.Common.DataType.Attributes:
815                     {
816                         list = new List<Attributes>();
817                         Interop.IoTConnectivity.Common.List.AttribsCallback cb = (int pos, IntPtr value, IntPtr userData) =>
818                         {
819                             list.Add(new Attributes(value));
820                             return true;
821                         };
822                         ret = Interop.IoTConnectivity.Common.List.ForeachAttributes(listHandle, cb, IntPtr.Zero);
823                         break;
824                     }
825                 case Interop.IoTConnectivity.Common.DataType.ByteStr:
826                     {
827                         list = new List<byte[]>();
828                         Interop.IoTConnectivity.Common.List.ByteStrCallback cb = (int pos, byte[] value, int len, IntPtr userData) =>
829                         {
830                             list.Add(value);
831                             return true;
832                         };
833                         ret = Interop.IoTConnectivity.Common.List.ForeachByteStr(listHandle, cb, IntPtr.Zero);
834                         break;
835                     }
836                 case Interop.IoTConnectivity.Common.DataType.List:
837                     {
838                         list = new List<List<object>>();
839                         Interop.IoTConnectivity.Common.List.ListCallback cb = (int pos, IntPtr value, IntPtr userData) =>
840                         {
841                             object childList = GetList(value);
842                             if (childList != null)
843                                 list.Add(childList);
844                             return true;
845                         };
846                         ret = Interop.IoTConnectivity.Common.List.ForeachList(listHandle, cb, IntPtr.Zero);
847                         break;
848                     }
849                 default:
850                     break;
851             }
852             if (ret != (int)IoTConnectivityError.None)
853             {
854                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get attributes");
855                 throw IoTConnectivityErrorFactory.GetException(ret);
856             }
857             return list;
858         }
859     }
860 }