/*
* 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.
/// The iotcon options API provides methods for managing vendor specific options of coap packet.
/// See more about coap packet in http://tools.ietf.org/html/rfc7252.
///
/// 3
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.
///
/// 3
/// http://tizen.org/feature/iot.ocf
///
///
/// Thrown when the iotcon is not supported.
/// Thrown when there is not enough memory.
///
/// 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.
///
/// 3
/// 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.
///
/// 3
/// 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.
///
/// 3
/// 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;
}
}
///
/// Represents whether the collection is readonly.
///
/// 3
/// Whether the collection is readonly.
///
/// ResourceOptions options = new ResourceOptions();
/// if (options.IsReadOnly)
/// Console.WriteLine("Read only options");
///
public bool IsReadOnly
{
get
{
return _options.IsReadOnly;
}
}
///
/// Gets or sets the option data.
///
/// 3
/// 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.
///
/// 3
/// 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.
///
/// 3
///
/// ResourceOptions can have up to 2 options.
/// key is always situated between 2048 and 3000.
/// 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.
/// http://tizen.org/feature/iot.ocf
///
/// 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.
///
/// 3
/// The ID of the option to delete.
/// True if operation is successful. Otherwise, false.
/// http://tizen.org/feature/iot.ocf
///
/// 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)
{
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);
}
bool isRemoved = _options.Remove(key);
return isRemoved;
}
///
/// Gets the value associated with the specified key.
///
/// 3
/// 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.
///
/// 3
/// The key value pair.
/// http://tizen.org/feature/iot.ocf
///
/// (2050, "12345"));
/// ]]>
public void Add(KeyValuePair item)
{
Add(item.Key, item.Value);
}
///
/// Clears the Options collection.
///
/// 3
/// http://tizen.org/feature/iot.ocf
/// Thrown when the iotcon is not supported.
///
/// 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.
///
/// 3
/// The key value pair.
/// True if exists. Otherwise, false.
/// (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.
///
/// 3
/// The destination array.
/// Index parameter.
/// (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);
}
///
/// Removes the given key value pair from the options.
///
/// 3
/// The key value pair to remove
/// True if operation is successful. Otherwise, false
/// http://tizen.org/feature/iot.ocf
///
/// Thrown when there is an invalid parameter
/// (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.
///
/// 3
/// Enumerator to option pairs.
/// (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.
///
/// 3
/// http://tizen.org/feature/iot.ocf
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Gets the enumerator to options collection.
///
/// 3
/// Enumerator to option pairs.
/// (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.
///
/// 3
/// If true, disposes any disposable objects. If false, does not dispose disposable objects.
/// http://tizen.org/feature/iot.ocf
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);
}
}
}