/Assets/AWSSDK/src/Core/Amazon.Util/PaginatedResourceFactory.cs
C# | 293 lines | 246 code | 26 blank | 21 comment | 19 complexity | 78c777166d799a574a67c61f106b2f4b MD5 | raw file
- //
- // Copyright 2014-2015 Amazon.com,
- // Inc. or its affiliates. All Rights Reserved.
- //
- // Licensed under the Amazon Software License (the "License").
- // You may not use this file except in compliance with the
- // License. A copy of the License is located at
- //
- // http://aws.amazon.com/asl/
- //
- // or in the "license" file accompanying this file. This file is
- // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
- // CONDITIONS OF ANY KIND, 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;
- using System.Text;
- using System.Reflection;
- using System.Globalization;
- using Amazon.Util.Internal;
- namespace Amazon.Util
- {
- public static class PaginatedResourceFactory
- {
- public static object Create<TItemType, TRequestType, TResponseType>(PaginatedResourceInfo pri)
- {
- pri.Verify();
- return Create<TItemType, TRequestType, TResponseType>(pri.Client, pri.MethodName, pri.Request, pri.TokenRequestPropertyPath, pri.TokenResponsePropertyPath, pri.ItemListPropertyPath);
- }
- private static PaginatedResource<ItemType> Create<ItemType, TRequestType, TResponseType>
- (object client, string methodName, object request, string tokenRequestPropertyPath, string tokenResponsePropertyPath, string itemListPropertyPath)
- {
- ITypeInfo clientType = TypeFactory.GetTypeInfo(client.GetType());
- MethodInfo fetcherMethod = clientType.GetMethod(methodName, new ITypeInfo[] { TypeFactory.GetTypeInfo(typeof(TRequestType)) });
- //Type funcType = GetFuncType<TRequestType, TResponseType>();
- Func<TRequestType, TResponseType> call = (req) =>
- {
- return (TResponseType)fetcherMethod.Invoke(client, new object[] { req });
- };
- return Create<ItemType, TRequestType, TResponseType>(call, (TRequestType)request, tokenRequestPropertyPath, tokenResponsePropertyPath, itemListPropertyPath);
- }
- private static PaginatedResource<ItemType> Create<ItemType, TRequestType, TResponseType>
- (Func<TRequestType, TResponseType> call, TRequestType request, string tokenRequestPropertyPath, string tokenResponsePropertyPath, string itemListPropertyPath)
- {
- Func<string, Marker<ItemType>> fetcher =
- token =>
- {
- List<ItemType> currentItems;
- string nextToken;
- SetPropertyValueAtPath(request, tokenRequestPropertyPath, token);
- TResponseType nextSet = call(request);
- nextToken = GetPropertyValueFromPath<string>(nextSet, tokenResponsePropertyPath);
- currentItems = GetPropertyValueFromPath<List<ItemType>>(nextSet, itemListPropertyPath);
- return new Marker<ItemType>(currentItems, nextToken);
- };
- return new PaginatedResource<ItemType>(fetcher);
- }
- private static void SetPropertyValueAtPath(object instance, string path, string value)
- {
- String[] propPath = path.Split('.');
- object currentValue = instance;
- Type currentType = instance.GetType();
- PropertyInfo currentProperty = null;
- int i = 0;
- for (; i < propPath.Length - 1; i++)
- {
- string property = propPath[i];
- currentProperty = TypeFactory.GetTypeInfo(currentType).GetProperty(property);
- currentValue = currentProperty.GetValue(currentValue, null);
- currentType = currentProperty.PropertyType;
- }
- currentProperty = TypeFactory.GetTypeInfo(currentType).GetProperty(propPath[i]);
- currentProperty.SetValue(currentValue, value, null);
- }
- private static T GetPropertyValueFromPath<T>(object instance, string path)
- {
- String[] propPath = path.Split('.');
- object currentValue = instance;
- Type currentType = instance.GetType();
- PropertyInfo currentProperty = null;
- foreach (string property in propPath)
- {
- currentProperty = TypeFactory.GetTypeInfo(currentType).GetProperty(property);
- currentValue = currentProperty.GetValue(currentValue, null);
- currentType = currentProperty.PropertyType;
- }
- return (T)currentValue;
- }
- internal static Type GetPropertyTypeFromPath(Type start, string path)
- {
- String[] propPath = path.Split('.');
- Type currentType = start;
- PropertyInfo currentProperty = null;
- foreach (string property in propPath)
- {
- currentProperty = TypeFactory.GetTypeInfo(currentType).GetProperty(property);
- currentType = currentProperty.PropertyType;
- }
- return currentType;
- }
- private static Type GetFuncType<T, U>()
- {
- return typeof(Func<T, U>);
- }
- internal static T Cast<T>(object o)
- {
- return (T)o;
- }
- }
- public class PaginatedResourceInfo
- {
- private string tokenRequestPropertyPath;
- private string tokenResponsePropertyPath;
- internal object Client
- {
- get;
- set;
- }
- internal string MethodName
- {
- get;
- set;
- }
- internal object Request
- {
- get;
- set;
- }
- internal string TokenRequestPropertyPath
- {
- get
- {
- string ret = tokenRequestPropertyPath;
- if (String.IsNullOrEmpty(ret))
- {
- ret = "NextToken";
- }
- return ret;
- }
- set { tokenRequestPropertyPath = value; }
- }
- internal string TokenResponsePropertyPath
- {
- get
- {
- string ret = tokenResponsePropertyPath;
- if (String.IsNullOrEmpty(ret))
- {
- ret = "{0}";
- if (Client != null && !String.IsNullOrEmpty(MethodName))
- {
- MethodInfo mi = TypeFactory.GetTypeInfo(Client.GetType()).GetMethod(MethodName);
- if (mi != null)
- {
- Type responseType = mi.ReturnType;
- string baseName = responseType.Name;
- if (baseName.EndsWith("Response", StringComparison.Ordinal))
- {
- baseName = baseName.Substring(0, baseName.Length - 8);
- }
- if (TypeFactory.GetTypeInfo(responseType).GetProperty(string.Format(CultureInfo.InvariantCulture, "{0}Result", baseName)) != null)
- {
- ret = string.Format(CultureInfo.InvariantCulture, ret, string.Format(CultureInfo.InvariantCulture, "{0}Result.{1}", baseName, "{0}"));
- }
- }
- }
- ret = string.Format(CultureInfo.InvariantCulture, ret, "NextToken");
- }
- return ret;
- }
- set { tokenResponsePropertyPath = value; }
- }
- internal string ItemListPropertyPath
- {
- get;
- set;
- }
- public PaginatedResourceInfo WithClient(object client)
- {
- Client = client;
- return this;
- }
- public PaginatedResourceInfo WithMethodName(string methodName)
- {
- MethodName = methodName;
- return this;
- }
- public PaginatedResourceInfo WithRequest(object request)
- {
- Request = request;
- return this;
- }
- public PaginatedResourceInfo WithTokenRequestPropertyPath(string tokenRequestPropertyPath)
- {
- TokenRequestPropertyPath = tokenRequestPropertyPath;
- return this;
- }
- public PaginatedResourceInfo WithTokenResponsePropertyPath(string tokenResponsePropertyPath)
- {
- TokenResponsePropertyPath = tokenResponsePropertyPath;
- return this;
- }
- public PaginatedResourceInfo WithItemListPropertyPath(string itemListPropertyPath)
- {
- ItemListPropertyPath = itemListPropertyPath;
- return this;
- }
- internal void Verify()
- {
- //Client is set
- if (Client == null)
- {
- throw new ArgumentException("PaginatedResourceInfo.Client needs to be set.");
- }
- //MethodName exists on Client and takes one argument of the declared request type
- Type clientType = Client.GetType();
- MethodInfo mi = TypeFactory.GetTypeInfo(clientType).GetMethod(MethodName, new ITypeInfo[] { TypeFactory.GetTypeInfo(Request.GetType()) });
- if (mi == null)
- {
- throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "{0} has no method called {1}", clientType.Name, MethodName));
- }
- //Request is valid type.
- Type requestType = mi.GetParameters()[0].ParameterType;
- try
- {
- Convert.ChangeType(Request, requestType, CultureInfo.InvariantCulture);
- }
- catch (Exception)
- {
- throw new ArgumentException("PaginatedResourcInfo.Request is an incompatible type.");
- }
- //Properties exist
- Type responseType = mi.ReturnType;
- VerifyProperty("TokenRequestPropertyPath", requestType, TokenRequestPropertyPath, typeof(string));
- VerifyProperty("TokenResponsePropertyPath", responseType, TokenResponsePropertyPath, typeof(string));
- VerifyProperty("ItemListPropertyPath", responseType, ItemListPropertyPath, typeof(string), true);
- }
- private static void VerifyProperty(string propName, Type start, string path, Type expectedType)
- {
- VerifyProperty(propName, start, path, expectedType, false);
- }
- private static void VerifyProperty(string propName, Type start, string path, Type expectedType, bool skipTypecheck)
- {
- Type type = null;
- if (String.IsNullOrEmpty(path))
- {
- throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "{0} must contain a value.", propName));
- }
- try
- {
- type = PaginatedResourceFactory.GetPropertyTypeFromPath(start, path);
- }
- catch (Exception)
- {
- throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "{0} does not exist on {1}", path, start.Name));
- }
- if (!skipTypecheck && type != expectedType)
- {
- throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "{0} on {1} is not of type {2}", path, start.Name, expectedType.Name));
- }
- }
- }
- }