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