#@ template language="C#" inherits="BaseGenerator" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#
AddLicenseHeader();
#>
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.Text;
using System.IO;
using System.Net;
using Amazon.Runtime;
using Amazon.Runtime.Internal;
<#
if(this.StructureType == StructureType.Request && this.Operation.AuthType.HasValue)
{
#>
using Amazon.Runtime.Internal.Auth;
<#
}
#>
<#
if(this.Structure != null && (this.Structure.IsEvent || this.Structure.IsEventStream))
{
#>
using Amazon.Runtime.EventStreams;
using Amazon.Runtime.EventStreams.Internal;
<#
}
#>
namespace <#=this.Config.Namespace#>.Model
{
<#
if(this.StructureType == StructureType.Request)
this.FormatOperationRequestDocumentation(this.Operation);
else if (this.Operation != null && GeneratorHelpers.HasSuppressedResult(this.Operation))
this.FormatVoidResultDocumentation(this.Operation.Name);
else if(this.StructureType == StructureType.Response && (this.Structure == null || string.IsNullOrEmpty(this.Structure.Documentation)))
{
#>
///
/// This is the response object from the <#=this.Operation.Name#> operation.
///
<#
}
else
this.FormatClassDocumentation(this.Structure);
#>
<#
if(this.Structure != null && this.Structure.IsDeprecated)
{
#>
[Obsolete("<#=this.Structure.DeprecationMessage#>")]
<#
}
if(this.Structure is ExceptionShape)
{
#>
#if !NETSTANDARD
[Serializable]
#endif
<#
}
#>
<#
if(this.Structure != null && this.Structure.IsEventStream)
{ // top if block
#>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1710:Identifiers should have correct suffix", Justification = "<#=this.Structure.Name#>Collection is not descriptive")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063", Justification = "IDisposable is a transient interface from IEventStream. Users need to be able to call Dispose.")]
public sealed class <#=this.Structure.Name#> : EnumerableEventStreamEventStreamException>
{
///summary>
///The mapping of event message to a generator function to construct the matching EventStream event
///
protected override IDictionary> EventMapping {get;} =
new Dictionary>
{
<#
foreach(var member in this.Structure.Members)
{
if(member.ModelShape.IsEvent)
{
#>
{"<#=member.PropertyName#>", payload => new <#=member.DetermineType()#>(payload)},
<#
}
}
#>
};
///
/// The mapping of event message to a generator function to construct the matching EventStream Exception
///
protected override IDictionaryEventStreamException>> ExceptionMapping {get;} =
new DictionaryEventStreamException>>
{
};
// Backing by a volatile bool. The flag only changes one way, so no need for a lock.
// This is located in the subclass to be CLS compliant.
private volatile bool _isProcessing;
///
/// Whether the backround processing loop is running.
///
protected override bool IsProcessing
{
get { return _isProcessing; }
set { _isProcessing = value; }
}
public override event EventHandler> EventReceived;
public override event EventHandlerEventStreamException>> ExceptionReceived;
<#
foreach(var member in this.Structure.Members)
{
if(member.ModelShape.IsEvent)
{
#>
///
///Raised when an <#=member.PropertyName#> event is received
///
public event EventHandler>> <#=member.PropertyName#>Received;
<#
}
}
#>
public <#=this.Structure.Name#>(Stream stream) : this (stream, null)
{
}
public <#=this.Structure.Name#>(Stream stream, IEventStreamDecoder eventStreamDecoder) : base(stream, eventStreamDecoder)
{
base.EventReceived += (sender,args) => EventReceived?.Invoke(this, args);
base.ExceptionReceived += (sender,args) => ExceptionReceived?.Invoke(this, args);
//Mapping the generic Event to more specific Events
Decoder.MessageReceived += (sender, args) =>
{
IEventStreamEvent ev;
try
{
ev = ConvertMessageToEvent(args.Message);
}
catch(UnknownEventStreamException)
{
throw new UnknownEventStreamException("Received an unknown event stream type");
}
EventReceived?.Invoke(this, new EventStreamEventReceivedArgs(ev));
//Call RaiseEvent until it returns true or all calls complete. This way only a subset of casts is perfromed
// and we can avoid a cascade of nested if else statements. The result is thrown away
var _ =
<#
var eventMembers = this.Structure.Members.Where(m => m.ModelShape.IsEvent).ToArray();
if(eventMembers.Length == 1)
{
#>
RaiseEvent(<#=eventMembers[0].PropertyName#>Received,ev);
<#
}
else if (eventMembers.Length > 1)
{
for(int i = 0; i < eventMembers.Length - 1; i++)
{
#>
RaiseEvent(<#=eventMembers[i].PropertyName#>Received,ev) ||
<#
}
#>
RaiseEvent(<#=eventMembers.Last().PropertyName#>Received,ev);
<#
}
#>
};
}
private bool RaiseEvent(EventHandler> eventHandler, IEventStreamEvent ev) where T : class, IEventStreamEvent
{
var convertedEvent = ev as T;
if (convertedEvent != null)
{
eventHandler?.Invoke(this, new EventStreamEventReceivedArgs(convertedEvent));
return true;
}
return false;
}
<#
}
#>
<#
bool hasStreamingMember = this.Structure?.Members.Any(member => member.IsStreaming) ?? false;
bool structureContainsEventPayload = this.Structure?.Members.Any(member => member.IsEventPayload) ?? false;
Member payloadMember = null;
if(structureContainsEventPayload)
{
payloadMember = this.Structure?.Members.Single(member => member.IsEventPayload);
}
bool structureIsNotEventStream = this.Structure != null && !this.Structure.IsEventStream;
bool structureIsEvent = this.Structure != null && this.Structure.IsEvent;
if (structureIsNotEventStream && this.StructureType == StructureType.Response && hasStreamingMember)
{
#>
public partial class <#=this.ClassName#><#=this.BaseClassString#>, IDisposable
{
<#
}
else
{
#>
<#
if( (this.Structure == null) || (structureIsNotEventStream))
{
#>
public partial class <#=this.ClassName#><#=this.BaseClassString#>
<#
if(structureIsEvent)
{
#>
: IEventStreamEvent
<#
}
#>
<#
if(structureIsEvent && !structureContainsEventPayload)
{
#>
,IEventStreamTerminalEvent
<#
}
#>
{
<#
}
#>
<#
}
#>
<#
if(structureIsEvent)
{
#>
public <#= Structure.Name#>()
{
}
public <#=Structure.Name#>(IEventStreamMessage message)
{
<#
if(structureContainsEventPayload)
{
#>
<#=payloadMember.PropertyName#> = new <#=payloadMember.DetermineType()#>(message.Payload);
<#
}
#>
}
<#
}
#>
<#
if(structureIsNotEventStream)
{
if(this.IsWrapped)
{
#>
private <#=this.Structure.Name#> _response;
///
/// Gets and sets the <#=this.Structure.Name#> property.
///
public <#=this.Structure.Name#> <#=this.Structure.Name#>
{
get { return this._response; }
set { this._response = value; }
}
<#
}
else
{
foreach(var member in this.Structure.Members)
{
if (member.IsExcluded)
continue;
#>
private <#=member.DetermineType()#><#= member.IsNullable ? "?" : "" #> <#=member.VariableName#><#= member.ShouldInstantiate ? string.Format(" = new {0}();", member.DetermineType()) : ";"#>
<#
}
#>
<#
AddSimpleRequestConstructors(this.ClassName, this.Structure, this.Config.Namespace);
if(this.Structure is ExceptionShape)
{
var exceptionShape = (ExceptionShape)this.Structure;
if (exceptionShape.IsRetryable)
{
#>
private RetryableDetails _retryableDetails = new RetryableDetails(<#=exceptionShape.Throttling.ToString().ToLower()#>);
<#
#>
<#
}
#>
<#@ include file=".\Exceptions\ExceptionConstructors.t4" once="true" #>
<#@ include file=".\Exceptions\ExceptionSerialization.t4" once="true" #>
<#
}
foreach(var member in this.Structure.Members)
{
if (member.IsExcluded)
continue;
#>
<# this.FormatPropertyDocumentation(member); #>
<#
if(member.IsDeprecated)
{
#>
[Obsolete("<#=member.DeprecationMessage#>")]
<#
}
var propertyAttributes = new List();
if(member.IsRequired && !member.IsIdempotent)
{
propertyAttributes.Add("Required=true");
}
if (member.Shape.Sensitive)
{
propertyAttributes.Add("Sensitive=true");
}
if (member.Shape.Min.HasValue)
{
propertyAttributes.Add("Min=" + member.Shape.Min);
}
if (member.Shape.Max.HasValue)
{
propertyAttributes.Add("Max=" + member.Shape.Max);
}
if (propertyAttributes.Count > 0)
{
#>
[AWSProperty(<#=string.Join(", ", propertyAttributes)#>)]
<#
}
#>
<#=member.AccessModifier#> <#=member.DetermineType()#><#=member.UseNullable ? "?" : ""#> <#=member.PropertyName#>
{
<#
if(member.IsNullable && !member.UseNullable)
{
#>
get { return this.<#=member.VariableName#>.GetValueOrDefault(); }
<#
}
else
{
#>
get { return this.<#=member.VariableName#>; }
<#
}
#>
set { <#=member.IsBackwardsCompatibleDateTimeProperty ? "this." + member.BackwardCompatibilityVariableName + " = " : ""#>this.<#=member.VariableName#> = value; }
}
<#
if (member.EmitIsSetProperties)
{
#>
///
/// This property is set to true if the property
/// is set; false otherwise.
/// This property can be used to determine if the related property
/// was returned by a service response or if the related property
/// should be sent to the service during a service call.
///
///
/// True if the related property was set or will be sent to a service; false otherwise.
///
<#
if(member.IsDeprecated)
{
#>
[Obsolete("<#=member.DeprecationMessage#>")]
<#
}
#>
public bool Is<#=member.PropertyName#>Set
{
get
{
return Amazon.Util.Internal.InternalSDKUtils.GetIsSet(this.<#=member.VariableName#>);
}
set
{
Amazon.Util.Internal.InternalSDKUtils.SetIsSet(value, ref this.<#=member.VariableName#>);
<#
if(member.IsBackwardsCompatibleDateTimeProperty)
{
#>
Amazon.Util.Internal.InternalSDKUtils.SetIsSet(value, ref this.<#=member.BackwardCompatibilityVariableName#>);
<#
}
#>
}
}
<#
}
#>
// Check to see if <#=member.PropertyName#> property is set
internal bool IsSet<#=member.PropertyName#>()
{
<#
if (member.EmitIsSetProperties)
{
#>
return this.Is<#=member.PropertyName#>Set;
<#
}
else if (member.IsNullable)
{
#>
return this.<#=member.VariableName#>.HasValue;
<#
}
else if (member.IsMap || member.IsList)
{
#>
return this.<#=member.VariableName#> != null && this.<#=member.VariableName#>.Count > 0;
<#
}
else if (member.IsDocument)
{
#>
return !this.<#=member.VariableName#>.IsNull();
<#
}
else
{
#>
return this.<#=member.VariableName#> != null;
<#
}
#>
}
<#
}
if (this.StructureType == StructureType.Request && this.Operation.AuthType.HasValue)
{
#>
///
/// Get the signer to use for this request.
///
/// A signer for this request.
override protected AbstractAWSSigner CreateSigner()
{
<#
switch (this.Operation.AuthType.Value)
{
case OperationAuthType.None:
#>
return new NullSigner();
<#
break;
case OperationAuthType.V4:
#>
return new AWS4Signer();
<#
break;
case OperationAuthType.V4UnsignedBody:
#>
return new AWS4Signer(false);
<#
break;
case OperationAuthType.Bearer:
#>
return new BearerTokenSigner();
<#
break;
default:
throw new ArgumentException("Unhandled value for operation authtype:" + this.Operation.AuthType.Value);
}
#>
}
<#
}
// Flexible checksum overrides to allow response validation configuration on the request
if (this.StructureType == StructureType.Request && !string.IsNullOrEmpty(this.Operation.ChecksumConfiguration?.RequestValidationModeMember))
{
#>
#region Flexible checksum properties
///
/// This must be enabled to retrieve the checksum
///
protected override CoreChecksumResponseBehavior CoreChecksumMode
{
get
{
if (IsSet<#=this.Operation.ChecksumConfiguration.RequestValidationModeMember#>())
{
return (CoreChecksumResponseBehavior)Enum.Parse(typeof(CoreChecksumResponseBehavior), this.<#=this.Operation.ChecksumConfiguration.RequestValidationModeMember#>);
}
return CoreChecksumResponseBehavior.DISABLED;
}
}
private static List _supportedChecksumAlgorithms = new List
{
<#= string.Join(", ", Operation.ChecksumConfiguration?.ResponseAlgorithms?.Select(s => $"CoreChecksumAlgorithm.{s}").ToArray()) #>
};
///
/// Checksum algorithms supported by this operation for response validation
///
protected override System.Collections.ObjectModel.ReadOnlyCollection ChecksumResponseAlgorithms => _supportedChecksumAlgorithms.AsReadOnly();
#endregion
<#
}
if (this.Structure.Members.Any(m => !m.IsExcluded && m.IsBackwardsCompatibleDateTimeProperty))
{
#>
#region Backwards compatible properties
<#
foreach(var member in this.Structure.Members)
{
if (member.IsExcluded || !member.IsBackwardsCompatibleDateTimeProperty)
continue;
#>
private <#=member.DetermineType()#><#= member.IsNullable ? "?" : "" #> <#=member.BackwardCompatibilityVariableName#><#= member.ShouldInstantiate ? string.Format(" = new {0}();", member.DetermineType()) : ";"#>
<#
}
#>
<#
foreach(var member in this.Structure.Members)
{
if (member.IsExcluded || !member.IsBackwardsCompatibleDateTimeProperty)
continue;
#>
<# this.FormatPropertyDocumentation(member, "This property is deprecated. Setting this property results in non-UTC DateTimes " +
"not being marshalled correctly. Use " + member.PropertyName + " instead. Setting either " + member.BackwardCompatibilityPropertyName +
" or " + member.PropertyName + " results in both " + member.BackwardCompatibilityPropertyName + " and " +
member.PropertyName + " being assigned, the latest assignment to either one of the two property is reflected in " +
"the value of both. " + member.BackwardCompatibilityPropertyName + " is provided for backwards compatibility only " +
"and assigning a non-Utc DateTime to it results in the wrong timestamp being passed to the service.");#>
[Obsolete("Setting this property results in non-UTC DateTimes not being marshalled correctly. " +
"Use <#=member.PropertyName#> instead. Setting either <#=member.BackwardCompatibilityPropertyName#> or <#=member.PropertyName#> results in both <#=member.BackwardCompatibilityPropertyName#> and " +
"<#=member.PropertyName#> being assigned, the latest assignment to either one of the two property is " +
"reflected in the value of both. <#=member.BackwardCompatibilityPropertyName#> is provided for backwards compatibility only and " +
"assigning a non-Utc DateTime to it results in the wrong timestamp being passed to the service.", false)]
<#=member.AccessModifier#> <#=member.DetermineType()#><#=member.UseNullable ? "?" : ""#> <#=member.BackwardCompatibilityPropertyName#>
{
get { return this.<#=member.BackwardCompatibilityVariableName#>.GetValueOrDefault(); }
set
{
this.<#=member.BackwardCompatibilityVariableName#> = value;
this.<#=member.VariableName#> = new DateTime(value.Ticks, DateTimeKind.Utc);
}
}
<#
if (member.EmitIsSetProperties)
{
#>
///
/// This property is set to true if the property
/// is set; false otherwise.
/// This property can be used to determine if the related property
/// was returned by a service response or if the related property
/// should be sent to the service during a service call.
///
///
/// True if the related property was set or will be sent to a service; false otherwise.
///
[Obsolete("Setting <#=member.BackwardCompatibilityPropertyName#> results in non-UTC DateTimes not being marshalled correctly. Use <#=member.PropertyName#> instead.", false)]
public bool Is<#=member.BackwardCompatibilityPropertyName#>Set
{
get
{
return this.Is<#=member.PropertyName#>Set;
}
set
{
this.Is<#=member.PropertyName#>Set = value;;
}
}
<#
}
}
#>
#endregion
<#
}
if (this.Structure is ExceptionShape)
{
var exceptionShape = (ExceptionShape)this.Structure;
if (exceptionShape.IsRetryable)
{
#>
///
/// Flag indicating if the exception is retryable and the associated retry
/// details. A null value indicates that the exception is not retryable.
///
public override RetryableDetails Retryable
{
get
{
return _retryableDetails;
}
}
<#
}
}
}
}
else //TODO: remove this else clause. It was added just to preserve whitespaces
{
#>
<#
}
if (this.StructureType == StructureType.Response && hasStreamingMember)
{
#>
#region Dispose Pattern
private bool _disposed;
///
/// Disposes of all managed and unmanaged resources.
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
<#
if (this.Structure != null)
{
foreach (var member in this.Structure.Members)
{
if (member.IsStreaming)
{
#>
this.<#=member.VariableName#>?.Dispose();
this.<#=member.VariableName#> = null;
<#
}
}
}
#>
}
this._disposed = true;
}
#endregion
<#
}
#>
}
}
<#+
// Set to true when the service model specifies a shape that should be wrapped in a response. ElastiCache CreateCacheCluster is an example of this.
public bool IsWrapped { get; set; }
public Operation Operation { get; set; }
public string ClassName { get; set; }
public string BaseClass { get; set; }
public Shape Structure { get; set; }
public StructureType StructureType { get; set; }
#>