nancyfx.parameters.mustache Maven / Gradle / Ivy
The newest version!
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Nancy;
using NodaTime;
using NodaTime.Text;
using Sharpility.Base;
using Sharpility.Extensions;
using Sharpility.Util;
namespace {{packageName}}.{{packageContext}}.Utils
{
internal static class Parameters
{
private static readonly IDictionary> Parsers = CreateParsers();
internal static TValue ValueOf(dynamic parameters, Request request, string name, ParameterType parameterType)
{
var valueType = typeof(TValue);
var valueUnderlyingType = Nullable.GetUnderlyingType(valueType);
var isNullable = default(TValue) == null;
string value = RawValueOf(parameters, request, name, parameterType);
Preconditions.Evaluate(!string.IsNullOrEmpty(value) || isNullable, string.Format("Required parameter: '{0}' is missing", name));
if (value == null && isNullable)
{
return default(TValue);
}
if (valueType.IsEnum || (valueUnderlyingType != null && valueUnderlyingType.IsEnum))
{
return EnumValueOf(name, value);
}
return ValueOf(parameters, name, value, valueType, request, parameterType);
}
private static string RawValueOf(dynamic parameters, Request request, string name, ParameterType parameterType)
{
try
{
switch (parameterType)
{
case ParameterType.Query:
string querValue = request.Query[name];
return querValue;
case ParameterType.Path:
string pathValue = parameters[name];
return pathValue;
case ParameterType.Header:
var headerValue = request.Headers[name];
return headerValue != null ? string.Join(",", headerValue) : null;
}
}
catch (Exception e)
{
throw new InvalidOperationException(string.Format("Could not obtain value of '{0}' parameter", name), e);
}
throw new InvalidOperationException(string.Format("Parameter with type: {0} is not supported", parameterType));
}
private static TValue EnumValueOf(string name, string value)
{
var valueType = typeof(TValue);
var enumType = valueType.IsEnum ? valueType : Nullable.GetUnderlyingType(valueType);
Preconditions.IsNotNull(enumType, () => new InvalidOperationException(
string.Format("Could not parse parameter: '{0}' to enum. Type {1} is not enum", name, valueType)));
var values = Enum.GetValues(enumType);
foreach (var entry in values)
{
if (entry.ToString().EqualsIgnoreCases(value)
|| ((int)entry).ToString().EqualsIgnoreCases(value))
{
return (TValue)entry;
}
}
throw new ArgumentException(string.Format("Parameter: '{0}' value: '{1}' is not supported. Expected one of: {2}",
name, value, Strings.ToString(values)));
}
private static TValue ValueOf(dynamic parameters, string name, string value, Type valueType, Request request, ParameterType parameterType)
{
var parser = Parsers.GetIfPresent(valueType);
if (parser != null)
{
return ParseValueUsing(name, value, valueType, parser);
}
if (parameterType == ParameterType.Path)
{
return DynamicValueOf(parameters, name);
}
if (parameterType == ParameterType.Query)
{
return DynamicValueOf(request.Query, name);
}
throw new InvalidOperationException(string.Format("Could not get value for {0} with type {1}", name, valueType));
}
private static TValue ParseValueUsing(string name, string value, Type valueType, Func parser)
{
var result = parser(Parameter.Of(name, value));
try
{
return (TValue)result;
}
catch (InvalidCastException)
{
throw new InvalidOperationException(
string.Format("Could not parse parameter: '{0}' with value: '{1}'. " +
"Received: '{2}', expected: '{3}'.",
name, value, result.GetType(), valueType));
}
}
private static TValue DynamicValueOf(dynamic parameters, string name)
{
string value = parameters[name];
try
{
TValue result = parameters[name];
return result;
}
catch (InvalidCastException)
{
throw new InvalidOperationException(Strings.Format("Parameter: '{0}' value: '{1}' could not be parsed. " +
"Expected type: '{2}' is not supported",
name, value, typeof(TValue)));
}
catch (Exception e)
{
throw new InvalidOperationException(string.Format("Could not get '{0}' value of '{1}' type dynamicly",
name, typeof(TValue)), e);
}
}
private static IDictionary> CreateParsers()
{
var parsers = ImmutableDictionary.CreateBuilder>();
parsers.Put(typeof(string), value => value);
parsers.Put(typeof(bool), SafeParse(bool.Parse));
parsers.Put(typeof(bool?), SafeParse(bool.Parse));
parsers.Put(typeof(byte), SafeParse(byte.Parse));
parsers.Put(typeof(sbyte?), SafeParse(sbyte.Parse));
parsers.Put(typeof(short), SafeParse(short.Parse));
parsers.Put(typeof(short?), SafeParse(short.Parse));
parsers.Put(typeof(ushort), SafeParse(ushort.Parse));
parsers.Put(typeof(ushort?), SafeParse(ushort.Parse));
parsers.Put(typeof(int), SafeParse(int.Parse));
parsers.Put(typeof(int?), SafeParse(int.Parse));
parsers.Put(typeof(uint), SafeParse(uint.Parse));
parsers.Put(typeof(uint?), SafeParse(uint.Parse));
parsers.Put(typeof(long), SafeParse(long.Parse));
parsers.Put(typeof(long?), SafeParse(long.Parse));
parsers.Put(typeof(ulong), SafeParse(ulong.Parse));
parsers.Put(typeof(ulong?), SafeParse(ulong.Parse));
parsers.Put(typeof(float), SafeParse(float.Parse));
parsers.Put(typeof(float?), SafeParse(float.Parse));
parsers.Put(typeof(double), SafeParse(double.Parse));
parsers.Put(typeof(double?), SafeParse(double.Parse));
parsers.Put(typeof(decimal), SafeParse(decimal.Parse));
parsers.Put(typeof(decimal?), SafeParse(decimal.Parse));
parsers.Put(typeof(DateTime), SafeParse(DateTime.Parse));
parsers.Put(typeof(DateTime?), SafeParse(DateTime.Parse));
parsers.Put(typeof(TimeSpan), SafeParse(TimeSpan.Parse));
parsers.Put(typeof(TimeSpan?), SafeParse(TimeSpan.Parse));
parsers.Put(typeof(ZonedDateTime), SafeParse(ParseZonedDateTime));
parsers.Put(typeof(ZonedDateTime?), SafeParse(ParseZonedDateTime));
parsers.Put(typeof(LocalTime), SafeParse(ParseLocalTime));
parsers.Put(typeof(LocalTime?), SafeParse(ParseLocalTime));
parsers.Put(typeof(IEnumerable), value => value);
parsers.Put(typeof(ICollection), value => value);
parsers.Put(typeof(IList), value => value);
parsers.Put(typeof(List), value => value);
parsers.Put(typeof(ISet), value => value);
parsers.Put(typeof(HashSet), value => value);
parsers.Put(typeof(IEnumerable), ImmutableListParse(bool.Parse));
parsers.Put(typeof(ICollection), ImmutableListParse(bool.Parse));
parsers.Put(typeof(IList), ImmutableListParse(bool.Parse));
parsers.Put(typeof(List), ListParse(bool.Parse));
parsers.Put(typeof(ISet), ImmutableSetParse(bool.Parse));
parsers.Put(typeof(HashSet), SetParse(bool.Parse));
parsers.Put(typeof(IEnumerable), ImmutableListParse(byte.Parse));
parsers.Put(typeof(ICollection), ImmutableListParse(byte.Parse));
parsers.Put(typeof(IList), ImmutableListParse(byte.Parse));
parsers.Put(typeof(List), ListParse(byte.Parse));
parsers.Put(typeof(ISet), ImmutableSetParse(byte.Parse));
parsers.Put(typeof(HashSet), SetParse(byte.Parse));
parsers.Put(typeof(IEnumerable), ImmutableListParse(sbyte.Parse));
parsers.Put(typeof(ICollection), ImmutableListParse(sbyte.Parse));
parsers.Put(typeof(IList), ImmutableListParse(sbyte.Parse));
parsers.Put(typeof(List), ListParse(sbyte.Parse));
parsers.Put(typeof(ISet), ImmutableSetParse(sbyte.Parse));
parsers.Put(typeof(HashSet), SetParse(sbyte.Parse));
parsers.Put(typeof(IEnumerable), ImmutableListParse(short.Parse));
parsers.Put(typeof(ICollection), ImmutableListParse(short.Parse));
parsers.Put(typeof(IList), ImmutableListParse(short.Parse));
parsers.Put(typeof(List), ListParse(short.Parse));
parsers.Put(typeof(ISet), ImmutableSetParse(short.Parse));
parsers.Put(typeof(HashSet), SetParse(short.Parse));
parsers.Put(typeof(IEnumerable), ImmutableListParse(ushort.Parse));
parsers.Put(typeof(ICollection), ImmutableListParse(ushort.Parse));
parsers.Put(typeof(IList), ImmutableListParse(ushort.Parse));
parsers.Put(typeof(List), ListParse(ushort.Parse));
parsers.Put(typeof(ISet), ImmutableSetParse(ushort.Parse));
parsers.Put(typeof(HashSet), SetParse(ushort.Parse));
parsers.Put(typeof(IEnumerable), ImmutableListParse(int.Parse));
parsers.Put(typeof(ICollection), ImmutableListParse(int.Parse));
parsers.Put(typeof(IList), ImmutableListParse(int.Parse));
parsers.Put(typeof(List), ListParse(int.Parse));
parsers.Put(typeof(ISet), ImmutableSetParse(int.Parse));
parsers.Put(typeof(HashSet), SetParse(int.Parse));
parsers.Put(typeof(IEnumerable), ImmutableListParse(uint.Parse));
parsers.Put(typeof(ICollection), ImmutableListParse(uint.Parse));
parsers.Put(typeof(IList), ImmutableListParse(uint.Parse));
parsers.Put(typeof(List), ListParse(uint.Parse));
parsers.Put(typeof(ISet), ImmutableSetParse(uint.Parse));
parsers.Put(typeof(HashSet), SetParse(uint.Parse));
parsers.Put(typeof(IEnumerable), ImmutableListParse(long.Parse));
parsers.Put(typeof(ICollection), ImmutableListParse(long.Parse));
parsers.Put(typeof(IList), ImmutableListParse(long.Parse));
parsers.Put(typeof(List), ListParse(long.Parse));
parsers.Put(typeof(ISet), ImmutableSetParse(long.Parse));
parsers.Put(typeof(HashSet), SetParse(long.Parse));
parsers.Put(typeof(IEnumerable), ImmutableListParse(ulong.Parse));
parsers.Put(typeof(ICollection), ImmutableListParse(ulong.Parse));
parsers.Put(typeof(IList), ImmutableListParse(ulong.Parse));
parsers.Put(typeof(List), ListParse(ulong.Parse));
parsers.Put(typeof(ISet), ImmutableSetParse(ulong.Parse));
parsers.Put(typeof(HashSet), SetParse(ulong.Parse));
parsers.Put(typeof(IEnumerable), ImmutableListParse(float.Parse));
parsers.Put(typeof(ICollection), ImmutableListParse(float.Parse));
parsers.Put(typeof(IList), ImmutableListParse(float.Parse));
parsers.Put(typeof(List), ListParse(float.Parse));
parsers.Put(typeof(ISet), ImmutableSetParse(float.Parse));
parsers.Put(typeof(HashSet), SetParse(float.Parse));
parsers.Put(typeof(IEnumerable), ImmutableListParse(double.Parse));
parsers.Put(typeof(ICollection), ImmutableListParse(double.Parse));
parsers.Put(typeof(IList), ImmutableListParse(double.Parse));
parsers.Put(typeof(List), ListParse(double.Parse));
parsers.Put(typeof(ISet), ImmutableSetParse(double.Parse));
parsers.Put(typeof(HashSet), SetParse(double.Parse));
parsers.Put(typeof(IEnumerable), ImmutableListParse(decimal.Parse));
parsers.Put(typeof(ICollection), ImmutableListParse(decimal.Parse));
parsers.Put(typeof(IList), ImmutableListParse(decimal.Parse));
parsers.Put(typeof(List), ListParse(decimal.Parse));
parsers.Put(typeof(ISet), ImmutableSetParse(decimal.Parse));
parsers.Put(typeof(HashSet), SetParse(decimal.Parse));
parsers.Put(typeof(IEnumerable), ImmutableListParse(DateTime.Parse));
parsers.Put(typeof(ICollection), ImmutableListParse(DateTime.Parse));
parsers.Put(typeof(IList), ImmutableListParse(DateTime.Parse));
parsers.Put(typeof(List), ListParse(DateTime.Parse));
parsers.Put(typeof(ISet), ImmutableSetParse(DateTime.Parse));
parsers.Put(typeof(HashSet), SetParse(DateTime.Parse));
parsers.Put(typeof(IEnumerable), ImmutableListParse(TimeSpan.Parse));
parsers.Put(typeof(ICollection), ImmutableListParse(TimeSpan.Parse));
parsers.Put(typeof(IList), ImmutableListParse(TimeSpan.Parse));
parsers.Put(typeof(List), ListParse(TimeSpan.Parse));
parsers.Put(typeof(ISet), ImmutableSetParse(TimeSpan.Parse));
parsers.Put(typeof(HashSet), SetParse(TimeSpan.Parse));
return parsers.ToImmutableDictionary();
}
private static Func SafeParse(Func parse)
{
return parameter =>
{
try
{
return parse(parameter.Value);
}
catch (OverflowException)
{
throw ParameterOutOfRange(parameter, typeof(T));
}
catch (FormatException)
{
throw InvalidParameterFormat(parameter, typeof(T));
}
catch (Exception e)
{
throw new InvalidOperationException(Strings.Format("Unable to parse parameter: '{0}' with value: '{1}' to {2}",
parameter.Name, parameter.Value, typeof(T)), e);
}
};
}
private static Func ListParse(Func itemParser)
{
return parameter =>
{
if (string.IsNullOrEmpty(parameter.Value))
{
return new List();
}
var results = parameter.Value.Split(new[] { ',' }, StringSplitOptions.None)
.Where(it => it != null)
.Select(it => it.Trim())
.Select(itemParser)
.ToList();
return results;
};
}
private static Func ImmutableListParse(Func itemParser)
{
return parameter =>
{
if (string.IsNullOrEmpty(parameter.Value))
{
return Lists.EmptyList();
}
var results = parameter.Value.Split(new[] { ',' }, StringSplitOptions.None)
.Where(it => it != null)
.Select(it => it.Trim())
.Select(itemParser)
.ToImmutableList();
return results;
};
}
private static Func SetParse(Func itemParser)
{
return parameter =>
{
if (string.IsNullOrEmpty(parameter.Value))
{
return new HashSet();
}
var results = parameter.Value.Split(new[] { ',' }, StringSplitOptions.None)
.Where(it => it != null)
.Select(it => it.Trim())
.Select(itemParser)
.ToSet();
return results;
};
}
private static Func ImmutableSetParse(Func itemParser)
{
return parameter =>
{
if (string.IsNullOrEmpty(parameter.Value))
{
return Sets.EmptySet();
}
var results = parameter.Value.Split(new[] { ',' }, StringSplitOptions.None)
.Where(it => it != null)
.Select(it => it.Trim())
.Select(itemParser)
.ToImmutableHashSet();
return results;
};
}
private static ZonedDateTime ParseZonedDateTime(string value)
{
var dateTime = DateTime.Parse(value);
return new ZonedDateTime(Instant.FromDateTimeUtc(dateTime.ToUniversalTime()), DateTimeZone.Utc);
}
private static LocalTime ParseLocalTime(string value)
{
return LocalTimePattern.ExtendedIsoPattern.Parse(value).Value;
}
private static ArgumentException ParameterOutOfRange(Parameter parameter, Type type)
{
return new ArgumentException(Strings.Format("Query: '{0}' value: '{1}' is out of range for: '{2}'",
parameter.Name, parameter.Value, type));
}
private static ArgumentException InvalidParameterFormat(Parameter parameter, Type type)
{
return new ArgumentException(Strings.Format("Query '{0}' value: '{1}' format is invalid for: '{2}'",
parameter.Name, parameter.Value, type));
}
private class Parameter
{
internal string Name { get; private set; }
internal string Value { get; private set; }
private Parameter(string name, string value)
{
Name = name;
Value = value;
}
internal static Parameter Of(string name, string value)
{
return new Parameter(name, value);
}
}
}
internal enum ParameterType
{
Undefined,
Query,
Path,
Header
}
}