Release 4.0.0-preview1-00051
[platform/core/csapi/tizenfx.git] / src / Tizen.Network.IoTConnectivity / Tizen.Network.IoTConnectivity / ResourceOptions.cs
1  /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17
18 using System;
19 using System.Collections;
20 using System.Collections.Generic;
21 using System.Linq;
22
23 namespace Tizen.Network.IoTConnectivity
24 {
25     /// <summary>
26     /// This class represents resource options. It provides APIs to manage them.\n
27     /// The iotcon options API provides methods for managing vendor specific options of coap packet.\n
28     /// See more about coap packet in http://tools.ietf.org/html/rfc7252.
29     /// </summary>
30     /// <since_tizen> 3 </since_tizen>
31     public class ResourceOptions : IDictionary<ushort, string>, IDisposable
32     {
33         internal const int MaxSize = 2;
34         internal const int IdMin = 2048;
35         internal const int IdMax = 3000;
36         internal const int DataMax = 15;
37
38         internal IntPtr _resourceOptionsHandle = IntPtr.Zero;
39         private readonly IDictionary<ushort, string> _options = new Dictionary<ushort, string>();
40         private bool _disposed = false;
41
42         /// <summary>
43         /// The resource options constructor.
44         /// </summary>
45         /// <since_tizen> 3 </since_tizen>
46         /// <feature>http://tizen.org/feature/iot.ocf</feature>
47         /// <seealso cref="Add()"/>
48         /// <seealso cref="Remove()"/>
49         /// <exception cref="NotSupportedException">Thrown when the iotcon is not supported.</exception>
50         /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory.</exception>
51         /// <code>
52         /// ResourceOptions options = new ResourceOptions();
53         /// </code>
54         public ResourceOptions()
55         {
56             int ret = Interop.IoTConnectivity.Common.Options.Create(out _resourceOptionsHandle);
57             if (ret != (int)IoTConnectivityError.None)
58             {
59                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to create options");
60                 throw IoTConnectivityErrorFactory.GetException(ret);
61             }
62         }
63
64         // internal constructor
65         internal ResourceOptions(IntPtr handleToClone)
66         {
67             int ret = Interop.IoTConnectivity.Common.Options.Create(out _resourceOptionsHandle);
68             if (ret != (int)IoTConnectivityError.None)
69             {
70                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to create options");
71                 throw IoTConnectivityErrorFactory.GetException(ret);
72             }
73
74             Interop.IoTConnectivity.Common.Options.OptionsCallback forEachCallback = (ushort id, string value, IntPtr userData) =>
75             {
76                 Add(id, value);
77                 return true;
78             };
79
80             ret = Interop.IoTConnectivity.Common.Options.ForEach(handleToClone, forEachCallback, IntPtr.Zero);
81             if (ret != (int)IoTConnectivityError.None)
82             {
83                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to iterate options");
84                 throw IoTConnectivityErrorFactory.GetException(ret);
85             }
86         }
87
88         /// <summary>
89         /// Destructor of the ResourceOptions class.
90         /// </summary>
91         ~ResourceOptions()
92         {
93             Dispose(false);
94         }
95
96         /// <summary>
97         /// Contains all the Option keys.
98         /// </summary>
99         /// <since_tizen> 3 </since_tizen>
100         /// <value>All the Option keys.</value>
101         /// <code>
102         /// ResourceOptions options = new ResourceOptions();
103         /// options.Add(2050, "sample-data");
104         /// options.Add(2055, "sample value");
105         /// var keys = options.Keys;
106         /// Console.WriteLine("Resource options contains keys {0} and {1}", keys.ElementAt(0), keys.ElementAt(1));
107         /// </code>
108         public ICollection<ushort> Keys
109         {
110             get
111             {
112                 return _options.Keys;
113             }
114         }
115
116         /// <summary>
117         /// Contains all the Option values.
118         /// </summary>
119         /// <since_tizen> 3 </since_tizen>
120         /// <value>All the Option values.</value>
121         /// <code>
122         /// ResourceOptions options = new ResourceOptions();
123         /// options.Add(2050, "sample-data");
124         /// options.Add(2055, "sample value");
125         /// var values = options.Values;
126         /// Console.WriteLine("Resource options contains values {0} and {1}", values.ElementAt(0), values.ElementAt(1));
127         /// </code>
128         public ICollection<string> Values
129         {
130             get
131             {
132                 return _options.Values;
133             }
134         }
135
136         /// <summary>
137         /// Gets the number of options.
138         /// </summary>
139         /// <since_tizen> 3 </since_tizen>
140         /// <value>The number of options.</value>
141         /// <code>
142         /// ResourceOptions options = new ResourceOptions();
143         /// options.Add(2050, "sample-data");
144         /// options.Add(2055, "sample value");
145         /// var count = options.Count;
146         /// Console.WriteLine("There are {0} keys in the options object", count);
147         /// </code>
148         public int Count
149         {
150             get
151             {
152                 return _options.Count;
153             }
154         }
155
156         /// <summary>
157         /// Represents whether the collection is readonly.
158         /// </summary>
159         /// <since_tizen> 3 </since_tizen>
160         /// <value>Whether the collection is readonly.</value>
161         /// <code>
162         /// ResourceOptions options = new ResourceOptions();
163         /// if (options.IsReadOnly)
164         ///     Console.WriteLine("Read only options");
165         /// </code>
166         public bool IsReadOnly
167         {
168             get
169             {
170                 return _options.IsReadOnly;
171             }
172         }
173
174         /// <summary>
175         /// Gets or sets the option data.
176         /// </summary>
177         /// <since_tizen> 3 </since_tizen>
178         /// <value>The option data.</value>
179         /// <param name="key">The option ID to get or set.</param>
180         /// <returns>The option with the specified ID.</returns>
181         /// <code>
182         /// ResourceOptions options = new ResourceOptions();
183         /// options[2055] = "sample-data";
184         /// Console.WriteLine("Option has : {0}", options[2055]);
185         /// </code>
186         public string this[ushort key]
187         {
188             get
189             {
190                 return _options[key];
191             }
192             set
193             {
194                 Add(key, value);
195             }
196         }
197
198         /// <summary>
199         /// Checks whether the given key exists in Options collection.
200         /// </summary>
201         /// <since_tizen> 3 </since_tizen>
202         /// <param name="key">The key to look for.</param>
203         /// <returns>true if exists. Otherwise, false.</returns>
204         /// <code>
205         /// ResourceOptions options = new ResourceOptions();
206         /// options.Add(2050, "sample-data");
207         /// if (options.ContainsKey(2050))
208         ///     Console.WriteLine("options conatins key : 2050");
209         /// </code>
210         public bool ContainsKey(ushort key)
211         {
212             return _options.ContainsKey(key);
213         }
214
215         /// <summary>
216         /// Adds a new ID and a correspoding data into the options.
217         /// </summary>
218         /// <since_tizen> 3 </since_tizen>
219         /// <remarks>
220         /// ResourceOptions can have up to 2 options. \n
221         /// key is always situated between 2048 and 3000. \n
222         /// Length of option data is less than or equal to 15.
223         /// </remarks>
224         /// <param name="key">The ID of the option to insert.</param>
225         /// <param name="value">The string data to insert into the options.</param>
226         /// <feature>http://tizen.org/feature/iot.ocf</feature>
227         /// <seealso cref="Remove()"/>
228         /// <exception cref="NotSupportedException">Thrown when the iotcon is not supported.</exception>
229         /// <exception cref="ArgumentException">Thrown when there is an invalid parameter.</exception>
230         /// <code>
231         /// ResourceOptions options = new ResourceOptions();
232         /// options.Add(2050, "sample-data");
233         /// </code>
234         public void Add(ushort key, string value)
235         {
236             int ret = (int)IoTConnectivityError.InvalidParameter;
237             if (IsValid(key, value))
238             {
239                 ret = Interop.IoTConnectivity.Common.Options.Add(_resourceOptionsHandle, key, value);
240                 if (ret != (int)IoTConnectivityError.None)
241                 {
242                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add option");
243                     throw IoTConnectivityErrorFactory.GetException(ret);
244                 }
245                 _options.Add(key, value);
246             }
247             else
248             {
249                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Invalid options");
250                 throw IoTConnectivityErrorFactory.GetException((int)IoTConnectivityError.InvalidParameter);
251             }
252         }
253
254         /// <summary>
255         /// Removes the ID and its associated data from the options.
256         /// </summary>
257         /// <since_tizen> 3 </since_tizen>
258         /// <param name="key">The ID of the option to delete.</param>
259         /// <returns>True if operation is successful. Otherwise, false.</returns>
260         /// <feature>http://tizen.org/feature/iot.ocf</feature>
261         /// <seealso cref="Add()"/>
262         /// <exception cref="NotSupportedException">Thrown when the iotcon is not supported.</exception>
263         /// <exception cref="ArgumentException">Thrown when there is an invalid parameter.</exception>
264         /// <code>
265         /// ResourceOptions options = new ResourceOptions();
266         /// options.Add(2050, "12345");
267         /// var result = options.Remove(2050);
268         /// </code>
269         public bool Remove(ushort key)
270         {
271             int ret = Interop.IoTConnectivity.Common.Options.Remove(_resourceOptionsHandle, key);
272             if (ret != (int)IoTConnectivityError.None)
273             {
274                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to remove option");
275                 throw IoTConnectivityErrorFactory.GetException(ret);
276             }
277
278             bool isRemoved = _options.Remove(key);
279
280             return isRemoved;
281         }
282
283         /// <summary>
284         /// Gets the value associated with the specified key.
285         /// </summary>
286         /// <since_tizen> 3 </since_tizen>
287         /// <param name="key">The option ID.</param>
288         /// <param name="value">Value corresponding to option ID.</param>
289         /// <returns>True if the key exists, false otherwise.</returns>
290         /// <code>
291         /// ResourceOptions options = new ResourceOptions();
292         /// options.Add(2050, "12345");
293         /// string value;
294         /// var isPresent = options.TryGetValue(2050, out value);
295         /// if (isPresent)
296         ///     Console.WriteLine("value : {0}", value);
297         /// </code>
298         public bool TryGetValue(ushort key, out string value)
299         {
300             return _options.TryGetValue(key, out value);
301         }
302
303         /// <summary>
304         ///  Adds options key and value as a key value pair.
305         /// </summary>
306         /// <since_tizen> 3 </since_tizen>
307         /// <param name="item">The key value pair.</param>
308         /// <feature>http://tizen.org/feature/iot.ocf</feature>
309         /// <seealso cref="Remove()"/>
310         /// <code>
311         /// ResourceOptions options = new ResourceOptions();
312         /// options.Add(new KeyValuePair<ushort, string>(2050, "12345"));
313         /// </code>
314         public void Add(KeyValuePair<ushort, string> item)
315         {
316             Add(item.Key, item.Value);
317         }
318
319         /// <summary>
320         /// Clears the Options collection.
321         /// </summary>
322         /// <since_tizen> 3 </since_tizen>
323         /// <feature>http://tizen.org/feature/iot.ocf</feature>
324         /// <exception cref="NotSupportedException">Thrown when the iotcon is not supported.</exception>
325         /// <code>
326         /// ResourceOptions options = new ResourceOptions();
327         /// options.Add(2050, "12345");
328         /// options.Add(2055, "sample");
329         /// options.Clear();
330         /// </code>
331         public void Clear()
332         {
333             foreach (ushort key in Keys)
334             {
335                 int ret = Interop.IoTConnectivity.Common.Options.Remove(_resourceOptionsHandle, key);
336                 if (ret != (int)IoTConnectivityError.None)
337                 {
338                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to remove option");
339                     throw IoTConnectivityErrorFactory.GetException(ret);
340                 };
341             }
342             _options.Clear();
343         }
344
345         /// <summary>
346         /// Checks if the given option pair exists.
347         /// </summary>
348         /// <since_tizen> 3 </since_tizen>
349         /// <param name="item">The key value pair.</param>
350         /// <returns>True if exists. Otherwise, false.</returns>
351         /// <code>
352         /// ResourceOptions options = new ResourceOptions();
353         /// options.Add(new KeyValuePair<ushort, string>(2050, "12345"));
354         /// var isPresent = options.Contains(new KeyValuePair<ushort, string>(2050, "12345"));
355         /// if (isPresent)
356         ///     Console.WriteLine("Key value pair is present");
357         /// </code>
358         public bool Contains(KeyValuePair<ushort, string> item)
359         {
360             return _options.Contains(item);
361         }
362
363         /// <summary>
364         /// Copies the elements of the options collection to an array, starting at a particular index.
365         /// </summary>
366         /// <since_tizen> 3 </since_tizen>
367         /// <param name="array">The destination array.</param>
368         /// <param name="arrayIndex">Index parameter.</param>
369         /// <code>
370         /// ResourceOptions options = new ResourceOptions();
371         /// options.Add(new KeyValuePair<ushort, string>(2050, "12345"));
372         /// KeyValuePair<ushort, string>[] dest = new KeyValuePair<ushort, string>[options.Count];
373         /// options.CopyTo(dest, 0);
374         /// Console.WriteLine("Dest conatins ({0}, {1})", dest[0].Key, dest[0].Value);
375         /// </code>
376         public void CopyTo(KeyValuePair<ushort, string>[] array, int arrayIndex)
377         {
378             _options.CopyTo(array, arrayIndex);
379         }
380
381         /// <summary>
382         /// Removes the given key value pair from the options.
383         /// </summary>
384         /// <since_tizen>3</since_tizen>
385         /// <param name="item">The key value pair to remove</param>
386         /// <returns>True if operation is successful. Otherwise, false</returns>
387         /// <feature>http://tizen.org/feature/iot.ocf</feature>
388         /// <seealso cref="Add()"/>
389         /// <exception cref="ArgumentException">Thrown when there is an invalid parameter</exception>
390         /// <code>
391         /// ResourceOptions options = new ResourceOptions();
392         /// options.Add(new KeyValuePair<ushort, string>(2050, "12345"));
393         /// var result = options.Remove(new KeyValuePair<ushort, string>(2050, "12345"));
394         /// </code>
395         public bool Remove(KeyValuePair<ushort, string> item)
396         {
397             return Remove(item.Key);
398         }
399
400         /// <summary>
401         /// Get the enumerator to options collection.
402         /// </summary>
403         /// <since_tizen> 3 </since_tizen>
404         /// <returns>Enumerator to option pairs.</returns>
405         /// <code>
406         /// ResourceOptions options = new ResourceOptions();
407         /// options.Add(new KeyValuePair<ushort, string>(2050, "sample1"));
408         /// options.Add(new KeyValuePair<ushort, string>(2055, "sample2"));
409         /// foreach (KeyValuePair<string, object> pair in options)
410         /// {
411         ///     Console.WriteLine("key : {0}, value : {1}", pair.Key, pair.Value);
412         /// }
413         /// </code>
414         public IEnumerator<KeyValuePair<ushort, string>> GetEnumerator()
415         {
416             return _options.GetEnumerator();
417         }
418
419         /// <summary>
420         /// Releases any unmanaged resources used by this object.
421         /// </summary>
422         /// <since_tizen> 3 </since_tizen>
423         /// <feature>http://tizen.org/feature/iot.ocf</feature>
424         public void Dispose()
425         {
426             Dispose(true);
427             GC.SuppressFinalize(this);
428         }
429
430         /// <summary>
431         /// Gets the enumerator to options collection.
432         /// </summary>
433         /// <since_tizen> 3 </since_tizen>
434         /// <returns>Enumerator to option pairs.</returns>
435         /// <code>
436         /// ResourceOptions options = new ResourceOptions();
437         /// options.Add(new KeyValuePair<ushort, string>(2050, "sample1"));
438         /// options.Add(new KeyValuePair<ushort, string>(2055, "sample2"));
439         /// foreach (KeyValuePair<string, object> pair in options)
440         /// {
441         ///     Console.WriteLine("key : {0}, value : {1}", pair.Key, pair.Value);
442         /// }
443         /// </code>
444         IEnumerator IEnumerable.GetEnumerator()
445         {
446             return _options.GetEnumerator();
447         }
448
449         /// <summary>
450         /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects.
451         /// </summary>
452         /// <since_tizen> 3 </since_tizen>
453         /// <param name="disposing">If true, disposes any disposable objects. If false, does not dispose disposable objects.</param>
454         /// <feature>http://tizen.org/feature/iot.ocf</feature>
455         protected virtual void Dispose(bool disposing)
456         {
457             if (_disposed)
458                 return;
459
460             if (disposing)
461             {
462                 // Free managed objects
463             }
464
465             Interop.IoTConnectivity.Common.Options.Destroy(_resourceOptionsHandle);
466             _disposed = true;
467         }
468
469         private bool IsValid(ushort key, string value)
470         {
471             return (key > IdMin && key < IdMax && value.Length <= DataMax && _options.Count() < MaxSize);
472         }
473     }
474 }