/// <summary> /// Inspects list member to determine if the original list shape in the model has been /// substituted and if so, whether a member suffix should be used to extract the value /// for use in the query. An example usage would be the replacement of IpRange (in EC2) /// within an IpRangeList - we treat as a list of strings, yet need to get to the /// IpRange.CidrIp member in the query marshalling. Note that we also have some EC2 /// operations where we don't want this submember extraction too even though the /// same substitite is in use. /// </summary> /// <param name="member"></param> /// <returns></returns> public static string DetermineAWSQueryListMemberSuffix(Operation operation, Member member) { if (member.Shape.ModelListShape == null) return null; string suffixMember = null; var substituteShapeData = member.model.Customizations.GetSubstituteShapeData(member.ModelShape.ModelListShape.Name); if (substituteShapeData != null && substituteShapeData[CustomizationsModel.EmitFromMemberKey] != null) { var useSuffix = true; if (substituteShapeData[CustomizationsModel.ListMemberSuffixExclusionsKey] != null) { var exclusions = substituteShapeData[CustomizationsModel.ListMemberSuffixExclusionsKey]; foreach (JsonData excl in exclusions) { if (string.Equals(operation.Name, (string)excl, StringComparison.Ordinal)) { useSuffix = false; break; } } } if (useSuffix) suffixMember = (string)substituteShapeData[CustomizationsModel.EmitFromMemberKey]; } return suffixMember; }
// The "locationName" must always be lower-cased (first letter only) when used with EC2's // variant of AWSQuery. MarshallLocationName isn't consistently set. public static string DetermineAWSQueryBaseUnmarshallName(Member member) { if (!member.model.IsEC2Protocol) return member.MarshallName; var baseExpression = string.IsNullOrEmpty(member.MarshallLocationName) ? member.MarshallName : member.MarshallLocationName; return TransformUnmarshallLocationName(true, baseExpression); }
// List members in EC2 are always considered flattened, so we drop the 'member' prefix public static string DetermineAWSQueryListMemberPrefix(Member member) { if (member.model.IsEC2Protocol || member.Shape.IsFlattened) return string.Empty; if (member.Shape.IsList) return "member"; if (member.Shape.IsMap) return "entry"; throw new Exception("Unknown member type for list member prefix determination"); }
// returns the unmarshall expression for a member public static string DetermineAWSQueryTestExpression(Member member) { var isEC2Protocol = member.model.IsEC2Protocol; var testExpression = DetermineAWSQueryBaseUnmarshallName(member); if (member.IsList) { if (!member.Shape.IsFlattened) { testExpression += "/"; if (member.Shape.ListMarshallName != null) testExpression += member.Shape.ListMarshallName; else testExpression += "member"; // If the list element shape has a customization replacing it // with another shape, extend the expression with any subexpression // to the value member that the replaced shape has. This allows us to // handle collections of EC2's AttributeValue shape which is replaced // by a 'string' and we unmarshall the collection using the shape's 'value' // member. var listShape = member.Shape.ModelListShape; var substituteShapeData = member.model.Customizations.GetSubstituteShapeData(listShape.Name); if (substituteShapeData != null) { if (substituteShapeData[CustomizationsModel.EmitFromMemberKey] != null) { var valueMember = (string)substituteShapeData[CustomizationsModel.EmitFromMemberKey]; if (isEC2Protocol) testExpression += "/" + TransformUnmarshallLocationName(true, valueMember); else testExpression += "/" + valueMember; } else { if (listShape.ValueMarshallName != null) testExpression += "/" + listShape.ValueMarshallName; } } } else { testExpression = member.Shape.ListMarshallName; } } else if (member.IsMap) { if (!member.Shape.IsFlattened) testExpression += "/entry"; } else { var substituteShapeData = member.model.Customizations.GetSubstituteShapeData(member.ModelShape.Name); if (substituteShapeData != null && substituteShapeData[CustomizationsModel.EmitFromMemberKey] != null) { var valueMember = (string)substituteShapeData[CustomizationsModel.EmitFromMemberKey]; var subMember = member.ModelShape.Members.Single(m => m.PropertyName.Equals(valueMember, StringComparison.Ordinal)); var subExpression = string.IsNullOrEmpty(subMember.MarshallLocationName) ? subMember.MarshallName : subMember.MarshallLocationName; if (!string.IsNullOrEmpty(subExpression)) testExpression += "/" + subExpression; } } return testExpression; }
// The marshal name must always be up-cased (first letter only) when used with EC2's // variant of AWSQuery. We can also apply operation-specific customizations for marshal // names public static string DetermineAWSQueryMarshallName(Member member, Operation operation) { var isEC2Protocol = member.model.IsEC2Protocol; CustomizationsModel.OperationModifiers modifiers = null; if (operation != null) modifiers = operation.OperationModifiers; var marshallName = new StringBuilder(); if (modifiers != null) { var marshallOverride = modifiers.GetMarshallNameOverrides(member.OwningShape.Name, member.PropertyName); if (marshallOverride != null) { var marshallOverrideName = !isEC2Protocol ? marshallOverride.MarshallName : (string.IsNullOrEmpty(marshallOverride.MarshallLocationName) ? marshallOverride.MarshallName : marshallOverride.MarshallLocationName); marshallName.Append(TransformMarshallLocationName(isEC2Protocol, marshallOverrideName)); } } // if the operation didn't override the marshal location, is there a property modifier doing so? if (marshallName.Length == 0 && member.PropertyModifier != null) { var locationName = TransformMarshallLocationName(isEC2Protocol, member.PropertyModifier.LocationName); marshallName.Append(locationName); } // if the marshal name still isn't set, fall back to the model if (marshallName.Length == 0) { var modelMarshallName = !isEC2Protocol ? member.MarshallName : (string.IsNullOrEmpty(member.MarshallLocationName) ? member.MarshallName : member.MarshallLocationName); marshallName.Append(TransformMarshallLocationName(isEC2Protocol, modelMarshallName)); } // also check if we need to emit from a submember as a result of shape substitution var substituteShapeData = member.model.Customizations.GetSubstituteShapeData(member.ModelShape.Name); if (substituteShapeData != null && substituteShapeData[CustomizationsModel.EmitFromMemberKey] != null) { var valueMember = (string) substituteShapeData[CustomizationsModel.EmitFromMemberKey]; var subMember = member.ModelShape.Members.Single(m => m.PropertyName.Equals(valueMember, StringComparison.Ordinal)); if (subMember != null) { var subExpression = string.IsNullOrEmpty(subMember.MarshallLocationName) ? subMember.MarshallName : subMember.MarshallLocationName; marshallName.AppendFormat(".{0}", TransformMarshallLocationName(isEC2Protocol, subExpression)); } } return marshallName.ToString(); }
/// <summary> /// Determines if a property modifier for the member is suppressing automatic marshall /// generation code for the field. If true, custom code in the pipeline will handle the /// member. /// </summary> /// <param name="member"></param> /// <param name="operation"></param> /// <returns></returns> public static bool UseCustomMarshall(Member member, Operation operation) { if (member.PropertyModifier != null && member.PropertyModifier.IsSetUseCustomMarshall) return member.PropertyModifier.UseCustomMarshall; if (member.PropertyInjector != null && member.PropertyInjector.IsSetUseCustomMarshall) return member.PropertyInjector.UseCustomMarshall; return false; }
private void ValidateProperty(string parameterBase, Type type, object propertyValue, string propertyName, Member member) { if (IsScalarValue(type)) { var key = parameterBase; if (!string.IsNullOrEmpty(key)) key += "."; key += GeneratorHelpers.DetermineAWSQueryMarshallName(member, this.Operation); Assert.IsTrue(this.Parameters.ContainsKey(key), "Failed to find query key " + key); } else { if (type.GetInterface("System.Collections.IList") != null) { var list = propertyValue as System.Collections.IList; for (var i = 0; i < list.Count; i++) { var item = list[i]; var queryKey = ConstructMemberQueryKey(parameterBase, member, i+1); if (IsScalarValue(item.GetType())) { Assert.IsTrue(this.Parameters.ContainsKey(queryKey), "Failed to find query key " + queryKey); } else { Validate(queryKey, item, member.Shape.ListShape); } } } else if (type.GetInterface("System.Collections.IDictionary") != null) { var map = propertyValue as System.Collections.IDictionary; var i = 1; foreach (var key in map.Keys) { object value = map[key]; var queryKey = ConstructMemberQueryKey(parameterBase, member, i); Assert.IsTrue(this.Parameters.ContainsKey(queryKey + "." + member.Shape.KeyMarshallName), "Failed to find query key " + queryKey + "." + member.Shape.KeyMarshallName); if (IsScalarValue(value.GetType())) { Assert.IsTrue(this.Parameters.ContainsKey(queryKey + "." + member.Shape.ValueMarshallName), "Failed to find query key " + queryKey + "." + member.Shape.ValueMarshallName); } else { Validate(queryKey + "." + member.Shape.ValueMarshallName, value, member.Shape.ValueShape); } i++; } } else { var key = parameterBase; if (!string.IsNullOrEmpty(key)) key += "."; key += GeneratorHelpers.DetermineAWSQueryMarshallName(member, this.Operation); Validate(key, propertyValue, member.Shape); } } }
private string ConstructMemberQueryKey(string parameterBase, Member member, int memberIndex) { var queryKey = new StringBuilder(parameterBase); if (queryKey.Length > 0) queryKey.Append("."); queryKey.AppendFormat("{0}.", GeneratorHelpers.DetermineAWSQueryMarshallName(member, this.Operation)); var memberPrefix = GeneratorHelpers.DetermineAWSQueryListMemberPrefix(member); // can return empty for EC2/AWSQuery if (!string.IsNullOrEmpty(memberPrefix)) queryKey.AppendFormat("{0}.", memberPrefix); queryKey.Append(memberIndex); var memberSuffix = GeneratorHelpers.DetermineAWSQueryListMemberSuffix(this.Operation, member); if (memberSuffix != null) queryKey.AppendFormat(".{0}", memberSuffix); return queryKey.ToString(); }
/// <summary> /// Given a member and sample data, build a literal/instantation for the /// member's type with the sample data. /// </summary> /// <param name="member">The member in the model</param> /// <param name="data">Sample data to populate the literal with</param> /// <param name="cb">A CodeBuilder instance to write the code to.</param> public void GetSampleLiteral(Member member, JsonData data, CodeBuilder cb) { GetSampleLiteral(member.Shape, data, cb); }
private void WriteArray(XmlWriter writer, Member member, Shape shape) { if (!shape.IsFlattened) { writer.WriteStartElement(GeneratorHelpers.DetermineAWSQueryBaseUnmarshallName(member)); } for (int i = 0; i < shape.Name.Length % 5 + 2; i++) { writer.WriteStartElement(shape.ListMarshallName ?? "member"); Write(writer, shape.ModelListShape); writer.WriteEndElement(); } if (!shape.IsFlattened) writer.WriteEndElement(); }
/// <summary> /// Create a new OperationPaginatorConfigOption object /// and set whether or not it is a jmespath expression /// </summary> /// <param name="isJmesPath"> Whether or not it is a jmespath expression </param> /// <param name="member"> Member associated with the option </param> public OperationPaginatorConfigOption(bool isJmesPath, Member member) { IsJmesPath = isJmesPath; Member = member; }
/// <summary> /// Create a new OperationPaginatorConfigOption object /// and set whether or not it is a jmespath expression /// </summary> /// <param name="isJmesPath"> Whether or not it is a jmespath expression </param> /// <param name="member"> Member associated with the option </param> /// <param name="wrappedResultMember">If the result of this operation is wrapped in a response /// object. (workaround for SimpleWorkFlow) </param> public OperationPaginatorConfigOption(bool isJmesPath, string wrappedResultMember, Member member) : this(isJmesPath, member) { WrappedResultMember = wrappedResultMember; }
/// <summary> /// Create a new OperationPaginatorConfigOption object /// and set whether or not it is a jmespath expression /// </summary> /// <param name="isJmesPath"> Whether or not it is a jmespath expression </param> /// <param name="member"> Member associated with the option </param> /// <param name="name"> String name of the option as found in paginator config </param> public OperationPaginatorConfigOption(bool isJmesPath, Member member, string name) : this(isJmesPath, member) { Name = name; }
// returns the unmarshall expression for a member public static string DetermineAWSQueryTestExpression(Member member) { var isEC2Protocol = member.model.IsEC2Protocol; var testExpression = DetermineAWSQueryBaseUnmarshallName(member); if (member.IsList) { if (!member.Shape.IsFlattened) { testExpression += "/"; if (member.Shape.ListMarshallName != null) { testExpression += member.Shape.ListMarshallName; } else { testExpression += "member"; } // If the list element shape has a customization replacing it // with another shape, extend the expression with any subexpression // to the value member that the replaced shape has. This allows us to // handle collections of EC2's AttributeValue shape which is replaced // by a 'string' and we unmarshall the collection using the shape's 'value' // member. var listShape = member.Shape.ModelListShape; var substituteShapeData = member.model.Customizations.GetSubstituteShapeData(listShape.Name); if (substituteShapeData != null) { if (substituteShapeData[CustomizationsModel.EmitFromMemberKey] != null) { var valueMember = (string)substituteShapeData[CustomizationsModel.EmitFromMemberKey]; if (isEC2Protocol) { testExpression += "/" + TransformUnmarshallLocationName(true, valueMember); } else { testExpression += "/" + valueMember; } } else { if (listShape.ValueMarshallName != null) { testExpression += "/" + listShape.ValueMarshallName; } } } } else { testExpression = member.Shape.ListMarshallName; } } else if (member.IsMap) { if (!member.Shape.IsFlattened) { testExpression += "/entry"; } } else { var substituteShapeData = member.model.Customizations.GetSubstituteShapeData(member.ModelShape.Name); if (substituteShapeData != null && substituteShapeData[CustomizationsModel.EmitFromMemberKey] != null) { var valueMember = (string)substituteShapeData[CustomizationsModel.EmitFromMemberKey]; var subMember = member.ModelShape.Members.Single(m => m.PropertyName.Equals(valueMember, StringComparison.Ordinal)); var subExpression = string.IsNullOrEmpty(subMember.MarshallLocationName) ? subMember.MarshallName : subMember.MarshallLocationName; if (!string.IsNullOrEmpty(subExpression)) { testExpression += "/" + subExpression; } } } return(testExpression); }
// The marshal name must always be up-cased (first letter only) when used with EC2's // variant of AWSQuery. We can also apply operation-specific customizations for marshal // names public static string DetermineAWSQueryMarshallName(Member member, Operation operation) { var isEC2Protocol = member.model.IsEC2Protocol; CustomizationsModel.OperationModifiers modifiers = null; if (operation != null) { modifiers = operation.OperationModifiers; } var marshallName = new StringBuilder(); if (modifiers != null) { var marshallOverride = modifiers.GetMarshallNameOverrides(member.OwningShape.Name, member.PropertyName); if (marshallOverride != null) { var marshallOverrideName = !isEC2Protocol ? marshallOverride.MarshallName : (string.IsNullOrEmpty(marshallOverride.MarshallLocationName) ? marshallOverride.MarshallName : marshallOverride.MarshallLocationName); marshallName.Append(TransformMarshallLocationName(isEC2Protocol, marshallOverrideName)); } } // if the operation didn't override the marshal location, is there a property modifier doing so? if (marshallName.Length == 0 && member.PropertyModifier != null) { var locationName = TransformMarshallLocationName(isEC2Protocol, member.PropertyModifier.LocationName); marshallName.Append(locationName); } // if the marshal name still isn't set, fall back to the model if (marshallName.Length == 0) { var modelMarshallName = !isEC2Protocol ? member.MarshallName : (string.IsNullOrEmpty(member.MarshallLocationName) ? member.MarshallName : member.MarshallLocationName); marshallName.Append(TransformMarshallLocationName(isEC2Protocol, modelMarshallName)); } // also check if we need to emit from a submember as a result of shape substitution var substituteShapeData = member.model.Customizations.GetSubstituteShapeData(member.ModelShape.Name); if (substituteShapeData != null && substituteShapeData[CustomizationsModel.EmitFromMemberKey] != null) { var valueMember = (string)substituteShapeData[CustomizationsModel.EmitFromMemberKey]; var subMember = member.ModelShape.Members.Single(m => m.PropertyName.Equals(valueMember, StringComparison.Ordinal)); if (subMember != null) { var subExpression = string.IsNullOrEmpty(subMember.MarshallLocationName) ? subMember.MarshallName : subMember.MarshallLocationName; marshallName.AppendFormat(".{0}", TransformMarshallLocationName(isEC2Protocol, subExpression)); } } return(marshallName.ToString()); }