Update according to design review
[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     public class ResourceOptions : IDictionary<ushort, string>, IDisposable
31     {
32         internal const int MaxSize = 2;
33         internal const int IdMin = 2048;
34         internal const int IdMax = 3000;
35         internal const int DataMax = 15;
36
37         internal IntPtr _resourceOptionsHandle = IntPtr.Zero;
38         private readonly IDictionary<ushort, string> _options = new Dictionary<ushort, string>();
39         private bool _disposed = false;
40
41         /// <summary>
42         /// The resource options constructor
43         /// </summary>
44         /// <seealso cref="Add()"/>
45         /// <seealso cref="Remove()"/>
46         /// <exception cref="NotSupportedException">Thrown when the iotcon is not supported</exception>
47         /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory</exception>
48         /// <exception cref="ArgumentException">Thrown when there is an invalid parameter</exception>
49         /// <code>
50         /// ResourceOptions options = new ResourceOptions();
51         /// </code>
52         public ResourceOptions()
53         {
54             int ret = Interop.IoTConnectivity.Common.Options.Create(out _resourceOptionsHandle);
55             if (ret != (int)IoTConnectivityError.None)
56             {
57                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to create options");
58                 throw IoTConnectivityErrorFactory.GetException(ret);
59             }
60         }
61
62         // internal constructor
63         internal ResourceOptions(IntPtr handleToClone)
64         {
65             int ret = Interop.IoTConnectivity.Common.Options.Create(out _resourceOptionsHandle);
66             if (ret != (int)IoTConnectivityError.None)
67             {
68                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to create options");
69                 throw IoTConnectivityErrorFactory.GetException(ret);
70             }
71
72             Interop.IoTConnectivity.Common.Options.OptionsCallback forEachCallback = (ushort id, string value, IntPtr userData) =>
73             {
74                 Add(id, value);
75                 return true;
76             };
77
78             ret = Interop.IoTConnectivity.Common.Options.ForEach(handleToClone, forEachCallback, IntPtr.Zero);
79             if (ret != (int)IoTConnectivityError.None)
80             {
81                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to iterate options");
82                 throw IoTConnectivityErrorFactory.GetException(ret);
83             }
84         }
85
86         /// <summary>
87         /// Destructor of the ResourceOptions class.
88         /// </summary>
89         ~ResourceOptions()
90         {
91             Dispose(false);
92         }
93
94         /// <summary>
95         /// Contains all the Option keys
96         /// </summary>
97         /// <code>
98         /// ResourceOptions options = new ResourceOptions();
99         /// options.Add(2050, "sample-data");
100         /// options.Add(2055, "sample value");
101         /// var keys = options.Keys;
102         /// Console.WriteLine("Resource options contains keys {0} and {1}", keys.ElementAt(0), keys.ElementAt(1));
103         /// </code>
104         public ICollection<ushort> Keys
105         {
106             get
107             {
108                 return _options.Keys;
109             }
110         }
111
112         /// <summary>
113         /// Contains all the Option values
114         /// </summary>
115         /// <code>
116         /// ResourceOptions options = new ResourceOptions();
117         /// options.Add(2050, "sample-data");
118         /// options.Add(2055, "sample value");
119         /// var values = options.Values;
120         /// Console.WriteLine("Resource options contains values {0} and {1}", values.ElementAt(0), values.ElementAt(1));
121         /// </code>
122         public ICollection<string> Values
123         {
124             get
125             {
126                 return _options.Values;
127             }
128         }
129
130         /// <summary>
131         /// Gets the number of options
132         /// </summary>
133         /// <code>
134         /// ResourceOptions options = new ResourceOptions();
135         /// options.Add(2050, "sample-data");
136         /// options.Add(2055, "sample value");
137         /// var count = options.Count;
138         /// Console.WriteLine("There are {0} keys in the options object", count);
139         /// </code>
140         public int Count
141         {
142             get
143             {
144                 return _options.Count;
145             }
146         }
147
148         /// <summary>
149         /// Gets or sets the option data
150         /// </summary>
151         /// <remarks>
152         /// <param name="key">The option id to get or set.</param>
153         /// <returns>The option with the specified id.</returns>
154         /// <code>
155         /// ResourceOptions options = new ResourceOptions();
156         /// options[2055] = "sample-data";
157         /// Console.WriteLine("Option has : {0}", options[2055]);
158         /// </code>
159         public string this[ushort key]
160         {
161             get
162             {
163                 return _options[key];
164             }
165             set
166             {
167                 Add(key, value);
168             }
169         }
170
171         /// <summary>
172         /// Checks whether the given key exists in Options collection
173         /// </summary>
174         /// <param name="key">The key to look for</param>
175         /// <returns>true if exists. Otherwise, false</returns>
176         /// <code>
177         /// ResourceOptions options = new ResourceOptions();
178         /// options.Add(2050, "sample-data");
179         /// if (options.ContainsKey(2050))
180         ///     Console.WriteLine("options conatins key : 2050");
181         /// </code>
182         public bool ContainsKey(ushort key)
183         {
184             return _options.ContainsKey(key);
185         }
186
187         /// <summary>
188         /// Adds a new id and a correspoding data into the options.
189         /// </summary>
190         /// <remarks>
191         /// ResourceOptions can have up to 2 options. \n
192         /// key is always situated between 2048 and 3000. \n
193         /// Length of option data is less than or equal to 15.
194         /// </remarks>
195         /// <param name="key">The id of the option to insert</param>
196         /// <param name="value">The string data to insert into the options</param>
197         /// <seealso cref="Remove()"/>
198         /// <exception cref="NotSupportedException">Thrown when the iotcon is not supported</exception>
199         /// <exception cref="ArgumentException">Thrown when there is an invalid parameter</exception>
200         /// <code>
201         /// ResourceOptions options = new ResourceOptions();
202         /// options.Add(2050, "sample-data");
203         /// </code>
204         public void Add(ushort key, string value)
205         {
206             int ret = (int)IoTConnectivityError.InvalidParameter;
207             if (IsValid(key, value))
208             {
209                 ret = Interop.IoTConnectivity.Common.Options.Add(_resourceOptionsHandle, key, value);
210                 if (ret != (int)IoTConnectivityError.None)
211                 {
212                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add option");
213                     throw IoTConnectivityErrorFactory.GetException(ret);
214                 }
215                 _options.Add(key, value);
216             }
217             else
218             {
219                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Invalid options");
220                 throw IoTConnectivityErrorFactory.GetException((int)IoTConnectivityError.InvalidParameter);
221             }
222         }
223
224         /// <summary>
225         /// Removes the id and its associated data from the options.
226         /// </summary>
227         /// <param name="key">The id of the option to delete</param>
228         /// <returns>True if operation is successful. Otherwise, false</returns>
229         /// <seealso cref="Add()"/>
230         /// <exception cref="NotSupportedException">Thrown when the iotcon is not supported</exception>
231         /// <exception cref="ArgumentException">Thrown when there is an invalid parameter</exception>
232         /// <code>
233         /// ResourceOptions options = new ResourceOptions();
234         /// options.Add(2050, "12345");
235         /// var result = options.Remove(2050);
236         /// </code>
237         public bool Remove(ushort key)
238         {
239             bool isRemoved = _options.Remove(key);
240             if (isRemoved)
241             {
242                 int ret = Interop.IoTConnectivity.Common.Options.Remove(_resourceOptionsHandle, key);
243                 if (ret != (int)IoTConnectivityError.None)
244                 {
245                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to remove option");
246                     throw IoTConnectivityErrorFactory.GetException(ret);
247                 }
248             }
249             return isRemoved;
250         }
251
252         /// <summary>
253         /// Gets the value associated with the specified key.
254         /// </summary>
255         /// <param name="key">The option id</param>
256         /// <param name="value">Value corresponding to option id</param>
257         /// <returns>True if the key exists, false otherwise</returns>
258         /// <code>
259         /// ResourceOptions options = new ResourceOptions();
260         /// options.Add(2050, "12345");
261         /// string value;
262         /// var isPresent = options.TryGetValue(2050, out value);
263         /// if (isPresent)
264         ///     Console.WriteLine("value : {0}", value);
265         /// </code>
266         public bool TryGetValue(ushort key, out string value)
267         {
268             return _options.TryGetValue(key, out value);
269         }
270
271         /// <summary>
272         ///  Adds options key and value as a key value pair
273         /// </summary>
274         /// <param name="item">The key value pair</param>
275         /// <seealso cref="Remove()"/>
276         /// <code>
277         /// ResourceOptions options = new ResourceOptions();
278         /// options.Add(new KeyValuePair<ushort, string>(2050, "12345"));
279         /// </code>
280         public void Add(KeyValuePair<ushort, string> item)
281         {
282             Add(item.Key, item.Value);
283         }
284
285         /// <summary>
286         /// Clears the Options collection
287         /// </summary>
288         /// <exception cref="NotSupportedException">Thrown when the iotcon is not supported</exception>
289         /// <exception cref="ArgumentException">Thrown when there is an invalid parameter</exception>
290         /// <code>
291         /// ResourceOptions options = new ResourceOptions();
292         /// options.Add(2050, "12345");
293         /// options.Add(2055, "sample");
294         /// options.Clear();
295         /// </code>
296         public void Clear()
297         {
298             foreach (ushort key in Keys)
299             {
300                 int ret = Interop.IoTConnectivity.Common.Options.Remove(_resourceOptionsHandle, key);
301                 if (ret != (int)IoTConnectivityError.None)
302                 {
303                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to remove option");
304                     throw IoTConnectivityErrorFactory.GetException(ret);
305                 };
306             }
307             _options.Clear();
308         }
309
310         /// <summary>
311         /// Checks if the given option pair exists
312         /// </summary>
313         /// <param name="item">The key value pair</param>
314         /// <returns>True if exists. Otherwise, false</returns>
315         /// <code>
316         /// ResourceOptions options = new ResourceOptions();
317         /// options.Add(new KeyValuePair<ushort, string>(2050, "12345"));
318         /// var isPresent = options.Contains(new KeyValuePair<ushort, string>(2050, "12345"));
319         /// if (isPresent)
320         ///     Console.WriteLine("Key value pair is present");
321         /// </code>
322         public bool Contains(KeyValuePair<ushort, string> item)
323         {
324             return _options.Contains(item);
325         }
326
327         /// <summary>
328         /// Copies the elements of the options collection to an Array, starting at a particular index.
329         /// </summary>
330         /// <param name="array">The destination array</param>
331         /// <param name="arrayIndex">Index parameter</param>
332         /// <code>
333         /// ResourceOptions options = new ResourceOptions();
334         /// options.Add(new KeyValuePair<ushort, string>(2050, "12345"));
335         /// KeyValuePair<ushort, string>[] dest = new KeyValuePair<ushort, string>[options.Count];
336         /// options.CopyTo(dest, 0);
337         /// Console.WriteLine("Dest conatins ({0}, {1})", dest[0].Key, dest[0].Value);
338         /// </code>
339         public void CopyTo(KeyValuePair<ushort, string>[] array, int arrayIndex)
340         {
341             _options.CopyTo(array, arrayIndex);
342         }
343
344         /// <summary>
345         /// Remove the given key value pair from the options
346         /// </summary>
347         /// <param name="item">The key value pair to remove</param>
348         /// <returns>True if operation is successful. Otherwise, false</returns>
349         /// <seealso cref="Add()"/>
350         /// <code>
351         /// ResourceOptions options = new ResourceOptions();
352         /// options.Add(new KeyValuePair<ushort, string>(2050, "12345"));
353         /// var result = options.Remove(new KeyValuePair<ushort, string>(2050, "12345"));
354         /// </code>
355         public bool Remove(KeyValuePair<ushort, string> item)
356         {
357             return Remove(item.Key);
358         }
359
360         /// <summary>
361         /// Get the enumerator to options collection
362         /// </summary>
363         /// <returns>Enumerator to option pairs</returns>
364         /// <code>
365         /// ResourceOptions options = new ResourceOptions();
366         /// options.Add(new KeyValuePair<ushort, string>(2050, "sample1"));
367         /// options.Add(new KeyValuePair<ushort, string>(2055, "sample2"));
368         /// foreach (KeyValuePair<string, object> pair in options)
369         /// {
370         ///     Console.WriteLine("key : {0}, value : {1}", pair.Key, pair.Value);
371         /// }
372         /// </code>
373         public IEnumerator<KeyValuePair<ushort, string>> GetEnumerator()
374         {
375             return _options.GetEnumerator();
376         }
377
378         /// <summary>
379         /// Releases any unmanaged resources used by this object.
380         /// </summary>
381         public void Dispose()
382         {
383             Dispose(true);
384             GC.SuppressFinalize(this);
385         }
386
387         /// <summary>
388         /// Get the enumerator to options collection
389         /// </summary>
390         /// <returns>Enumerator to option pairs</returns>
391         /// <code>
392         /// ResourceOptions options = new ResourceOptions();
393         /// options.Add(new KeyValuePair<ushort, string>(2050, "sample1"));
394         /// options.Add(new KeyValuePair<ushort, string>(2055, "sample2"));
395         /// foreach (KeyValuePair<string, object> pair in options)
396         /// {
397         ///     Console.WriteLine("key : {0}, value : {1}", pair.Key, pair.Value);
398         /// }
399         /// </code>
400         IEnumerator IEnumerable.GetEnumerator()
401         {
402             return _options.GetEnumerator();
403         }
404
405         /// <summary>
406         /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects.
407         /// </summary>
408         /// <param name="disposing">If true, disposes any disposable objects. If false, does not dispose disposable objects.</param>
409         protected virtual void Dispose(bool disposing)
410         {
411             if (_disposed)
412                 return;
413
414             if (disposing)
415             {
416                 // Free managed objects
417             }
418
419             Interop.IoTConnectivity.Common.Options.Destroy(_resourceOptionsHandle);
420             _disposed = true;
421         }
422
423         private bool IsValid(ushort key, string value)
424         {
425             return (key > IdMin && key < IdMax && value.Length <= DataMax && _options.Count() < MaxSize);
426         }
427     }
428 }