/*
* 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.Globalization;
using System.IO;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime.Internal.Util;
using Amazon.Util;
using System.Collections;
using System.Collections.Generic;
namespace Amazon.DynamoDBv2.DocumentModel
{
///
/// Enumerator describing type of DynamoDB data in a Primitive or PrimitiveList
///
public enum DynamoDBEntryType {
///
/// DynamoDB String type.
///
String,
///
/// DynamoDB Numeric type.
///
Numeric,
///
/// DynamoDB Binary type.
///
Binary
}
///
/// A DynamoDBEntry that represents a scalar DynamoDB type
///
public class Primitive : DynamoDBEntry, IEquatable
{
#region Private members
private static DynamoDBEntryConversion V1Conversion = DynamoDBEntryConversion.V1;
#endregion
#region Constructors
///
/// Constructs an empty Primitive
///
public Primitive()
: this(null, DynamoDBEntryType.String)
{
}
///
/// Constructs a Primitive with the specified value.
/// Value is stored as a string, not numeric.
///
/// Value of the Primitive
public Primitive(string value)
: this(value, DynamoDBEntryType.String)
{
}
///
/// Constructs a Primitive with the specified value
/// and specifies whether it should be stored as a number or not.
///
/// Value of the Primitive
///
/// Flag, set to true if value should be treated as a number instead of a string
///
public Primitive(string value, bool saveAsNumeric)
: this(value, saveAsNumeric ? DynamoDBEntryType.Numeric : DynamoDBEntryType.String)
{
}
///
/// Constructs a Binary Primitive with the specified MemoryStream value.
/// Note: Primitive's Value is set to the stream's ToArray() response.
///
/// Value of the Primitive
public Primitive(MemoryStream value)
: this(value.ToArray()) { }
///
/// Constructs a Binary Primitive with the specified byte[] value.
///
/// Value of the Primitive
public Primitive(byte[] value)
: this(value, DynamoDBEntryType.Binary) { }
internal Primitive(object value, DynamoDBEntryType type)
{
Value = value;
Type = type;
}
#endregion
#region Properties
///
/// Value of the Primitive.
/// If Type is String or Numeric, this property is a string.
/// If Type is Binary, this property is a byte array.
///
public object Value { get; set; }
///
/// Type of this primitive object
///
public DynamoDBEntryType Type { get; set; }
#endregion
#region Internal conversion methods
internal override AttributeValue ConvertToAttributeValue(AttributeConversionConfig conversionConfig)
{
if (this.Value == null)
return null;
if (conversionConfig.IsEmptyStringValueEnabled)
{
if (this.Type != DynamoDBEntryType.Binary && StringValue == null)
{
return null;
}
}
else
{
if (this.Type != DynamoDBEntryType.Binary && string.IsNullOrEmpty(this.StringValue))
{
return null;
}
}
AttributeValue attribute = new AttributeValue();
switch (this.Type)
{
case DynamoDBEntryType.Numeric:
attribute.N = StringValue;
break;
case DynamoDBEntryType.String:
attribute.S = StringValue;
break;
case DynamoDBEntryType.Binary:
byte[] bytes = (byte[])Value;
attribute.B = new MemoryStream(bytes);
break;
}
return attribute;
}
internal string StringValue
{
get
{
if (this.Type == DynamoDBEntryType.Numeric || this.Type == DynamoDBEntryType.String)
return this.Value as string;
return null;
}
}
#endregion
#region Explicit and Implicit conversions
///
/// Explicitly convert Primitive to Boolean
///
/// Boolean value of this object
public override Boolean AsBoolean()
{
return V1Conversion.ConvertFromEntry(this);
}
///
/// Implicitly convert Boolean to Primitive
///
/// Boolean data to convert
/// Primitive representing the data
public static implicit operator Primitive(Boolean data)
{
return V1Conversion.ConvertToEntry(data).AsPrimitive();
}
///
/// Explicitly convert Primitive to Boolean
///
/// Primitive to convert
/// Boolean value of Primitive
public static explicit operator Boolean(Primitive p)
{
return p.AsBoolean();
}
///
/// Explicitly convert Primitive to Byte
///
/// Byte value of this object
public override Byte AsByte()
{
return V1Conversion.ConvertFromEntry(this);
}
///
/// Implicitly convert Byte to Primitive
///
/// Byte data to convert
/// Primitive representing the data
public static implicit operator Primitive(Byte data)
{
return V1Conversion.ConvertToEntry(data).AsPrimitive();
}
///
/// Explicitly convert Primitive to Byte
///
/// Primitive to convert
/// Byte value of Primitive
public static explicit operator Byte(Primitive p)
{
return p.AsByte();
}
///
/// Explicitly convert Primitive to SByte
///
/// SByte value of this object
[CLSCompliant(false)]
public override SByte AsSByte()
{
return V1Conversion.ConvertFromEntry(this);
}
///
/// Implicitly convert SByte to Primitive
///
/// SByte data to convert
/// Primitive representing the data
[CLSCompliant(false)]
public static implicit operator Primitive(SByte data)
{
return V1Conversion.ConvertToEntry(data).AsPrimitive();
}
///
/// Explicitly convert Primitive to SByte
///
/// Primitive to convert
/// SByte value of Primitive
[CLSCompliant(false)]
public static explicit operator SByte(Primitive p)
{
return p.AsSByte();
}
///
/// Explicitly convert Primitive to UInt16
///
/// UInt16 value of this object
[CLSCompliant(false)]
public override UInt16 AsUShort()
{
return V1Conversion.ConvertFromEntry(this);
}
///
/// Implicitly convert UInt16 to Primitive
///
/// UInt16 data to convert
/// Primitive representing the data
[CLSCompliant(false)]
public static implicit operator Primitive(UInt16 data)
{
return V1Conversion.ConvertToEntry(data).AsPrimitive();
}
///
/// Explicitly convert Primitive to UInt16
///
/// Primitive to convert
/// UInt16 value of Primitive
[CLSCompliant(false)]
public static explicit operator UInt16(Primitive p)
{
return p.AsUShort();
}
///
/// Explicitly convert Primitive to Int16
///
/// Int16 value of this object
public override Int16 AsShort()
{
return V1Conversion.ConvertFromEntry(this);
}
///
/// Implicitly convert Int16 to Primitive
///
/// Int16 data to convert
/// Primitive representing the data
public static implicit operator Primitive(Int16 data)
{
return V1Conversion.ConvertToEntry(data).AsPrimitive();
}
///
/// Explicitly convert Primitive to Int16
///
/// Primitive to convert
/// Int16 value of Primitive
public static explicit operator Int16(Primitive p)
{
return p.AsShort();
}
///
/// Explicitly convert Primitive to UInt32
///
/// UInt32 value of this object
[CLSCompliant(false)]
public override UInt32 AsUInt()
{
return V1Conversion.ConvertFromEntry(this);
}
///
/// Implicitly convert UInt32 to Primitive
///
/// UInt32 data to convert
/// Primitive representing the data
[CLSCompliant(false)]
public static implicit operator Primitive(UInt32 data)
{
return V1Conversion.ConvertToEntry(data).AsPrimitive();
}
///
/// Explicitly convert Primitive to UInt32
///
/// Primitive to convert
/// UInt32 value of Primitive
[CLSCompliant(false)]
public static explicit operator UInt32(Primitive p)
{
return p.AsUInt();
}
///
/// Explicitly convert Primitive to Int32
///
/// Int32 value of this object
public override Int32 AsInt()
{
return V1Conversion.ConvertFromEntry(this);
}
///
/// Implicitly convert Int32 to Primitive
///
/// Int32 data to convert
/// Primitive representing the data
public static implicit operator Primitive(Int32 data)
{
return V1Conversion.ConvertToEntry(data).AsPrimitive();
}
///
/// Explicitly convert Primitive to Int32
///
/// Primitive to convert
/// Int32 value of Primitive
public static explicit operator Int32(Primitive p)
{
return p.AsInt();
}
///
/// Explicitly convert Primitive to UInt64
///
/// UInt64 value of this object
[CLSCompliant(false)]
public override UInt64 AsULong()
{
return V1Conversion.ConvertFromEntry(this);
}
///
/// Implicitly convert UInt64 to Primitive
///
/// UInt64 data to convert
/// Primitive representing the data
[CLSCompliant(false)]
public static implicit operator Primitive(UInt64 data)
{
return V1Conversion.ConvertToEntry(data).AsPrimitive();
}
///
/// Explicitly convert Primitive to UInt64
///
/// Primitive to convert
/// UInt64 value of Primitive
[CLSCompliant(false)]
public static explicit operator UInt64(Primitive p)
{
return p.AsULong();
}
///
/// Explicitly convert Primitive to Int64
///
/// Int64 value of this object
public override Int64 AsLong()
{
return V1Conversion.ConvertFromEntry(this);
}
///
/// Implicitly convert Int64 to Primitive
///
/// Int64 data to convert
/// Primitive representing the data
public static implicit operator Primitive(Int64 data)
{
return V1Conversion.ConvertToEntry(data).AsPrimitive();
}
///
/// Explicitly convert Primitive to Int64
///
/// Primitive to convert
/// Int64 value of Primitive
public static explicit operator Int64(Primitive p)
{
return p.AsLong();
}
///
/// Explicitly convert Primitive to Single
///
/// Single value of this object
public override Single AsSingle()
{
return V1Conversion.ConvertFromEntry(this);
}
///
/// Implicitly convert Single to Primitive
///
/// Single data to convert
/// Primitive representing the data
public static implicit operator Primitive(Single data)
{
return V1Conversion.ConvertToEntry(data).AsPrimitive();
}
///
/// Explicitly convert Primitive to Single
///
/// Primitive to convert
/// Single value of Primitive
public static explicit operator Single(Primitive p)
{
return p.AsSingle();
}
///
/// Explicitly convert Primitive to Double
///
/// Double value of this object
public override Double AsDouble()
{
return V1Conversion.ConvertFromEntry(this);
}
///
/// Implicitly convert Double to Primitive
///
/// Double data to convert
/// Primitive representing the data
public static implicit operator Primitive(Double data)
{
return V1Conversion.ConvertToEntry(data).AsPrimitive();
}
///
/// Explicitly convert Primitive to Double
///
/// Primitive to convert
/// Double value of Primitive
public static explicit operator Double(Primitive p)
{
return p.AsDouble();
}
///
/// Explicitly convert Primitive to Decimal
///
/// Decimal value of this object
public override Decimal AsDecimal()
{
return V1Conversion.ConvertFromEntry(this);
}
///
/// Implicitly convert Decimal to Primitive
///
/// Decimal data to convert
/// Primitive representing the data
public static implicit operator Primitive(Decimal data)
{
return V1Conversion.ConvertToEntry(data).AsPrimitive();
}
///
/// Explicitly convert Primitive to Decimal
///
/// Primitive to convert
/// Decimal value of Primitive
public static explicit operator Decimal(Primitive p)
{
return p.AsDecimal();
}
///
/// Explicitly convert Primitive to Char
///
/// Char value of this object
public override Char AsChar()
{
return V1Conversion.ConvertFromEntry(this);
}
///
/// Implicitly convert Char to Primitive
///
/// Char data to convert
/// Primitive representing the data
public static implicit operator Primitive(Char data)
{
return V1Conversion.ConvertToEntry(data).AsPrimitive();
}
///
/// Explicitly convert Primitive to Char
///
/// Primitive to convert
/// Char value of Primitive
public static explicit operator Char(Primitive p)
{
return p.AsChar();
}
///
/// Explicitly convert Primitive to String
///
/// String value of this object
public override String AsString()
{
return V1Conversion.ConvertFromEntry(this);
}
///
/// Implicitly convert String to Primitive
///
/// String data to convert
/// Primitive representing the data
public static implicit operator Primitive(String data)
{
return V1Conversion.ConvertToEntry(data).AsPrimitive();
}
///
/// Explicitly convert Primitive to String
///
/// Primitive to convert
/// String value of Primitive
public static implicit operator String(Primitive p)
{
return p.AsString();
}
///
/// Explicitly convert Primitive to DateTime
///
/// DateTime value of this object
public override DateTime AsDateTime()
{
return V1Conversion.ConvertFromEntry(this);
}
///
/// Implicitly convert DateTime to Primitive
///
/// DateTime data to convert
/// Primitive representing the data
public static implicit operator Primitive(DateTime data)
{
return V1Conversion.ConvertToEntry(data).AsPrimitive();
}
///
/// Explicitly convert Primitive to DateTime
///
/// Primitive to convert
/// DateTime value of Primitive
public static explicit operator DateTime(Primitive p)
{
return p.AsDateTime();
}
///
/// Explicitly convert Primitive to Guid
///
/// Guid value of this object
public override Guid AsGuid()
{
return V1Conversion.ConvertFromEntry(this);
}
///
/// Implicitly convert Guid to Primitive
///
/// Guid data to convert
/// Primitive representing the data
public static implicit operator Primitive(Guid data)
{
return V1Conversion.ConvertToEntry(data).AsPrimitive();
}
///
/// Explicitly convert Primitive to Guid
///
/// Primitive to convert
/// Guid value of Primitive
public static explicit operator Guid(Primitive p)
{
return p.AsGuid();
}
///
/// Explicitly convert Primitive to byte[]
///
/// byte[] value of this object
public override byte[] AsByteArray()
{
return V1Conversion.ConvertFromEntry(this);
}
///
/// Implicitly convert byte[] to Primitive
///
/// byte[] data to convert
/// Primitive representing the data
public static implicit operator Primitive(byte[] data)
{
return V1Conversion.ConvertToEntry(data).AsPrimitive();
}
///
/// Explicitly convert Primitive to byte[]
///
/// Primitive to convert
/// byte[] value of Primitive
public static explicit operator byte[](Primitive p)
{
return p.AsByteArray();
}
///
/// Explicitly convert Primitive to MemoryStream
///
/// MemoryStream value of this object
public override MemoryStream AsMemoryStream()
{
return V1Conversion.ConvertFromEntry(this);
}
///
/// Implicitly convert MemoryStream to Primitive
///
/// MemoryStream data to convert
/// Primitive representing the data
public static implicit operator Primitive(MemoryStream data)
{
return V1Conversion.ConvertToEntry(data).AsPrimitive();
}
///
/// Explicitly convert Primitive to MemoryStream
///
/// Primitive to convert
/// MemoryStream value of Primitive
public static explicit operator MemoryStream(Primitive p)
{
return p.AsMemoryStream();
}
#endregion
#region Public overrides
///
/// Implement the ToString method.
///
///
public override string ToString()
{
if (this.Value == null)
return string.Empty;
return this.Value.ToString();
}
///
/// Implement the Clone method.
///
///
public override object Clone()
{
return new Primitive(this.Value, this.Type);
}
///
/// Implement the GetHashCode method.
///
///
public override int GetHashCode()
{
var typeHashCode = this.Type.GetHashCode();
var valueHashCode = 0;
if (this.Value != null)
{
if (this.Type == DynamoDBEntryType.Numeric || this.Type == DynamoDBEntryType.String)
valueHashCode = this.Value.GetHashCode();
else if (this.Type == DynamoDBEntryType.Binary)
{
var bytes = this.Value as byte[];
if (bytes != null)
{
for (int i = 0; i < bytes.Length; i++)
{
byte b = bytes[i];
valueHashCode = Hashing.CombineHashes(valueHashCode, b.GetHashCode());
}
}
}
}
return Hashing.CombineHashes(typeHashCode, valueHashCode);
}
///
/// Implement the Equals method.
///
///
///
public override bool Equals(object obj)
{
Primitive entryOther = obj as Primitive;
if (entryOther == null)
return false;
if (this.Type != entryOther.Type)
return false;
if (this.Type == DynamoDBEntryType.Numeric || this.Type == DynamoDBEntryType.String)
{
return (string.Equals(this.StringValue, entryOther.StringValue));
}
else if (this.Type == DynamoDBEntryType.Binary)
{
byte[] thisByteArray = this.Value as byte[];
byte[] otherByteArray = entryOther.Value as byte[];
if (thisByteArray.Length != otherByteArray.Length)
return false;
for (int i = 0; i < thisByteArray.Length; i++)
{
if (thisByteArray[i] != otherByteArray[i])
return false;
}
return true;
}
else
{
return false;
}
}
#endregion
#region IEquatable Members
///
/// Implement the Equals method from the IEquatable interface.
///
///
///
public bool Equals(Primitive other)
{
return this.Equals((object)other);
}
#endregion
}
internal class PrimitiveEqualityComparer : IEqualityComparer
{
public static readonly PrimitiveEqualityComparer Default = new PrimitiveEqualityComparer();
public bool Equals(Primitive x, Primitive y)
{
if (x == null || y == null)
return (x == y);
return x.Equals(y);
}
public int GetHashCode(Primitive obj)
{
if (obj == null)
return 0;
return obj.GetHashCode();
}
}
internal class PrimitiveComparer : IComparer
{
public int Compare(Primitive x, Primitive y)
{
if (x.Type != y.Type)
return x.Type.CompareTo(y.Type);
if (x.Type == DynamoDBEntryType.Numeric || x.Type == DynamoDBEntryType.String)
{
return (string.Compare(x.StringValue, y.StringValue, StringComparison.Ordinal));
}
else if (x.Type == DynamoDBEntryType.Binary)
{
byte[] xByteArray = x.Value as byte[];
byte[] yByteArray = y.Value as byte[];
if (xByteArray.Length != yByteArray.Length)
return xByteArray.Length.CompareTo(yByteArray.Length);
for (int i = 0; i < xByteArray.Length; i++)
{
byte xb = xByteArray[i];
byte yb = yByteArray[i];
int byteCompare = xb.CompareTo(yb);
if (byteCompare != 0)
return byteCompare;
}
return 0;
}
else
{
throw new InvalidOperationException("Unknown type of Primitive: " + x.Type);
}
}
public static PrimitiveComparer Default = new PrimitiveComparer();
}
}