Update content of nuspec file
[platform/core/csapi/tizenfx.git] / src / Tizen.Network.IoTConnectivity / Tizen.Network.IoTConnectivity / ResourceQuery.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.Runtime.InteropServices;
22
23 namespace Tizen.Network.IoTConnectivity
24 {
25     /// <summary>
26     /// This class provides APIs to manage query of request.
27     /// </summary>
28     public class ResourceQuery : IDictionary<string, string>, IDisposable
29     {
30         internal const int QueryMaxLenth = 64;
31         internal IntPtr _resourceQueryHandle = IntPtr.Zero;
32         private readonly IDictionary<string, string> _query = new Dictionary<string, string>();
33         private bool _disposed = false;
34
35         /// <summary>
36         /// The resource query constructor
37         /// </summary>
38         /// <seealso cref="Add()"/>
39         /// <seealso cref="Remove()"/>
40         /// <code>
41         /// ResourceQuery query = new ResourceQuery();
42         /// </code>
43         public ResourceQuery()
44         {
45             int ret = Interop.IoTConnectivity.Common.Query.Create(out _resourceQueryHandle);
46             if (ret != (int)IoTConnectivityError.None)
47             {
48                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to create query");
49                 throw IoTConnectivityErrorFactory.GetException(ret);
50             }
51         }
52
53         internal ResourceQuery(IntPtr resourceQueryHandleToClone)
54         {
55             int ret = Interop.IoTConnectivity.Common.Query.Create(out _resourceQueryHandle);
56             if (ret != (int)IoTConnectivityError.None)
57             {
58                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to create query");
59                 throw IoTConnectivityErrorFactory.GetException(ret);
60             }
61
62             Interop.IoTConnectivity.Common.Query.QueryCallback forEachCallback = (string key, string value, IntPtr userData) =>
63             {
64                 Add(key, value);
65                 return true;
66             };
67
68             ret = Interop.IoTConnectivity.Common.Query.Foreach(resourceQueryHandleToClone, forEachCallback, IntPtr.Zero);
69             if (ret != (int)IoTConnectivityError.None)
70             {
71                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to iterate query");
72                 throw IoTConnectivityErrorFactory.GetException(ret);
73             }
74         }
75
76         /// <summary>
77         /// Destructor of the ResourceQuery class.
78         /// </summary>
79         ~ResourceQuery()
80         {
81             Dispose(false);
82         }
83
84         /// <summary>
85         /// Gets and sets the resource type of the query
86         /// </summary>
87         /// <code>
88         /// ResourceQuery query = new ResourceQuery();
89         /// query.Type = "org.tizen.light";
90         /// Console.WriteLine("Type of query : {0}", query.Type);
91         /// </code>
92         public string Type
93         {
94             get
95             {
96                 IntPtr type;
97                 int ret = Interop.IoTConnectivity.Common.Query.GetResourceType(_resourceQueryHandle, out type);
98                 if (ret != (int)IoTConnectivityError.None)
99                 {
100                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get type");
101                     throw IoTConnectivityErrorFactory.GetException(ret);
102                 }
103                 return Marshal.PtrToStringAnsi(type);
104             }
105             set
106             {
107                 int ret = (int)IoTConnectivityError.InvalidParameter;
108                 if (ResourceTypes.IsValid(value))
109                     ret = Interop.IoTConnectivity.Common.Query.SetResourceType(_resourceQueryHandle, value);
110
111                 if (ret != (int)IoTConnectivityError.None)
112                 {
113                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to set type");
114                     throw IoTConnectivityErrorFactory.GetException(ret);
115                 }
116             }
117         }
118
119         /// <summary>
120         /// Gets and sets the resource interface of the query
121         /// </summary>
122         /// <remarks>
123         /// Setter value could be a value such as <see cref="ResourceInterfaces.DefaultInterface"/>
124         /// </remarks>
125         /// <code>
126         /// ResourceQuery query = new ResourceQuery();
127         /// query.Interface = ResourceInterfaces.LinkInterface;
128         /// </code>
129         public string Interface
130         {
131             get
132             {
133                 IntPtr iface;
134                 int ret = Interop.IoTConnectivity.Common.Query.GetInterface(_resourceQueryHandle, out iface);
135                 if (ret != (int)IoTConnectivityError.None)
136                 {
137                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get interface");
138                     throw IoTConnectivityErrorFactory.GetException(ret);
139                 }
140                 return Marshal.PtrToStringAnsi(iface);
141             }
142             set
143             {
144                 int ret = (int)IoTConnectivityError.InvalidParameter;
145                 if (ResourceInterfaces.IsValid(value))
146                     ret = Interop.IoTConnectivity.Common.Query.SetInterface(_resourceQueryHandle, value);
147
148                 if (ret != (int)IoTConnectivityError.None)
149                 {
150                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to set interface");
151                     throw IoTConnectivityErrorFactory.GetException(ret);
152                 }
153             }
154         }
155
156         /// <summary>
157         /// Contains all the query keys
158         /// </summary>
159         /// <code>
160         /// ResourceQuery query = new ResourceQuery();
161         /// query.Add("key", "value");
162         /// query.Add("newKey", "sample value");
163         /// var keys = query.Keys;
164         /// Console.WriteLine("Resource query contains keys {0} and {1}", keys.ElementAt(0), keys.ElementAt(1));
165         /// </code>
166         public ICollection<string> Keys
167         {
168             get
169             {
170                 return _query.Keys;
171             }
172         }
173
174         /// <summary>
175         /// Contains all the query values
176         /// </summary>
177         /// <code>
178         /// ResourceQuery query = new ResourceQuery();
179         /// query.Add("key", "value");
180         /// query.Add("newKey", "sample value");
181         /// var values = query.Values;
182         /// Console.WriteLine("Resource query contains values {0} and {1}", values.ElementAt(0), values.ElementAt(1));
183         /// </code>
184         public ICollection<string> Values
185         {
186             get
187             {
188                 return _query.Values;
189             }
190         }
191
192         /// <summary>
193         /// Gets the number of query elements
194         /// </summary>
195         /// <code>
196         /// ResourceQuery query = new ResourceQuery();
197         /// query.Add("key", "value");
198         /// query.Add("newKey", "sample value");
199         /// var count = query.Count;
200         /// Console.WriteLine("There are {0} keys in the query object", count);
201         /// </code>
202         public int Count
203         {
204             get
205             {
206                 return _query.Count;
207             }
208         }
209
210         /// <summary>
211         /// Represents whether the collection is readonly
212         /// </summary>
213         /// <code>
214         /// ResourceQuery query = new ResourceQuery();
215         /// if (query.IsReadOnly)
216         ///     Console.WriteLine("Read only query");
217         /// </code>
218         public bool IsReadOnly
219         {
220             get
221             {
222                 return _query.IsReadOnly;
223             }
224         }
225
226         /// <summary>
227         /// Gets or sets the query data
228         /// </summary>
229         /// <param name="key">The query key to get or set.</param>
230         /// <returns>The query with the specified key.</returns>
231         /// <code>
232         /// ResourceQuery query = new ResourceQuery();
233         /// query["key1"] = "sample-data";
234         /// Console.WriteLine("query has : {0}", query["key1"]);
235         /// </code>
236         public string this[string key]
237         {
238             get
239             {
240                 return _query[key];
241             }
242
243             set
244             {
245                 Add(key, value);
246             }
247         }
248
249         /// <summary>
250         /// Checks whether the given key exists in Query collection
251         /// </summary>
252         /// <param name="key">The key to look for</param>
253         /// <returns>true if exists. Otherwise, false</returns>
254         /// <code>
255         /// ResourceQuery query = new ResourceQuery();
256         /// query.Add("key1", "value1");
257         /// if (query.ContainsKey("key1"))
258         ///     Console.WriteLine("query conatins key : key1");
259         /// </code>
260         public bool ContainsKey(string key)
261         {
262             return _query.ContainsKey(key);
263         }
264
265         /// <summary>
266         /// Adds a new key and correspoding value into the query.
267         /// </summary>
268         /// <remarks>
269         /// The full length of query should be less than or equal to 64.
270         /// </remarks>
271         /// <param name="key">The key of the query to insert</param>
272         /// <param name="value">The string data to insert into the query</param>
273         /// <seealso cref="Remove()"/>
274         /// <code>
275         /// ResourceQuery query = new ResourceQuery();
276         /// query.Add("key1", "value1");
277         /// </code>
278         public void Add(string key, string value)
279         {
280             if (CanAddQuery(key, value))
281             {
282                 int ret = Interop.IoTConnectivity.Common.Query.Add(_resourceQueryHandle, key, value);
283                 if (ret != (int)IoTConnectivityError.None)
284                 {
285                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add query");
286                     throw IoTConnectivityErrorFactory.GetException(ret);
287                 }
288                 _query.Add(key, value);
289             }
290             else
291             {
292                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Query cannot be added");
293                 throw IoTConnectivityErrorFactory.GetException((int)IoTConnectivityError.InvalidParameter);
294             }
295         }
296
297         /// <summary>
298         /// Removes the key and its associated value from the query.
299         /// </summary>
300         /// <param name="key">The id of the query to delete</param>
301         /// <returns>True if operation is successful. Otherwise, false</returns>
302         /// <seealso cref="Add()"/>
303         /// <code>
304         /// ResourceQuery query = new ResourceQuery();
305         /// query.Add("key1", "value1");
306         /// var result = query.Remove("key1");
307         /// </code>
308         public bool Remove(string key)
309         {
310             bool isRemoved = _query.Remove(key);
311             if (isRemoved)
312             {
313                 int ret = Interop.IoTConnectivity.Common.Query.Remove(_resourceQueryHandle, key);
314                 if (ret != (int)IoTConnectivityError.None)
315                 {
316                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to remove query");
317                     throw IoTConnectivityErrorFactory.GetException(ret);
318                 }
319             }
320             return isRemoved;
321         }
322
323         /// <summary>
324         /// Gets the value associated with the specified key.
325         /// </summary>
326         /// <param name="key">The query key</param>
327         /// <param name="value">Value corresponding to query key</param>
328         /// <returns>True if the key exists, false otherwise</returns>
329         /// <code>
330         /// ResourceQuery query = new ResourceQuery();
331         /// query.Add("key1", "value1");
332         /// string value;
333         /// var isPresent = query.TryGetValue("key1", out value);
334         /// if (isPresent)
335         ///     Console.WriteLine("value : {0}", value);
336         /// </code>
337         public bool TryGetValue(string key, out string value)
338         {
339             return _query.TryGetValue(key, out value);
340         }
341
342         /// <summary>
343         ///  Adds query key and value as a key value pair
344         /// </summary>
345         /// <param name="item">The key value pair</param>
346         /// <seealso cref="Remove()"/>
347         /// <code>
348         /// ResourceQuery query = new ResourceQuery();
349         /// query.Add(new KeyValuePair<string, string>("key1", "value1"));
350         /// </code>
351         public void Add(KeyValuePair<string, string> item)
352         {
353             Add(item.Key, item.Value);
354         }
355
356         /// <summary>
357         /// Clears the Query collection
358         /// </summary>
359         /// <code>
360         /// ResourceQuery query = new ResourceQuery();
361         /// query.Add("key1", "value1");
362         /// query.Add("key2", "value2");
363         /// query.Clear();
364         /// </code>
365         public void Clear()
366         {
367             foreach (string key in _query.Keys)
368             {
369                 int ret = Interop.IoTConnectivity.Common.Query.Remove(_resourceQueryHandle, key);
370                 if (ret != (int)IoTConnectivityError.None)
371                 {
372                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to clear query");
373                     throw IoTConnectivityErrorFactory.GetException(ret);
374                 }
375             }
376             _query.Clear();
377         }
378
379         /// <summary>
380         /// Checks if the given query pair exists
381         /// </summary>
382         /// <param name="item">The key value pair</param>
383         /// <returns>True if exists. Otherwise, false</returns>
384         /// <code>
385         /// ResourceQuery query = new ResourceQuery();
386         /// query.Add(new KeyValuePair<string, string>("key1", "value1"));
387         /// var isPresent = query.Contains(new KeyValuePair<string, string>("key1", "value1"));
388         /// if (isPresent)
389         ///     Console.WriteLine("Key value pair is present");
390         /// </code>
391         public bool Contains(KeyValuePair<string, string> item)
392         {
393             return _query.Contains(item);
394         }
395
396         /// <summary>
397         /// Copies the elements of the query collection to an Array, starting at a particular index.
398         /// </summary>
399         /// <param name="array">The destination array</param>
400         /// <param name="arrayIndex">Index parameter</param>
401         /// <code>
402         /// ResourceQuery query = new ResourceQuery();
403         /// query.Add(new KeyValuePair<string, string>("key1", "value1"));
404         /// KeyValuePair<string, string>[] dest = new KeyValuePair<string, string>[query.Count];
405         /// query.CopyTo(dest, 0);
406         /// Console.WriteLine("Dest conatins ({0}, {1})", dest[0].Key, dest[0].Value);
407         /// </code>
408         public void CopyTo(KeyValuePair<string, string>[] array, int arrayIndex)
409         {
410             _query.CopyTo(array, arrayIndex);
411         }
412
413         /// <summary>
414         /// Remove the given key value pair from the query
415         /// </summary>
416         /// <param name="item">The key value pair to remove</param>
417         /// <returns>True if operation is successful. Otherwise, false</returns>
418         /// <seealso cref="Add()"/>
419         /// <code>
420         /// ResourceQuery query = new ResourceQuery();
421         /// query.Add(new KeyValuePair<string, string>("key1", "value1"));
422         /// var result = query.Remove(new KeyValuePair<string, string>("key1", "value1"));
423         /// </code>
424         public bool Remove(KeyValuePair<string, string> item)
425         {
426             return Remove(item.Key);
427         }
428
429         /// <summary>
430         /// Get the enumerator to query collection
431         /// </summary>
432         /// <returns>Enumerator to query pairs</returns>
433         /// <code>
434         /// ResourceQuery query = new ResourceQuery();
435         /// query.Add(new KeyValuePair<string, string>("key1", "value1"));
436         /// query.Add(new KeyValuePair<string, string>("key2", "value2"));
437         /// foreach (KeyValuePair<string, string> pair in query)
438         /// {
439         ///     Console.WriteLine("key : {0}, value : {1}", pair.Key, pair.Value);
440         /// }
441         /// </code>
442         public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
443         {
444             return _query.GetEnumerator();
445         }
446
447         /// <summary>
448         /// Get the enumerator to query collection
449         /// </summary>
450         /// <returns>Enumerator to query pairs</returns>
451         /// <code>
452         /// ResourceQuery query = new ResourceQuery();
453         /// query.Add(new KeyValuePair<string, string>("key1", "value1"));
454         /// query.Add(new KeyValuePair<string, string>("key2", "value2"));
455         /// foreach (KeyValuePair<string, string> pair in query)
456         /// {
457         ///     Console.WriteLine("key : {0}, value : {1}", pair.Key, pair.Value);
458         /// }
459         /// </code>
460         IEnumerator IEnumerable.GetEnumerator()
461         {
462             return _query.GetEnumerator();
463         }
464
465         /// <summary>
466         /// Releases any unmanaged resources used by this object.
467         /// </summary>
468         public void Dispose()
469         {
470             Dispose(true);
471             GC.SuppressFinalize(this);
472         }
473
474         /// <summary>
475         /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects.
476         /// </summary>
477         /// <param name="disposing">If true, disposes any disposable objects. If false, does not dispose disposable objects.</param>
478         protected virtual void Dispose(bool disposing)
479         {
480             if (_disposed)
481                 return;
482
483             if (disposing)
484             {
485                 // Free managed objects
486             }
487
488             Interop.IoTConnectivity.Common.Query.Destroy(_resourceQueryHandle);
489             _disposed = true;
490         }
491
492         private bool CanAddQuery(string newKey, string newValue)
493         {
494             int queryLenth = 0;
495             foreach (string key in Keys)
496             {
497                 queryLenth += key.Length + 2;
498             }
499             foreach (string value in Values)
500             {
501                 queryLenth += value.Length;
502             }
503
504             if ((newKey.Length + newValue.Length + queryLenth + 2) < QueryMaxLenth)
505                 return true;
506
507             return false;
508         }
509     }
510 }