Beispiel #1
0
        private static void PopulateConfigFromType(ItemStorageConfig config, ITypeInfo typeInfo)
        {
            DynamoDBTableAttribute tableAttribute = Utils.GetTableAttribute(typeInfo);

            if (tableAttribute == null)
            {
                config.TableName = typeInfo.Name;
            }
            else
            {
                if (string.IsNullOrEmpty(tableAttribute.TableName))
                {
                    throw new InvalidOperationException("DynamoDBTableAttribute.Table is empty or null");
                }
                config.TableName = tableAttribute.TableName;
                config.LowerCamelCaseProperties = tableAttribute.LowerCamelCaseProperties;
            }

            string tableAlias;

            if (AWSConfigs.DynamoDBConfig.Context.TableAliases.TryGetValue(config.TableName, out tableAlias))
            {
                config.TableName = tableAlias;
            }

            foreach (var member in typeInfo.GetMembers())
            {
                if (!ItemStorageConfig.IsValidMemberInfo(member))
                {
                    continue;
                }

                // prepare basic info
                PropertyStorage propertyStorage = new PropertyStorage(member);
                propertyStorage.AttributeName = GetAccurateCase(config, member.Name);

                // run through all DDB attributes
                List <DynamoDBAttribute> allAttributes = Utils.GetAttributes(member);
                foreach (var attribute in allAttributes)
                {
                    // filter out ignored properties
                    if (attribute is DynamoDBIgnoreAttribute)
                    {
                        propertyStorage.IsIgnored = true;
                    }

                    if (attribute is DynamoDBVersionAttribute)
                    {
                        propertyStorage.IsVersion = true;
                    }


                    DynamoDBPropertyAttribute propertyAttribute = attribute as DynamoDBPropertyAttribute;
                    if (propertyAttribute != null)
                    {
                        if (!string.IsNullOrEmpty(propertyAttribute.AttributeName))
                        {
                            propertyStorage.AttributeName = GetAccurateCase(config, propertyAttribute.AttributeName);
                        }

                        if (propertyAttribute.Converter != null)
                        {
                            propertyStorage.ConverterType = propertyAttribute.Converter;
                        }

                        if (propertyAttribute is DynamoDBHashKeyAttribute)
                        {
                            var gsiHashAttribute = propertyAttribute as DynamoDBGlobalSecondaryIndexHashKeyAttribute;
                            if (gsiHashAttribute != null)
                            {
                                propertyStorage.IsGSIHashKey = true;
                                propertyStorage.AddIndex(gsiHashAttribute);
                            }
                            else
                            {
                                propertyStorage.IsHashKey = true;
                            }
                        }
                        if (propertyAttribute is DynamoDBRangeKeyAttribute)
                        {
                            var gsiRangeAttribute = propertyAttribute as DynamoDBGlobalSecondaryIndexRangeKeyAttribute;
                            if (gsiRangeAttribute != null)
                            {
                                propertyStorage.IsGSIRangeKey = true;
                                propertyStorage.AddIndex(gsiRangeAttribute);
                            }
                            else
                            {
                                propertyStorage.IsRangeKey = true;
                            }
                        }

                        DynamoDBLocalSecondaryIndexRangeKeyAttribute lsiRangeKeyAttribute = propertyAttribute as DynamoDBLocalSecondaryIndexRangeKeyAttribute;
                        if (lsiRangeKeyAttribute != null)
                        {
                            propertyStorage.IsLSIRangeKey = true;
                            propertyStorage.AddIndex(lsiRangeKeyAttribute);
                        }
                    }
                }

                config.Properties.Add(propertyStorage);
            }
        }
Beispiel #2
0
 protected void AddPropertyStorage(string propertyName, PropertyStorage propertyStorage)
 {
     PropertyToPropertyStorageMapping[propertyName] = propertyStorage;
 }
Beispiel #3
0
 public bool TryGetPropertyStorage(string propertyName, out PropertyStorage storage)
 {
     return(PropertyToPropertyStorageMapping.TryGetValue(propertyName, out storage));
 }
