예제 #1
0
 private static void AddSkipEncodingProperty(TSObject parameterObject, Parameter parameter)
 {
     if (parameter.SkipUrlEncoding())
     {
         parameterObject.BooleanProperty("skipEncoding", true);
     }
 }
예제 #2
0
        public void GenerateOperationSpec(TSObject operationSpec)
        {
            operationSpec.QuotedStringProperty("httpMethod", HttpMethod.ToString().ToUpper());
            if (IsAbsoluteUrl)
            {
                operationSpec.QuotedStringProperty("baseUrl", CodeModelTS.SchemeHostAndPort);
            }
            else
            {
                operationSpec.TextProperty("baseUrl", $"{ClientReference}.baseUri");
            }

            string path = Path;

            if (!string.IsNullOrEmpty(path))
            {
                operationSpec.QuotedStringProperty("path", path);
            }

            Parameter[] logicalParameters = LogicalParameters.ToArray();
            GenerateParameters(operationSpec, "urlParameters", logicalParameters.Where(p => p.Location == ParameterLocation.Path), AddSkipEncodingProperty);
            GenerateParameters(operationSpec, "queryParameters", logicalParameters.Where(p => p.Location == ParameterLocation.Query),
                               (TSObject queryParameterObject, Parameter queryParameter) =>
            {
                AddSkipEncodingProperty(queryParameterObject, queryParameter);
                if (queryParameter.CollectionFormat != CollectionFormat.None)
                {
                    queryParameterObject.TextProperty("collectionFormat", $"msRest.QueryCollectionFormat.{queryParameter.CollectionFormat}");
                }
            });
            GenerateParameters(operationSpec, "headerParameters", logicalParameters.Where(p => p.Location == ParameterLocation.Header));

            if (RequestBody != null)
            {
                operationSpec.Property("requestBodyMapper", requestBodyMapper => ClientModelExtensions.ConstructRequestBodyMapper(requestBodyMapper, RequestBody));
                operationSpec.QuotedStringProperty("requestBodyName", RequestBody.Name);
                operationSpec.QuotedStringProperty("contentType", RequestContentType);
            }
            else
            {
                IEnumerable <Parameter> formDataParameters = logicalParameters.Where(p => p.Location == ParameterLocation.FormData);
                if (formDataParameters.Any())
                {
                    GenerateParameters(operationSpec, "formDataParameters", formDataParameters);
                    operationSpec.QuotedStringProperty("contentType", RequestContentType);
                }
            }

            if (CodeModel.ShouldGenerateXmlSerialization)
            {
                operationSpec.BooleanProperty("isXML", true);
            }
        }
        public static void ConstructMapper(TSObject mapper, IModelType type, string serializedName, IVariable parameter, bool isPageable, bool expandComposite, bool isXML, bool isCaseSensitive = true, string xmlName = null)
        {
            string defaultValue = null;
            bool   isRequired   = false;
            bool   isConstant   = false;
            bool   isReadOnly   = false;
            Dictionary <Constraint, string> constraints = null;
            var property = parameter as Property;

            if (parameter != null)
            {
                defaultValue = parameter.DefaultValue;
                isRequired   = parameter.IsRequired;
                isConstant   = parameter.IsConstant;
                constraints  = parameter.Constraints;
            }

            string xmlPrefix = !isXML ? null : property?.XmlPrefix ?? type?.XmlPrefix;

            bool addXmlNameFromParameterValue = isXML && !string.IsNullOrEmpty(xmlName) && xmlName != serializedName;

            if (addXmlNameFromParameterValue)
            {
                if (!string.IsNullOrEmpty(xmlPrefix))
                {
                    xmlName = $"{xmlPrefix}:{xmlName}";
                }
                mapper.QuotedStringProperty("xmlName", xmlName);
            }

            if (isXML && !string.IsNullOrEmpty(serializedName) && !string.IsNullOrEmpty(xmlPrefix))
            {
                serializedName = $"{xmlPrefix}:{serializedName}";
            }

            if (property != null)
            {
                isReadOnly = property.IsReadOnly;

                if (isXML)
                {
                    if (property.XmlIsAttribute)
                    {
                        mapper.BooleanProperty("xmlIsAttribute", true);
                    }

                    if (property.XmlIsWrapped)
                    {
                        mapper.BooleanProperty("xmlIsWrapped", true);
                    }

                    string propertyXmlName = property.ModelType.XmlProperties?.Name ?? property.XmlName;
                    if (!addXmlNameFromParameterValue && !string.IsNullOrEmpty(propertyXmlName))
                    {
                        if (!string.IsNullOrEmpty(xmlPrefix))
                        {
                            propertyXmlName = $"{xmlPrefix}:{propertyXmlName}";
                        }

                        // For some reason we can't omit xmlName in this scenario if it is equal to
                        // serializedName. It might have to do with whether or not xmlElementName
                        // is present, but I'm not sure at this time.
                        mapper.QuotedStringProperty("xmlName", propertyXmlName);
                    }
                }
            }

            CompositeTypeTS composite = type as CompositeTypeTS;

            if (composite != null && composite.ContainsConstantProperties && (parameter != null && parameter.IsRequired))
            {
                defaultValue = "{}";
            }

            SequenceType sequence = type as SequenceType;

            if (sequence != null && isXML)
            {
                if (sequence.ElementXmlIsWrapped)
                {
                    mapper.BooleanProperty("xmlElementIsWrapped", true);
                }

                string xmlElementName = sequence.ElementType.XmlProperties?.Name ?? sequence.ElementXmlName;
                if (!string.IsNullOrEmpty(xmlElementName))
                {
                    mapper.QuotedStringProperty("xmlElementName", xmlElementName);
                }
            }

            if (isRequired)
            {
                mapper.BooleanProperty("required", true);
            }

            if (parameter?.IsXNullable != null)
            {
                if (parameter.IsXNullable.Value)
                {
                    mapper.BooleanProperty("nullable", true);
                }
                else
                {
                    mapper.BooleanProperty("nullable", false);
                }
            }

            if (isReadOnly)
            {
                mapper.BooleanProperty("readOnly", true);
            }

            if (isConstant)
            {
                mapper.BooleanProperty("isConstant", true);
            }

            if (serializedName != null)
            {
                if (!isCaseSensitive)
                {
                    serializedName = serializedName.ToLower();
                }
                mapper.QuotedStringProperty("serializedName", serializedName);
            }

            if (!string.IsNullOrEmpty(defaultValue))
            {
                mapper.TextProperty("defaultValue", defaultValue);
            }

            DictionaryType dictionary = type as DictionaryType;
            PrimaryType    primary    = type as PrimaryType;
            EnumType       enumType   = type as EnumType;

            void applyConstraints(TSObject obj)
            {
                bool useClientSideValidation = (bool)(Settings.Instance?.CustomSettings[CodeModelTS.ClientSideValidationSettingName] ?? false);

                if (useClientSideValidation && constraints != null && constraints.Any())
                {
                    obj.ObjectProperty("constraints", constraintsObject =>
                    {
                        foreach (KeyValuePair <Constraint, string> constraintEntry in constraints)
                        {
                            Constraint constraint  = constraintEntry.Key;
                            string constraintValue = constraintEntry.Value;
                            if (constraint == Constraint.Pattern)
                            {
                                constraintValue = CreateRegexPatternConstraintValue(constraintValue);
                            }
                            constraintsObject.TextProperty(constraint.ToString(), constraintValue);
                        }
                    });
                }
            }

            // Apply header collection constraints only to dictionary values, not the dictionary itself
            string prefix          = parameter?.Extensions?.GetValue <string>(SwaggerExtensions.HeaderCollectionPrefix);
            bool   skipConstraints = !string.IsNullOrEmpty(prefix) && dictionary != null;

            if (!skipConstraints)
            {
                applyConstraints(mapper);
            }

            if (primary != null)
            {
                switch (primary.KnownPrimaryType)
                {
                case KnownPrimaryType.Base64Url:
                case KnownPrimaryType.Boolean:
                case KnownPrimaryType.ByteArray:
                case KnownPrimaryType.Date:
                case KnownPrimaryType.DateTime:
                case KnownPrimaryType.DateTimeRfc1123:
                case KnownPrimaryType.Object:
                case KnownPrimaryType.Stream:
                case KnownPrimaryType.String:
                case KnownPrimaryType.TimeSpan:
                case KnownPrimaryType.UnixTime:
                case KnownPrimaryType.Uuid:
                    AddTypeProperty(mapper, primary.KnownPrimaryType.ToString());
                    break;

                case KnownPrimaryType.Int:
                case KnownPrimaryType.Long:
                case KnownPrimaryType.Decimal:
                case KnownPrimaryType.Double:
                    AddTypeProperty(mapper, "Number");
                    break;

                default:
                    throw new NotImplementedException($"{primary} is not a supported Type.");
                }
            }
            else if (enumType != null)
            {
                if (enumType.ModelAsString)
                {
                    AddTypeProperty(mapper, "String");
                }
                else
                {
                    AddTypeProperty(mapper, "Enum", typeObject =>
                    {
                        typeObject.ArrayProperty("allowedValues", allowedValues =>
                        {
                            foreach (EnumValue enumValue in enumType.Values)
                            {
                                allowedValues.QuotedString(enumValue.SerializedName);
                            }
                        });
                    });
                }
            }
            else if (sequence != null)
            {
                AddTypeProperty(mapper, "Sequence", typeObject =>
                {
                    typeObject.Property("element", element =>
                    {
                        ConstructMapper(element, sequence.ElementType, null, null, false, false, isXML, isCaseSensitive);
                    });
                });
            }
            else if (dictionary != null)
            {
                AddTypeProperty(mapper, "Dictionary", typeObject =>
                {
                    typeObject.ObjectProperty("value", dictionaryValue =>
                    {
                        ConstructMapper(dictionaryValue, dictionary.ValueType, null, null, false, false, isXML, isCaseSensitive);
                        applyConstraints(dictionaryValue);
                    });
                });

                if (!string.IsNullOrEmpty(prefix))
                {
                    mapper.QuotedStringProperty("headerCollectionPrefix", prefix);
                }
            }
            else if (composite != null)
            {
                AddTypeProperty(mapper, "Composite", typeObject =>
                {
                    if (expandComposite)
                    {
                        if (composite.IsPolymorphic)
                        {
                            // Note: If the polymorphicDiscriminator has a dot in it's name then do not escape that dot for
                            // it's serializedName, the way it is done for other properties. This makes it easy to find the
                            // discriminator property from the responseBody during deserialization. Please, do not get confused
                            // between the definition of the discriminator and the definition of the property that is
                            // marked as the discriminator.
                            typeObject.ObjectProperty("polymorphicDiscriminator", polymorphicDiscriminator =>
                            {
                                polymorphicDiscriminator.QuotedStringProperty("serializedName", composite.PolymorphicDiscriminator);
                                polymorphicDiscriminator.QuotedStringProperty("clientName", Singleton <CodeNamerTS> .Instance.GetPropertyName(composite.PolymorphicDiscriminator));
                            });
                            typeObject.QuotedStringProperty("uberParent", composite.Name);
                        }
                        else
                        {
                            CompositeType baseType = composite;
                            while (baseType.BaseModelType != null)
                            {
                                baseType = baseType.BaseModelType;
                            }
                            if (baseType.IsPolymorphic)
                            {
                                typeObject.TextProperty("polymorphicDiscriminator", baseType.Name + ".type.polymorphicDiscriminator");
                                typeObject.QuotedStringProperty("uberParent", baseType.Name);
                            }
                        }
                    }

                    typeObject.QuotedStringProperty("className", composite.Name);

                    if (expandComposite)
                    {
                        typeObject.ObjectProperty("modelProperties", modelProperties =>
                        {
                            if (composite.BaseModelType != null && composite.BaseModelType.ComposedProperties.Any())
                            {
                                modelProperties.Spread(composite.BaseModelType.Name + ".type.modelProperties");
                            }
                            foreach (Property prop in composite.Properties)
                            {
                                var serializedPropertyName = prop.SerializedName;
                                if (isPageable)
                                {
                                    PropertyInfo itemName     = composite.GetType().GetProperty("ItemName");
                                    PropertyInfo nextLinkName = composite.GetType().GetProperty("NextLinkName");
                                    string nextLinkNameValue  = (string)nextLinkName.GetValue(composite);
                                    if (itemName != null && ((string)itemName.GetValue(composite) == prop.Name))
                                    {
                                        serializedPropertyName = "";
                                    }

                                    if (prop.Name.Contains("nextLink") && nextLinkName != null && nextLinkNameValue == null)
                                    {
                                        continue;
                                    }
                                }

                                if (modelProperties.ContainsProperty(prop.Name))
                                {
                                    // throw new InvalidOperationException($"Mapper \"{serializedName}\" contains multiple modelProperties with the name \"{prop.Name}\".");
                                }
                                else
                                {
                                    modelProperties.Property(prop.Name, propertyValue => ConstructMapper(propertyValue, prop.ModelType, serializedPropertyName, prop, false, false, isXML, isCaseSensitive));
                                }
                            }
                        });
                    }

                    if (composite.AdditionalProperties != null)
                    {
                        typeObject.ObjectProperty("additionalProperties", additionalProperties =>
                        {
                            ConstructMapper(additionalProperties, composite.AdditionalProperties, serializedName: null, parameter: null, isPageable: false, expandComposite: false, isXML: isXML);
                        });
                    }
                    else
                    {
                        CompositeTypeTS baseType = composite;
                        while (true)
                        {
                            baseType = (CompositeTypeTS)baseType.BaseModelType;
                            if (baseType == null)
                            {
                                break;
                            }
                            else if (baseType.AdditionalProperties != null)
                            {
                                typeObject.TextProperty("additionalProperties", $"{baseType.Name}.type.additionalProperties");
                                break;
                            }
                        }
                    }
                });
            }
            else
            {
                throw new NotImplementedException($"{type} is not a supported Type.");
            }
        }
