PageRenderTime 56ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/Assets/AWSSDK/src/Core/Amazon.Util/PaginatedResourceFactory.cs

https://gitlab.com/github-cloud-corp/aws-sdk-unity
C# | 293 lines | 246 code | 26 blank | 21 comment | 19 complexity | 78c777166d799a574a67c61f106b2f4b MD5 | raw file
  1. //
  2. // Copyright 2014-2015 Amazon.com,
  3. // Inc. or its affiliates. All Rights Reserved.
  4. //
  5. // Licensed under the Amazon Software License (the "License").
  6. // You may not use this file except in compliance with the
  7. // License. A copy of the License is located at
  8. //
  9. // http://aws.amazon.com/asl/
  10. //
  11. // or in the "license" file accompanying this file. This file is
  12. // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  13. // CONDITIONS OF ANY KIND, express or implied. See the License
  14. // for the specific language governing permissions and
  15. // limitations under the License.
  16. //
  17. using System;
  18. using System.Collections;
  19. using System.Collections.Generic;
  20. using System.Linq;
  21. using System.Text;
  22. using System.Reflection;
  23. using System.Globalization;
  24. using Amazon.Util.Internal;
  25. namespace Amazon.Util
  26. {
  27. public static class PaginatedResourceFactory
  28. {
  29. public static object Create<TItemType, TRequestType, TResponseType>(PaginatedResourceInfo pri)
  30. {
  31. pri.Verify();
  32. return Create<TItemType, TRequestType, TResponseType>(pri.Client, pri.MethodName, pri.Request, pri.TokenRequestPropertyPath, pri.TokenResponsePropertyPath, pri.ItemListPropertyPath);
  33. }
  34. private static PaginatedResource<ItemType> Create<ItemType, TRequestType, TResponseType>
  35. (object client, string methodName, object request, string tokenRequestPropertyPath, string tokenResponsePropertyPath, string itemListPropertyPath)
  36. {
  37. ITypeInfo clientType = TypeFactory.GetTypeInfo(client.GetType());
  38. MethodInfo fetcherMethod = clientType.GetMethod(methodName, new ITypeInfo[] { TypeFactory.GetTypeInfo(typeof(TRequestType)) });
  39. //Type funcType = GetFuncType<TRequestType, TResponseType>();
  40. Func<TRequestType, TResponseType> call = (req) =>
  41. {
  42. return (TResponseType)fetcherMethod.Invoke(client, new object[] { req });
  43. };
  44. return Create<ItemType, TRequestType, TResponseType>(call, (TRequestType)request, tokenRequestPropertyPath, tokenResponsePropertyPath, itemListPropertyPath);
  45. }
  46. private static PaginatedResource<ItemType> Create<ItemType, TRequestType, TResponseType>
  47. (Func<TRequestType, TResponseType> call, TRequestType request, string tokenRequestPropertyPath, string tokenResponsePropertyPath, string itemListPropertyPath)
  48. {
  49. Func<string, Marker<ItemType>> fetcher =
  50. token =>
  51. {
  52. List<ItemType> currentItems;
  53. string nextToken;
  54. SetPropertyValueAtPath(request, tokenRequestPropertyPath, token);
  55. TResponseType nextSet = call(request);
  56. nextToken = GetPropertyValueFromPath<string>(nextSet, tokenResponsePropertyPath);
  57. currentItems = GetPropertyValueFromPath<List<ItemType>>(nextSet, itemListPropertyPath);
  58. return new Marker<ItemType>(currentItems, nextToken);
  59. };
  60. return new PaginatedResource<ItemType>(fetcher);
  61. }
  62. private static void SetPropertyValueAtPath(object instance, string path, string value)
  63. {
  64. String[] propPath = path.Split('.');
  65. object currentValue = instance;
  66. Type currentType = instance.GetType();
  67. PropertyInfo currentProperty = null;
  68. int i = 0;
  69. for (; i < propPath.Length - 1; i++)
  70. {
  71. string property = propPath[i];
  72. currentProperty = TypeFactory.GetTypeInfo(currentType).GetProperty(property);
  73. currentValue = currentProperty.GetValue(currentValue, null);
  74. currentType = currentProperty.PropertyType;
  75. }
  76. currentProperty = TypeFactory.GetTypeInfo(currentType).GetProperty(propPath[i]);
  77. currentProperty.SetValue(currentValue, value, null);
  78. }
  79. private static T GetPropertyValueFromPath<T>(object instance, string path)
  80. {
  81. String[] propPath = path.Split('.');
  82. object currentValue = instance;
  83. Type currentType = instance.GetType();
  84. PropertyInfo currentProperty = null;
  85. foreach (string property in propPath)
  86. {
  87. currentProperty = TypeFactory.GetTypeInfo(currentType).GetProperty(property);
  88. currentValue = currentProperty.GetValue(currentValue, null);
  89. currentType = currentProperty.PropertyType;
  90. }
  91. return (T)currentValue;
  92. }
  93. internal static Type GetPropertyTypeFromPath(Type start, string path)
  94. {
  95. String[] propPath = path.Split('.');
  96. Type currentType = start;
  97. PropertyInfo currentProperty = null;
  98. foreach (string property in propPath)
  99. {
  100. currentProperty = TypeFactory.GetTypeInfo(currentType).GetProperty(property);
  101. currentType = currentProperty.PropertyType;
  102. }
  103. return currentType;
  104. }
  105. private static Type GetFuncType<T, U>()
  106. {
  107. return typeof(Func<T, U>);
  108. }
  109. internal static T Cast<T>(object o)
  110. {
  111. return (T)o;
  112. }
  113. }
  114. public class PaginatedResourceInfo
  115. {
  116. private string tokenRequestPropertyPath;
  117. private string tokenResponsePropertyPath;
  118. internal object Client
  119. {
  120. get;
  121. set;
  122. }
  123. internal string MethodName
  124. {
  125. get;
  126. set;
  127. }
  128. internal object Request
  129. {
  130. get;
  131. set;
  132. }
  133. internal string TokenRequestPropertyPath
  134. {
  135. get
  136. {
  137. string ret = tokenRequestPropertyPath;
  138. if (String.IsNullOrEmpty(ret))
  139. {
  140. ret = "NextToken";
  141. }
  142. return ret;
  143. }
  144. set { tokenRequestPropertyPath = value; }
  145. }
  146. internal string TokenResponsePropertyPath
  147. {
  148. get
  149. {
  150. string ret = tokenResponsePropertyPath;
  151. if (String.IsNullOrEmpty(ret))
  152. {
  153. ret = "{0}";
  154. if (Client != null && !String.IsNullOrEmpty(MethodName))
  155. {
  156. MethodInfo mi = TypeFactory.GetTypeInfo(Client.GetType()).GetMethod(MethodName);
  157. if (mi != null)
  158. {
  159. Type responseType = mi.ReturnType;
  160. string baseName = responseType.Name;
  161. if (baseName.EndsWith("Response", StringComparison.Ordinal))
  162. {
  163. baseName = baseName.Substring(0, baseName.Length - 8);
  164. }
  165. if (TypeFactory.GetTypeInfo(responseType).GetProperty(string.Format(CultureInfo.InvariantCulture, "{0}Result", baseName)) != null)
  166. {
  167. ret = string.Format(CultureInfo.InvariantCulture, ret, string.Format(CultureInfo.InvariantCulture, "{0}Result.{1}", baseName, "{0}"));
  168. }
  169. }
  170. }
  171. ret = string.Format(CultureInfo.InvariantCulture, ret, "NextToken");
  172. }
  173. return ret;
  174. }
  175. set { tokenResponsePropertyPath = value; }
  176. }
  177. internal string ItemListPropertyPath
  178. {
  179. get;
  180. set;
  181. }
  182. public PaginatedResourceInfo WithClient(object client)
  183. {
  184. Client = client;
  185. return this;
  186. }
  187. public PaginatedResourceInfo WithMethodName(string methodName)
  188. {
  189. MethodName = methodName;
  190. return this;
  191. }
  192. public PaginatedResourceInfo WithRequest(object request)
  193. {
  194. Request = request;
  195. return this;
  196. }
  197. public PaginatedResourceInfo WithTokenRequestPropertyPath(string tokenRequestPropertyPath)
  198. {
  199. TokenRequestPropertyPath = tokenRequestPropertyPath;
  200. return this;
  201. }
  202. public PaginatedResourceInfo WithTokenResponsePropertyPath(string tokenResponsePropertyPath)
  203. {
  204. TokenResponsePropertyPath = tokenResponsePropertyPath;
  205. return this;
  206. }
  207. public PaginatedResourceInfo WithItemListPropertyPath(string itemListPropertyPath)
  208. {
  209. ItemListPropertyPath = itemListPropertyPath;
  210. return this;
  211. }
  212. internal void Verify()
  213. {
  214. //Client is set
  215. if (Client == null)
  216. {
  217. throw new ArgumentException("PaginatedResourceInfo.Client needs to be set.");
  218. }
  219. //MethodName exists on Client and takes one argument of the declared request type
  220. Type clientType = Client.GetType();
  221. MethodInfo mi = TypeFactory.GetTypeInfo(clientType).GetMethod(MethodName, new ITypeInfo[] { TypeFactory.GetTypeInfo(Request.GetType()) });
  222. if (mi == null)
  223. {
  224. throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "{0} has no method called {1}", clientType.Name, MethodName));
  225. }
  226. //Request is valid type.
  227. Type requestType = mi.GetParameters()[0].ParameterType;
  228. try
  229. {
  230. Convert.ChangeType(Request, requestType, CultureInfo.InvariantCulture);
  231. }
  232. catch (Exception)
  233. {
  234. throw new ArgumentException("PaginatedResourcInfo.Request is an incompatible type.");
  235. }
  236. //Properties exist
  237. Type responseType = mi.ReturnType;
  238. VerifyProperty("TokenRequestPropertyPath", requestType, TokenRequestPropertyPath, typeof(string));
  239. VerifyProperty("TokenResponsePropertyPath", responseType, TokenResponsePropertyPath, typeof(string));
  240. VerifyProperty("ItemListPropertyPath", responseType, ItemListPropertyPath, typeof(string), true);
  241. }
  242. private static void VerifyProperty(string propName, Type start, string path, Type expectedType)
  243. {
  244. VerifyProperty(propName, start, path, expectedType, false);
  245. }
  246. private static void VerifyProperty(string propName, Type start, string path, Type expectedType, bool skipTypecheck)
  247. {
  248. Type type = null;
  249. if (String.IsNullOrEmpty(path))
  250. {
  251. throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "{0} must contain a value.", propName));
  252. }
  253. try
  254. {
  255. type = PaginatedResourceFactory.GetPropertyTypeFromPath(start, path);
  256. }
  257. catch (Exception)
  258. {
  259. throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "{0} does not exist on {1}", path, start.Name));
  260. }
  261. if (!skipTypecheck && type != expectedType)
  262. {
  263. throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "{0} on {1} is not of type {2}", path, start.Name, expectedType.Name));
  264. }
  265. }
  266. }
  267. }