/* * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections; using System.Collections.Generic; using System.Linq; namespace Tizen.Network.IoTConnectivity { /// /// This class represents resource options. It provides APIs to manage them.\n /// The iotcon options API provides methods for managing vendor specific options of coap packet.\n /// See more about coap packet in http://tools.ietf.org/html/rfc7252. /// public class ResourceOptions : IDictionary, IDisposable { internal const int MaxSize = 2; internal const int IdMin = 2048; internal const int IdMax = 3000; internal const int DataMax = 15; internal IntPtr _resourceOptionsHandle = IntPtr.Zero; private readonly IDictionary _options = new Dictionary(); private bool _disposed = false; /// /// The resource options constructor /// /// /// /// Thrown when the iotcon is not supported /// Thrown when there is not enough memory /// Thrown when there is an invalid parameter /// /// ResourceOptions options = new ResourceOptions(); /// public ResourceOptions() { int ret = Interop.IoTConnectivity.Common.Options.Create(out _resourceOptionsHandle); if (ret != (int)IoTConnectivityError.None) { Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to create options"); throw IoTConnectivityErrorFactory.GetException(ret); } } // internal constructor internal ResourceOptions(IntPtr handleToClone) { int ret = Interop.IoTConnectivity.Common.Options.Create(out _resourceOptionsHandle); if (ret != (int)IoTConnectivityError.None) { Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to create options"); throw IoTConnectivityErrorFactory.GetException(ret); } Interop.IoTConnectivity.Common.Options.OptionsCallback forEachCallback = (ushort id, string value, IntPtr userData) => { Add(id, value); return true; }; ret = Interop.IoTConnectivity.Common.Options.ForEach(handleToClone, forEachCallback, IntPtr.Zero); if (ret != (int)IoTConnectivityError.None) { Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to iterate options"); throw IoTConnectivityErrorFactory.GetException(ret); } } /// /// Destructor of the ResourceOptions class. /// ~ResourceOptions() { Dispose(false); } /// /// Contains all the Option keys /// /// /// ResourceOptions options = new ResourceOptions(); /// options.Add(2050, "sample-data"); /// options.Add(2055, "sample value"); /// var keys = options.Keys; /// Console.WriteLine("Resource options contains keys {0} and {1}", keys.ElementAt(0), keys.ElementAt(1)); /// public ICollection Keys { get { return _options.Keys; } } /// /// Contains all the Option values /// /// /// ResourceOptions options = new ResourceOptions(); /// options.Add(2050, "sample-data"); /// options.Add(2055, "sample value"); /// var values = options.Values; /// Console.WriteLine("Resource options contains values {0} and {1}", values.ElementAt(0), values.ElementAt(1)); /// public ICollection Values { get { return _options.Values; } } /// /// Gets the number of options /// /// /// ResourceOptions options = new ResourceOptions(); /// options.Add(2050, "sample-data"); /// options.Add(2055, "sample value"); /// var count = options.Count; /// Console.WriteLine("There are {0} keys in the options object", count); /// public int Count { get { return _options.Count; } } /// /// Gets or sets the option data /// /// /// The option id to get or set. /// The option with the specified id. /// /// ResourceOptions options = new ResourceOptions(); /// options[2055] = "sample-data"; /// Console.WriteLine("Option has : {0}", options[2055]); /// public string this[ushort key] { get { return _options[key]; } set { Add(key, value); } } /// /// Checks whether the given key exists in Options collection /// /// The key to look for /// true if exists. Otherwise, false /// /// ResourceOptions options = new ResourceOptions(); /// options.Add(2050, "sample-data"); /// if (options.ContainsKey(2050)) /// Console.WriteLine("options conatins key : 2050"); /// public bool ContainsKey(ushort key) { return _options.ContainsKey(key); } /// /// Adds a new id and a correspoding data into the options. /// /// /// ResourceOptions can have up to 2 options. \n /// key is always situated between 2048 and 3000. \n /// Length of option data is less than or equal to 15. /// /// The id of the option to insert /// The string data to insert into the options /// /// Thrown when the iotcon is not supported /// Thrown when there is an invalid parameter /// /// ResourceOptions options = new ResourceOptions(); /// options.Add(2050, "sample-data"); /// public void Add(ushort key, string value) { int ret = (int)IoTConnectivityError.InvalidParameter; if (IsValid(key, value)) { ret = Interop.IoTConnectivity.Common.Options.Add(_resourceOptionsHandle, key, value); if (ret != (int)IoTConnectivityError.None) { Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add option"); throw IoTConnectivityErrorFactory.GetException(ret); } _options.Add(key, value); } else { Log.Error(IoTConnectivityErrorFactory.LogTag, "Invalid options"); throw IoTConnectivityErrorFactory.GetException((int)IoTConnectivityError.InvalidParameter); } } /// /// Removes the id and its associated data from the options. /// /// The id of the option to delete /// True if operation is successful. Otherwise, false /// /// Thrown when the iotcon is not supported /// Thrown when there is an invalid parameter /// /// ResourceOptions options = new ResourceOptions(); /// options.Add(2050, "12345"); /// var result = options.Remove(2050); /// public bool Remove(ushort key) { bool isRemoved = _options.Remove(key); if (isRemoved) { int ret = Interop.IoTConnectivity.Common.Options.Remove(_resourceOptionsHandle, key); if (ret != (int)IoTConnectivityError.None) { Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to remove option"); throw IoTConnectivityErrorFactory.GetException(ret); } } return isRemoved; } /// /// Gets the value associated with the specified key. /// /// The option id /// Value corresponding to option id /// True if the key exists, false otherwise /// /// ResourceOptions options = new ResourceOptions(); /// options.Add(2050, "12345"); /// string value; /// var isPresent = options.TryGetValue(2050, out value); /// if (isPresent) /// Console.WriteLine("value : {0}", value); /// public bool TryGetValue(ushort key, out string value) { return _options.TryGetValue(key, out value); } /// /// Adds options key and value as a key value pair /// /// The key value pair /// /// /// ResourceOptions options = new ResourceOptions(); /// options.Add(new KeyValuePair(2050, "12345")); /// public void Add(KeyValuePair item) { Add(item.Key, item.Value); } /// /// Clears the Options collection /// /// Thrown when the iotcon is not supported /// Thrown when there is an invalid parameter /// /// ResourceOptions options = new ResourceOptions(); /// options.Add(2050, "12345"); /// options.Add(2055, "sample"); /// options.Clear(); /// public void Clear() { foreach (ushort key in Keys) { int ret = Interop.IoTConnectivity.Common.Options.Remove(_resourceOptionsHandle, key); if (ret != (int)IoTConnectivityError.None) { Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to remove option"); throw IoTConnectivityErrorFactory.GetException(ret); }; } _options.Clear(); } /// /// Checks if the given option pair exists /// /// The key value pair /// True if exists. Otherwise, false /// /// ResourceOptions options = new ResourceOptions(); /// options.Add(new KeyValuePair(2050, "12345")); /// var isPresent = options.Contains(new KeyValuePair(2050, "12345")); /// if (isPresent) /// Console.WriteLine("Key value pair is present"); /// public bool Contains(KeyValuePair item) { return _options.Contains(item); } /// /// Copies the elements of the options collection to an Array, starting at a particular index. /// /// The destination array /// Index parameter /// /// ResourceOptions options = new ResourceOptions(); /// options.Add(new KeyValuePair(2050, "12345")); /// KeyValuePair[] dest = new KeyValuePair[options.Count]; /// options.CopyTo(dest, 0); /// Console.WriteLine("Dest conatins ({0}, {1})", dest[0].Key, dest[0].Value); /// public void CopyTo(KeyValuePair[] array, int arrayIndex) { _options.CopyTo(array, arrayIndex); } /// /// Remove the given key value pair from the options /// /// The key value pair to remove /// True if operation is successful. Otherwise, false /// /// /// ResourceOptions options = new ResourceOptions(); /// options.Add(new KeyValuePair(2050, "12345")); /// var result = options.Remove(new KeyValuePair(2050, "12345")); /// public bool Remove(KeyValuePair item) { return Remove(item.Key); } /// /// Get the enumerator to options collection /// /// Enumerator to option pairs /// /// ResourceOptions options = new ResourceOptions(); /// options.Add(new KeyValuePair(2050, "sample1")); /// options.Add(new KeyValuePair(2055, "sample2")); /// foreach (KeyValuePair pair in options) /// { /// Console.WriteLine("key : {0}, value : {1}", pair.Key, pair.Value); /// } /// public IEnumerator> GetEnumerator() { return _options.GetEnumerator(); } /// /// Releases any unmanaged resources used by this object. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Get the enumerator to options collection /// /// Enumerator to option pairs /// /// ResourceOptions options = new ResourceOptions(); /// options.Add(new KeyValuePair(2050, "sample1")); /// options.Add(new KeyValuePair(2055, "sample2")); /// foreach (KeyValuePair pair in options) /// { /// Console.WriteLine("key : {0}, value : {1}", pair.Key, pair.Value); /// } /// IEnumerator IEnumerable.GetEnumerator() { return _options.GetEnumerator(); } /// /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects. /// /// If true, disposes any disposable objects. If false, does not dispose disposable objects. protected virtual void Dispose(bool disposing) { if (_disposed) return; if (disposing) { // Free managed objects } Interop.IoTConnectivity.Common.Options.Destroy(_resourceOptionsHandle); _disposed = true; } private bool IsValid(ushort key, string value) { return (key > IdMin && key < IdMax && value.Length <= DataMax && _options.Count() < MaxSize); } } }