using System;
using System.Collections.Generic;
using System.Globalization;
using mustache.Properties;
namespace mustache
{
///
/// Represents a scope of keys.
///
public sealed class KeyScope
{
private readonly object _source;
private readonly KeyScope _parent;
///
/// Initializes a new instance of a KeyScope.
///
/// The object to search for keys in.
internal KeyScope(object source)
: this(source, null)
{
}
///
/// Initializes a new instance of a KeyScope.
///
/// The object to search for keys in.
/// The parent scope to search in if the value is not found.
internal KeyScope(object source, KeyScope parent)
{
_parent = parent;
_source = source;
}
///
/// Creates a child scope that searches for keys in the given object.
///
/// The object to search for keys in.
/// The new child scope.
public KeyScope CreateChildScope(object source)
{
KeyScope scope = new KeyScope(source, this);
return scope;
}
///
/// Attempts to find the value associated with the key with given name.
///
/// The name of the key.
/// The value associated with the key with the given name.
/// A key with the given name could not be found.
internal object Find(string name)
{
string[] names = name.Split('.');
string member = names[0];
object nextLevel = _source;
if (member != "this")
{
nextLevel = find(member);
}
for (int index = 1; index < names.Length; ++index)
{
IDictionary context = toLookup(nextLevel);
member = names[index];
nextLevel = context[member];
}
return nextLevel;
}
private object find(string name)
{
IDictionary lookup = toLookup(_source);
if (lookup.ContainsKey(name))
{
return lookup[name];
}
if (_parent == null)
{
string message = String.Format(CultureInfo.CurrentCulture, Resources.KeyNotFound, name);
throw new KeyNotFoundException(message);
}
return _parent.find(name);
}
private static IDictionary toLookup(object value)
{
IDictionary lookup = value as IDictionary;
if (lookup == null)
{
lookup = new PropertyDictionary(value);
}
return lookup;
}
}
}