Beispiel #4
0
        private bool FindSingleProperty(Func <PropertyStorage, bool> match, string errorMessage, out PropertyStorage propertyStorage)
        {
            var properties = Properties.Where(match).ToList();

            if (properties.Count == 0)
            {
                propertyStorage = null;
                return(false);
            }
            if (properties.Count == 1)
            {
                propertyStorage = properties[0];
                return(true);
            }

            throw new InvalidOperationException(errorMessage);
        }
Beispiel #5
0
        internal static ItemStorageConfig CreateStorageConfig(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            ItemStorageConfig config = new ItemStorageConfig(type);

            DynamoDBTableAttribute tableAttribute = Utils.GetTableAttribute(type);

            if (tableAttribute == null || string.IsNullOrEmpty(tableAttribute.TableName))
            {
                throw new InvalidOperationException("No DynamoDBTableAttribute on type");
            }

            if (string.IsNullOrEmpty(tableAttribute.TableName))
            {
                throw new InvalidOperationException("DynamoDBTableAttribute.Table is empty or null");
            }
            config.TableName = tableAttribute.TableName;
            config.LowerCamelCaseProperties = tableAttribute.LowerCamelCaseProperties;

            foreach (var member in type.GetMembers())
            {
                // filter out non-fields and non-properties
                if (!(member is FieldInfo || member is PropertyInfo))
                {
                    continue;
                }

                // filter out properties that aren't both read and write
                if (!Utils.IsReadWrite(member))
                {
                    continue;
                }

                DynamoDBAttribute attribute = Utils.GetAttribute(member);

                // filter out ignored properties
                if (attribute is DynamoDBIgnoreAttribute)
                {
                    continue;
                }

                Type   memberType    = Utils.GetType(member);
                string attributeName = GetAccurateCase(config, member.Name);
                string propertyName  = member.Name;

                PropertyStorage propertyStorage = new PropertyStorage
                {
                    Member     = member,
                    MemberType = memberType,
                };

                if (attribute is DynamoDBVersionAttribute)
                {
                    Utils.ValidateVersionType(memberType);    // no conversion is possible, so type must be a nullable primitive

                    propertyStorage.IsVersion = true;
                }

                DynamoDBPropertyAttribute propertyAttribute = attribute as DynamoDBPropertyAttribute;
                if (propertyAttribute != null)
                {
                    if (!string.IsNullOrEmpty(propertyAttribute.AttributeName))
                    {
                        attributeName = GetAccurateCase(config, propertyAttribute.AttributeName);
                    }

                    if (propertyAttribute is DynamoDBHashKeyAttribute)
                    {
                        if (propertyAttribute.Converter == null && !Utils.IsPrimitive(memberType))
                        {
                            throw new InvalidOperationException("Hash key " + propertyName + " must be of primitive type");
                        }

                        propertyStorage.IsHashKey = true;
                    }
                    if (propertyAttribute is DynamoDBRangeKeyAttribute)
                    {
                        if (propertyAttribute.Converter == null && !Utils.IsPrimitive(memberType))
                        {
                            throw new InvalidOperationException("Range key " + propertyName + " must be of primitive type");
                        }

                        propertyStorage.IsRangeKey = true;
                    }
                    if (propertyAttribute is DynamoDBLocalSecondaryIndexRangeKeyAttribute)
                    {
                        DynamoDBLocalSecondaryIndexRangeKeyAttribute lsiRangeKeyAttribute = propertyAttribute as DynamoDBLocalSecondaryIndexRangeKeyAttribute;
                        if (lsiRangeKeyAttribute.IndexNames == null || lsiRangeKeyAttribute.IndexNames.Length == 0)
                        {
                            throw new InvalidOperationException("Local Secondary Index must not be null or empty");
                        }
                        propertyStorage.Indexes.AddRange(lsiRangeKeyAttribute.IndexNames);
                    }

                    if (propertyAttribute.Converter != null)
                    {
                        if (!Utils.CanInstantiate(propertyAttribute.Converter) || !Utils.ImplementsInterface(propertyAttribute.Converter, typeof(IPropertyConverter)))
                        {
                            throw new InvalidOperationException("Converter for " + propertyName + " must be instantiable with no parameters and must implement IPropertyConverter");
                        }

                        propertyStorage.Converter = Utils.Instantiate(propertyAttribute.Converter) as IPropertyConverter;
                    }
                }

                propertyStorage.PropertyName  = propertyName;
                propertyStorage.AttributeName = attributeName;

                config.AddPropertyStorage(propertyStorage);
            }

            if (config.HashKeyPropertyNames.Count == 0)
            {
                throw new InvalidOperationException("No hash key configured for type " + type.FullName);
            }

            return(config);
        }
