namespace UglyToad.PdfPig.Tokens
{
using System;
using System.Collections.Generic;
using System.Linq;
///
/// A dictionary object is an associative table containing pairs of objects, known as the dictionary's entries.
/// The key must be a and the value may be an kind of .
///
public class DictionaryToken : IDataToken>, IEquatable
{
///
/// The key value pairs in this dictionary.
///
public IReadOnlyDictionary Data { get; }
///
/// Create a new .
///
/// The data this dictionary will contain.
public DictionaryToken(IReadOnlyDictionary data)
{
if (data == null)
{
throw new ArgumentNullException(nameof(data));
}
var result = new Dictionary(data.Count);
foreach (var keyValuePair in data)
{
result[keyValuePair.Key.Data] = keyValuePair.Value;
}
Data = result;
}
private DictionaryToken(IReadOnlyDictionary data)
{
Data = data;
}
///
/// Try and get the entry with a given name.
///
/// The name of the entry to retrieve.
/// The token, if it is found.
/// if the token is found, otherwise.
public bool TryGet(NameToken name, out IToken token)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
return Data.TryGetValue(name.Data, out token);
}
///
/// Try and get the entry with a given name and a specific data type.
///
/// The expected data type of the dictionary value.
/// The name of the entry to retrieve.
/// The token, if it is found.
/// if the token is found with this type, otherwise.
public bool TryGet(NameToken name, out T token) where T : IToken
{
token = default(T);
if (!TryGet(name, out var t) || !(t is T typedToken))
{
return false;
}
token = typedToken;
return true;
}
///
/// Whether the dictionary contains an entry with this name.
///
/// The name to check.
/// if the token is found, otherwise.
public bool ContainsKey(NameToken name)
{
return Data.ContainsKey(name.Data);
}
///
/// Create a copy of this dictionary with the additional entry (or override the value of the existing entry).
///
/// The key of the entry to create or override.
/// The value of the entry to create or override.
/// A new with the entry created or modified.
public DictionaryToken With(NameToken key, IToken value) => With(key.Data, value);
///
/// Create a copy of this dictionary with the additional entry (or override the value of the existing entry).
///
/// The key of the entry to create or override.
/// The value of the entry to create or override.
/// A new with the entry created or modified.
public DictionaryToken With(string key, IToken value)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
var result = new Dictionary(Data.Count + 1);
foreach (var keyValuePair in Data)
{
result[keyValuePair.Key] = keyValuePair.Value;
}
result[key] = value;
return new DictionaryToken(result);
}
///
/// Creates a copy of this dictionary with the entry with the specified key removed (if it exists).
///
/// The key of the entry to remove.
/// A new with the entry removed.
public DictionaryToken Without(NameToken key) => Without(key.Data);
///
/// Creates a copy of this dictionary with the entry with the specified key removed (if it exists).
///
/// The key of the entry to remove.
/// A new with the entry removed.
public DictionaryToken Without(string key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
var result = new Dictionary(Data.ContainsKey(key) ? Data.Count - 1 : Data.Count);
foreach (var keyValuePair in Data.Where(x => !x.Key.Equals(key)))
{
result[keyValuePair.Key] = keyValuePair.Value;
}
return new DictionaryToken(result);
}
///
/// Create a new .
///
/// The data this dictionary will contain.
public static DictionaryToken With(IReadOnlyDictionary data)
{
return new DictionaryToken(data ?? throw new ArgumentNullException(nameof(data)));
}
///
public bool Equals(IToken obj)
{
return Equals(obj as DictionaryToken);
}
///
public bool Equals(DictionaryToken other)
{
if (other == null)
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
if (Data.Count != other.Data.Count)
{
return false;
}
foreach (var kvp in other.Data)
{
if (!Data.TryGetValue(kvp.Key, out var val) || !val.Equals(kvp.Value))
{
return false;
}
}
return true;
}
///
public override string ToString()
{
return string.Join(", ", Data.Select(x => $"<{x.Key}, {x.Value}>"));
}
}
}