예제 #4
0
        public void GenerateOperationSpec(TSObject operationSpec)
        {
            operationSpec.QuotedStringProperty("httpMethod", HttpMethod.ToString().ToUpper());
            if (IsAbsoluteUrl)
            {
                operationSpec.QuotedStringProperty("baseUrl", CodeModelTS.BaseUrl);
            }

            string path = Path;

            if (!string.IsNullOrEmpty(path))
            {
                operationSpec.QuotedStringProperty("path", path);
            }

            Parameter[] logicalParameters = LogicalParameters.ToArray();

            AddParameterRefs(operationSpec, "urlParameters", logicalParameters.Where(p => p.Location == ParameterLocation.Path));
            AddParameterRefs(operationSpec, "queryParameters", logicalParameters.Where(p => p.Location == ParameterLocation.Query));
            AddParameterRefs(operationSpec, "headerParameters", logicalParameters.Where(p => p.Location == ParameterLocation.Header));

            bool addContentTypeProperty = (!string.IsNullOrEmpty(RequestContentType) && RequestContentType != CodeModelTS.RequestContentType);

            if (Body != null)
            {
                operationSpec.ObjectProperty("requestBody", requestBodyObject =>
                {
                    GenerateRequestParameterPath(requestBodyObject, Body, GetParameterTransformations());
                    requestBodyObject.Property("mapper", requestBodyMapper => ClientModelExtensions.ConstructRequestBodyMapper(requestBodyMapper, Body));
                });
            }
            else
            {
                IEnumerable <Parameter> formDataParameters = logicalParameters.Where(p => p.Location == ParameterLocation.FormData);
                if (formDataParameters.Any())
                {
                    AddParameterRefs(operationSpec, "formDataParameters", formDataParameters);
                    addContentTypeProperty = true;
                }
            }
            if (addContentTypeProperty)
            {
                operationSpec.QuotedStringProperty("contentType", RequestContentType);
            }

            operationSpec.ObjectProperty("responses", responses =>
            {
                bool isXml = CodeModelTS.ShouldGenerateXmlSerialization;
                foreach (KeyValuePair <HttpStatusCode, Response> statusCodeResponsePair in Responses)
                {
                    HttpStatusCode statusCode = statusCodeResponsePair.Key;
                    Response response         = statusCodeResponsePair.Value;

                    responses.ObjectProperty(((int)statusCode).ToString(), responseObject =>
                    {
                        if (response.Body != null)
                        {
                            responseObject.Property("bodyMapper", responseBodyMapper => ClientModelExtensions.ConstructResponseBodyMapper(responseBodyMapper, response, this));
                        }
                        if (response.Headers != null)
                        {
                            responseObject.Property("headersMapper", responseHeadersMapper => responseHeadersMapper.Text($"Mappers.{response.Headers.Name}"));
                        }
                    });
                }

                responses.ObjectProperty("default", defaultResponseObject =>
                {
                    Response defaultResponse = DefaultResponse;
                    if (defaultResponse != null && defaultResponse.Body != null)
                    {
                        defaultResponseObject.Property("bodyMapper", responseBodyMapper => ClientModelExtensions.ConstructResponseBodyMapper(responseBodyMapper, defaultResponse, this));
                    }
                });
            });


            if (CodeModel.ShouldGenerateXmlSerialization)
            {
                operationSpec.BooleanProperty("isXML", true);
            }

            operationSpec.TextProperty("serializer", "serializer");
        }