Beispiel #6
0
        private static List <AttributeValue> ConvertConditionValues(object[] conditionValues, PropertyStorage conditionProperty, bool canReturnPrimitiveInsteadOfList = false)
        {
            List <AttributeValue> attributeValues = new List <AttributeValue>();

            foreach (var conditionValue in conditionValues)
            {
                DynamoDBEntry  entry          = ToDynamoDBEntry(conditionProperty, conditionValue, canReturnPrimitiveInsteadOfList);
                AttributeValue attributeValue = entry.ConvertToAttributeValue();
                attributeValues.Add(attributeValue);
            }
            return(attributeValues);
        }
Beispiel #7
0
        // This method composes the query filter and determines the possible indexes that the filter
        // may be used against. In the case where the condition property is also a RANGE key on the
        // table and not just on LSI/GSI, the potential index will be "" (absent).
        private static QueryFilter ComposeQueryFilterHelper(
            DynamoDBFlatConfig currentConfig,
            Document hashKey,
            IEnumerable <QueryCondition> conditions,
            ItemStorageConfig storageConfig,
            out List <string> indexNames)
        {
            if (hashKey == null)
            {
                throw new ArgumentNullException("hashKey");
            }

            if (storageConfig.HashKeyPropertyNames.Count != 1)
            {
                throw new InvalidOperationException("Must have one hash key defined for the table " + storageConfig.TableName);
            }
            if (storageConfig.RangeKeyPropertyNames.Count != 1 && storageConfig.IndexNameToGSIMapping.Count == 0)
            {
                throw new InvalidOperationException("Must have one range key or a GSI index defined for the table " + storageConfig.TableName);
            }

            QueryFilter filter = new QueryFilter();

            // Configure hash-key equality condition
            string hashKeyProperty = storageConfig.HashKeyPropertyNames[0];

            hashKeyProperty = storageConfig.GetCorrectHashKeyProperty(currentConfig, hashKeyProperty);
            PropertyStorage propertyStorage = storageConfig.GetPropertyStorage(hashKeyProperty);
            string          attributeName   = propertyStorage.AttributeName;
            DynamoDBEntry   hashValue       = hashKey[attributeName];

            filter.AddCondition(attributeName, QueryOperator.Equal, hashValue);

            indexNames = new List <string>();
            if (conditions != null)
            {
                foreach (QueryCondition condition in conditions)
                {
                    object[]        conditionValues   = condition.Values;
                    PropertyStorage conditionProperty = storageConfig.GetPropertyStorage(condition.PropertyName);
                    if (conditionProperty.IsLSIRangeKey || conditionProperty.IsGSIKey)
                    {
                        indexNames.AddRange(conditionProperty.IndexNames);
                    }
                    if (conditionProperty.IsRangeKey)
                    {
                        indexNames.Add(NO_INDEX);
                    }
                    List <AttributeValue> attributeValues = ConvertConditionValues(conditionValues, conditionProperty);
                    filter.AddCondition(conditionProperty.AttributeName, condition.Operator, attributeValues);
                }
            }
            if (currentConfig.QueryFilter != null)
            {
                foreach (ScanCondition condition in currentConfig.QueryFilter)
                {
                    object[]              conditionValues   = condition.Values;
                    PropertyStorage       conditionProperty = storageConfig.GetPropertyStorage(condition.PropertyName);
                    List <AttributeValue> attributeValues   = ConvertConditionValues(conditionValues, conditionProperty, true);
                    filter.AddCondition(conditionProperty.AttributeName, condition.Operator, attributeValues);
                }
            }
            return(filter);
        }
Beispiel #8
0
 private static DynamoDBEntry ToDynamoDBEntry(PropertyStorage propertyStorage, object value)
 {
     return(ToDynamoDBEntry(propertyStorage, value, false));
 }
Beispiel #9
0
        // Key creation
        private static DynamoDBEntry ValueToDynamoDBEntry(PropertyStorage propertyStorage, object value)
        {
            var entry = ToDynamoDBEntry(propertyStorage, value);

            return(entry);
        }