PageRenderTime 63ms CodeModel.GetById 23ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

/Assets/AWSSDK/src/Services/DynamoDBv2/Custom/DataModel/Utils.cs

https://gitlab.com/github-cloud-corp/aws-sdk-unity
C# | 355 lines | 297 code | 39 blank | 19 comment | 61 complexity | 5fafe96bac29588b80ec4cc3c773c85d 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//
 17using System;
 18using System.Collections.Generic;
 19using System.IO;
 20using System.Linq;
 21using System.Reflection;
 22using System.Text;
 23
 24using Amazon.Util.Internal;
 25using System.Globalization;
 26using System.Collections;
 27using Amazon.DynamoDBv2.DocumentModel;
 28
 29namespace Amazon.DynamoDBv2.DataModel
 30{
 31    internal static class Utils
 32    {
 33        #region Type methods
 34
 35        private static readonly Type[] primitiveTypesArray = new Type[]
 36        {
 37            typeof(Boolean),
 38            typeof(Byte),
 39            typeof(Char),
 40            typeof(DateTime),
 41            typeof(Decimal),
 42            typeof(Double),
 43            typeof(int),
 44            typeof(long),
 45            typeof(SByte),
 46            typeof(short),
 47            typeof(Single),
 48            typeof(String),
 49            typeof(uint),
 50            typeof(ulong),
 51            typeof(ushort),
 52            typeof(Guid),
 53            typeof(byte[]),
 54            typeof(MemoryStream),
 55            typeof(Primitive)
 56        };
 57
 58        public static readonly IEnumerable<Type> PrimitiveTypes = new HashSet<Type>(primitiveTypesArray);
 59        private static readonly HashSet<ITypeInfo> PrimitiveTypeInfos = new HashSet<ITypeInfo>(primitiveTypesArray
 60            .Select(p => TypeFactory.GetTypeInfo(p)));
 61
 62        public static bool IsPrimitive(Type type)
 63        {
 64            var typeWrapper = TypeFactory.GetTypeInfo(type);
 65            return PrimitiveTypeInfos.Any(ti => typeWrapper.IsAssignableFrom(ti));
 66        }
 67        public static bool IsPrimitive<T>()
 68        {
 69            return IsPrimitive(typeof(T));
 70        }
 71        public static void ValidatePrimitiveType(Type type)
 72        {
 73            if (!Utils.IsPrimitive(type))
 74                throw new InvalidCastException(string.Format(CultureInfo.InvariantCulture,
 75                    "{0} is not a supported Primitive type", type.FullName));
 76        }
 77        public static void ValidatePrimitiveType<T>()
 78        {
 79            ValidatePrimitiveType(typeof(T));
 80        }
 81
 82        public static void ValidateVersionType(Type memberType)
 83        {
 84            var memberTypeWrapper = TypeFactory.GetTypeInfo(memberType);
 85            if (memberTypeWrapper.IsGenericType && memberTypeWrapper.GetGenericTypeDefinition() == typeof(Nullable<>) &&
 86                (memberTypeWrapper.IsAssignableFrom(TypeFactory.GetTypeInfo(typeof(Byte))) ||
 87                memberTypeWrapper.IsAssignableFrom(TypeFactory.GetTypeInfo(typeof(SByte))) ||
 88                memberTypeWrapper.IsAssignableFrom(TypeFactory.GetTypeInfo(typeof(int))) ||
 89                memberTypeWrapper.IsAssignableFrom(TypeFactory.GetTypeInfo(typeof(uint))) ||
 90                memberTypeWrapper.IsAssignableFrom(TypeFactory.GetTypeInfo(typeof(long))) ||
 91                memberTypeWrapper.IsAssignableFrom(TypeFactory.GetTypeInfo(typeof(ulong))) ||
 92                memberTypeWrapper.IsAssignableFrom(TypeFactory.GetTypeInfo(typeof(short))) ||
 93                memberTypeWrapper.IsAssignableFrom(TypeFactory.GetTypeInfo(typeof(ushort)))))
 94            {
 95                return;
 96            }
 97            throw new InvalidOperationException("Version property must be of primitive, numeric, integer, nullable type (e.g. int?, long?, byte?)");
 98        }
 99
100        public static Type GetPrimitiveElementType(Type collectionType)
101        {
102            var elementType = Utils.GetElementType(collectionType);
103
104            if (elementType != null)
105            {
106                Utils.ValidatePrimitiveType(elementType);
107                return elementType;
108            }
109
110            throw new InvalidOperationException("Unable to determine element type");
111        }
112        public static Type GetElementType(Type collectionType)
113        {
114            var elementType = collectionType.GetElementType();
115
116            if (elementType == null)
117            {
118                var collectionTypeInfo = TypeFactory.GetTypeInfo(collectionType);
119                var genericArguments = collectionTypeInfo.GetGenericArguments();
120                if (genericArguments != null && genericArguments.Length == 1)
121                    elementType = genericArguments[0];
122            }
123
124            // elementType may be null at this point, meaning that the collectionType isn't a collectionType
125            return elementType;
126        }
127
128        public static bool ItemsToCollection(Type targetType, IEnumerable<object> items, out object result)
129        {
130            result = Utils.Instantiate(targetType);
131
132            var ilist = result as IList;
133            if (ilist != null)
134            {
135                foreach (var item in items)
136                    ilist.Add(item);
137                return true;
138            }
139
140            var targetTypeInfo = TypeFactory.GetTypeInfo(targetType);
141            var addMethod = targetTypeInfo.GetMethod("Add");
142            if (addMethod != null)
143            {
144                foreach (var item in items)
145                    addMethod.Invoke(result, new object[] { item });
146                return true;
147            }
148
149            result = null;
150            return false;
151        }
152
153        #endregion
154
155        #region Attribute methods
156
157        public static DynamoDBTableAttribute GetTableAttribute(ITypeInfo targetTypeInfo)
158        {
159            DynamoDBTableAttribute tableAttribute = GetAttribute(targetTypeInfo) as DynamoDBTableAttribute;
160            if (tableAttribute == null)
161                return null;
162            return tableAttribute;
163        }
164
165        public static DynamoDBAttribute GetAttribute(ITypeInfo targetTypeInfo)
166        {
167            if (targetTypeInfo == null) throw new ArgumentNullException("targetTypeInfo");
168            object[] attributes = targetTypeInfo.GetCustomAttributes(TypeFactory.GetTypeInfo(typeof(DynamoDBAttribute)), true);
169            return GetSingleDDBAttribute(attributes);
170        }
171        public static DynamoDBAttribute GetAttribute(MemberInfo targetMemberInfo)
172        {
173            object[] attributes = GetAttributeObjects(targetMemberInfo);
174            return GetSingleDDBAttribute(attributes);
175        }
176        public static List<DynamoDBAttribute> GetAttributes(MemberInfo targetMemberInfo)
177        {
178            object[] attObjects = GetAttributeObjects(targetMemberInfo) ?? new object[0];
179            var attributes = new List<DynamoDBAttribute>();
180            foreach (var attObj in attObjects)
181            {
182                var attribute = attObj as DynamoDBAttribute;
183                if (attribute != null)
184                    attributes.Add(attribute);
185            }
186            return attributes;
187        }
188
189        private static DynamoDBAttribute GetSingleDDBAttribute(object[] attributes)
190        {
191            if (attributes.Length == 0)
192                return null;
193            if (attributes.Length == 1)
194                return (attributes[0] as DynamoDBAttribute);
195            throw new InvalidOperationException("Cannot have multiple DynamoDBAttributes on a single member");
196        }
197
198        private static object[] GetAttributeObjects(MemberInfo targetMemberInfo)
199        {
200            if (targetMemberInfo == null) throw new ArgumentNullException("targetMemberInfo");
201#if PCL
202            object[] attributes = targetMemberInfo.GetCustomAttributes(typeof(DynamoDBAttribute), true).ToArray();
203#else
204            object[] attributes = targetMemberInfo.GetCustomAttributes(typeof(DynamoDBAttribute), true);
205#endif
206            return attributes;
207        }
208
209        #endregion
210
211        #region Non-DynamoDB utilities
212
213        public static string ToLowerCamelCase(string value)
214        {
215            if (string.IsNullOrEmpty(value) || char.IsLower(value[0])) return value;
216            StringBuilder sb = new StringBuilder(value);
217            sb[0] = char.ToLowerInvariant(sb[0]);
218            return sb.ToString();
219        }
220
221        private static ITypeInfo[][] validConstructorInputs = new ITypeInfo[][]
222        {
223            TypeFactory.EmptyTypes,
224        };
225        private static ITypeInfo[][] validConverterConstructorInputs = new ITypeInfo[][]
226        {
227            TypeFactory.EmptyTypes,
228            new ITypeInfo[] { TypeFactory.GetTypeInfo(typeof(DynamoDBContext)) }
229        };
230
231        public static object InstantiateConverter(Type objectType, IDynamoDBContext context)
232        {
233            return InstantiateHelper(objectType, validConverterConstructorInputs, new object[] { context });
234        }
235        public static object Instantiate(Type objectType)
236        {
237            return InstantiateHelper(objectType, validConstructorInputs, null);
238        }
239        private static object InstantiateHelper(Type objectType, ITypeInfo[][] validConstructorInputs, object[] optionalInput = null)
240        {
241            if (objectType == null)
242                throw new ArgumentNullException("objectType");
243            if (!CanInstantiateHelper(objectType, validConstructorInputs))
244                throw new InvalidOperationException("Cannot instantiate type " + objectType.FullName);
245
246            var objectTypeWrapper = TypeFactory.GetTypeInfo(objectType);
247            var constructors = GetConstructors(objectTypeWrapper, validConverterConstructorInputs).ToList();
248
249            if (constructors != null && constructors.Count > 0)
250            {
251                foreach (var constructor in constructors)
252                {
253                    var inputs = constructor.GetParameters();
254                    object[] constructorParameters = inputs.Length == 0 ?
255                        null : optionalInput;
256                    object instance = constructor.Invoke(constructorParameters);
257                    return instance;
258                }
259            }
260
261            throw new InvalidOperationException("Unable to find valid constructor for type " + objectType.FullName);
262        }
263        private static IEnumerable<ConstructorInfo> GetConstructors(ITypeInfo typeInfo, ITypeInfo[][] validConstructorInputs)
264        {
265            foreach(var inputTypes in validConstructorInputs)
266            {
267                var constructor = typeInfo.GetConstructor(inputTypes);
268                if (constructor != null)
269                    yield return constructor;
270            }
271        }
272
273        public static bool CanInstantiate(Type objectType)
274        {
275            return CanInstantiateHelper(objectType, validConstructorInputs);
276        }
277        public static bool CanInstantiateConverter(Type objectType)
278        {
279            return CanInstantiateHelper(objectType, validConverterConstructorInputs);
280        }
281        private static bool CanInstantiateHelper(Type objectType, ITypeInfo[][] validConstructorInputs)
282        {
283            var objectTypeWrapper = TypeFactory.GetTypeInfo(objectType);
284
285            bool candidate =
286                //objectType.IsPublic &&
287                objectTypeWrapper.IsClass &&
288                !objectTypeWrapper.IsInterface &&
289                !objectTypeWrapper.IsAbstract &&
290                !objectTypeWrapper.IsGenericTypeDefinition &&
291                !objectTypeWrapper.ContainsGenericParameters;
292
293            if (!candidate)
294                return false;
295
296            // check valid constructor inputs
297            var constructors = GetConstructors(objectTypeWrapper, validConstructorInputs).ToList();
298            if (constructors.Count == 0)
299                return false;
300
301            return true;
302        }
303        public static Type GetType(MemberInfo member)
304        {
305            var pi = member as PropertyInfo;
306            var fi = member as FieldInfo;
307            if (pi == null && fi == null)
308                throw new ArgumentOutOfRangeException("member", "member must be of type PropertyInfo or FieldInfo");
309
310            return (pi != null ? pi.PropertyType : fi.FieldType);
311        }
312        public static bool IsReadWrite(MemberInfo member)
313        {
314            PropertyInfo property = member as PropertyInfo;
315            FieldInfo field = member as FieldInfo;
316
317            if (property != null)
318            {
319                return (property.CanRead && property.CanWrite);
320            }
321            else if (field != null)
322            {
323                return (field.IsPublic && !field.IsLiteral && !field.IsInitOnly);
324            }
325            else
326            {
327                throw new ArgumentOutOfRangeException("member", "Member must be FieldInfo or PropertyInfo");
328            }
329        }
330        public static bool ImplementsInterface(Type targetType, Type interfaceType)
331        {
332            var targetTypeWrapper = TypeFactory.GetTypeInfo(targetType);
333            var interfaceTypeWrapper = TypeFactory.GetTypeInfo(interfaceType);
334            if (!interfaceTypeWrapper.IsInterface)
335                throw new ArgumentOutOfRangeException("interfaceType", "Type is not an interface");
336
337            foreach (var inter in targetTypeWrapper.GetInterfaces())
338            {
339                var interWrapper = TypeFactory.GetTypeInfo(inter);
340                if (object.Equals(interWrapper, interfaceTypeWrapper))
341                    return true;
342                if (interfaceTypeWrapper.IsGenericTypeDefinition && interWrapper.IsGenericType)
343                {
344                    var generic = interWrapper.GetGenericTypeDefinition();
345                    if (generic == interfaceType)
346                        return true;
347                }
348            }
349            return false;
350        }
351
352        #endregion
353
354    }
355}