/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (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/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* 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.Globalization;
using Amazon.DynamoDBv2.DataModel;
using Amazon.DynamoDBv2.DocumentModel;
using Amazon.Util.Internal;
#if NETSTANDARD
using Amazon.Runtime.Internal.Util;
#endif
namespace Amazon.DynamoDBv2
{
///
/// Available conversion schemas.
///
internal enum ConversionSchema
{
///
/// Default schema before 2014 L, M, BOOL, NULL support
///
/// The following .NET types are converted into the following DynamoDB types:
/// Number types (byte, int, float, decimal, etc.) are converted to N
/// String and char are converted to S
/// Bool is converted to N (0=false, 1=true)
/// DateTime and Guid are converto to S
/// MemoryStream and byte[] are converted to B
/// List, HashSet, and array of numerics types are converted to NS
/// List, HashSet, and array of string-based types are converted to SS
/// List, HashSet, and array of binary-based types are converted to BS
/// Dictionary{string,object} are converted to M
///
V1 = 0,
///
/// Schema fully supporting 2014 L, M, BOOL, NULL additions
///
/// The following .NET types are converted into the following DynamoDB types:
/// Number types (byte, int, float, decimal, etc.) are converted to N
/// String and char are converted to S
/// Bool is converted to BOOL
/// DateTime and Guid are converto to S
/// MemoryStream and byte[] are converted to B
/// HashSet of numerics types are converted to NS
/// HashSet of string-based types are converted to SS
/// HashSet of binary-based types are converted to BS
/// List and array of numerics, string-based types, and binary-based types
/// are converted to L type.
/// Dictionary{string,object} are converted to M
///
V2 = 1,
}
///
/// A collection of converters capable of converting between
/// .NET and DynamoDB objects.
///
public class DynamoDBEntryConversion
{
#region Static members
///
/// Default conversion before 2014 L, M, BOOL, NULL support.
///
/// The following .NET types are converted into the following DynamoDB types:
/// Number types (byte, int, float, decimal, etc.) are converted to N
/// String and char are converted to S
/// Bool is converted to N (0=false, 1=true)
/// DateTime and Guid are converto to S
/// MemoryStream and byte[] are converted to B
/// List, HashSet, and array of numerics types are converted to NS
/// List, HashSet, and array of string-based types are converted to SS
/// List, HashSet, and array of binary-based types are converted to BS
/// Dictionary{string,object} are converted to M
///
public static DynamoDBEntryConversion V1 { get; private set; }
///
/// Schema fully supporting 2014 L, M, BOOL, NULL additions.
///
/// The following .NET types are converted into the following DynamoDB types:
/// Number types (byte, int, float, decimal, etc.) are converted to N
/// String and char are converted to S
/// Bool is converted to BOOL
/// DateTime and Guid are converto to S
/// MemoryStream and byte[] are converted to B
/// HashSet of numerics types are converted to NS
/// HashSet of string-based types are converted to SS
/// HashSet of binary-based types are converted to BS
/// List and array of numerics, string-based types, and binary-based types
/// are converted to L type.
/// Dictionary{string,object} are converted to M
///
public static DynamoDBEntryConversion V2 { get; private set; }
///
/// Returns a DynamoDBEntryConversion corresponding to the ConversionSchema.
/// The returned conversion is immutable. The conversion must be cloned
/// before it can be modified.
///
/// Conversion to return.
/// DynamoDBEntryConversion corresponding to the ConversionSchema.
internal static DynamoDBEntryConversion GetConversion(ConversionSchema schema)
{
switch (schema)
{
case ConversionSchema.V1:
return DynamoDBEntryConversion.V1;
case ConversionSchema.V2:
return DynamoDBEntryConversion.V2;
default:
throw new ArgumentOutOfRangeException("schema");
}
}
///
/// Conversion corresponding to AWSConfigs.DynamoDBConfig.ConversionSchema
///
internal static DynamoDBEntryConversion CurrentConversion
{
get
{
return GetConversion(AWSConfigsDynamoDB.ConversionSchema);
}
}
#endregion
#region Constructors
static DynamoDBEntryConversion()
{
V1 = new DynamoDBEntryConversion(ConversionSchema.V1, isImmutable: true);
V2 = new DynamoDBEntryConversion(ConversionSchema.V2, isImmutable: true);
}
private DynamoDBEntryConversion(ConversionSchema schema, bool isImmutable)
{
OriginalConversion = schema;
switch (schema)
{
case ConversionSchema.V1:
SetV1Converters();
break;
case ConversionSchema.V2:
SetV2Converters();
break;
default:
throw new ArgumentOutOfRangeException("schema");
}
IsImmutable = isImmutable;
}
///
/// Creates an empty, mutable conversion.
///
internal DynamoDBEntryConversion()
{
OriginalConversion = ConversionSchema.V1;
}
#endregion
#region Public methods
///
/// Convert value to DynamoDBEntry
///
///
///
///
public DynamoDBEntry ConvertToEntry(TInput value)
{
DynamoDBEntry entry;
if (TryConvertToEntry(value, out entry))
return entry;
throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture,
"Unable to convert [{0}] of type {1} to DynamoDBEntry", value, value.GetType().FullName));
}
///
/// Convert value to DynamoDBEntry
///
///
///
///
public DynamoDBEntry ConvertToEntry(Type inputType, object value)
{
if (inputType == null) throw new ArgumentNullException("inputType");
if (value == null) throw new ArgumentNullException("value");
var converter = ConverterCache.GetConverter(inputType);
DynamoDBEntry output = converter.ToEntry(value);
return output;
}
///
/// Try to convert value to DynamoDBEntry. If it fails the method returns false.
///
///
///
///
/// True if successfully converted, otherwise false.
public bool TryConvertToEntry(TInput value, out DynamoDBEntry entry)
{
var inputType = typeof(TInput);
return TryConvertToEntry(inputType, value, out entry);
}
///
/// Try to convert value to DynamoDBEntry. If it fails the method returns false.
///
///
///
///
///
///
public bool TryConvertToEntry(Type inputType, object value, out DynamoDBEntry entry)
{
if (inputType == null) throw new ArgumentNullException("inputType");
if (value == null) throw new ArgumentNullException("value");
var converter = ConverterCache.GetConverter(inputType);
return converter.TryToEntry(value, out entry);
}
///
/// Convert the DynamoDBEntry to the specified type.
///
///
///
///
public TOutput ConvertFromEntry(DynamoDBEntry entry)
{
TOutput output;
if (TryConvertFromEntry(entry, out output))
return output;
throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture,
"Unable to convert [{0}] of type {1} to {2}", entry, entry.GetType().FullName, typeof(TOutput).FullName));
}
///
/// Convert the DynamoDBEntry to the specified type.
///
///
///
///
///
public object ConvertFromEntry(Type outputType, DynamoDBEntry entry)
{
if (outputType == null) throw new ArgumentNullException("outputType");
if (entry == null) throw new ArgumentNullException("entry");
var converter = ConverterCache.GetConverter(outputType);
object output = converter.FromEntry(entry, outputType);
return output;
}
///
/// Try to convert the DynamoDBEntry to the specified type. If it fails the method returns false.
///
///
///
///
/// True if successfully converted, otherwise false.
public bool TryConvertFromEntry(DynamoDBEntry entry, out TOutput output)
{
output = default(TOutput);
var outputType = typeof(TOutput);
object converted;
if (TryConvertFromEntry(outputType, entry, out converted))
{
if (converted != null)
output = (TOutput)converted;
return true;
}
return false;
}
///
/// Try to convert the DynamoDBEntry to the specified type. If it fails the method returns false.
///
///
///
///
///
///
public bool TryConvertFromEntry(Type outputType, DynamoDBEntry entry, out object value)
{
if (outputType == null) throw new ArgumentNullException("outputType");
if (entry == null) throw new ArgumentNullException("entry");
var converter = ConverterCache.GetConverter(outputType);
return converter.TryFromEntry(entry, outputType, out value);
}
#endregion
#region Internal members
internal bool IsImmutable { get; private set; }
internal DynamoDBEntryConversion Clone()
{
return new DynamoDBEntryConversion(this.OriginalConversion, isImmutable: false);
}
internal bool HasConverter(Type type)
{
return ConverterCache.HasConverter(type);
}
internal IEnumerable ConvertToEntries(Type elementType, IEnumerable values)
{
if (values == null) throw new ArgumentNullException("values");
foreach (var value in values)
yield return ConvertToEntry(elementType, value);
}
internal IEnumerable ConvertToEntries(IEnumerable values)
{
if (values == null) throw new ArgumentNullException("values");
var elementType = typeof(T);
foreach (var value in values)
yield return ConvertToEntry(elementType, value);
//foreach (var value in values)
// yield return ConvertToEntry(value);
}
internal IEnumerable