/// <summary>
        /// Adds the parameter groups to operation parameters.
        /// </summary>
        /// <param name="codeModelient"></param>
        public static void AddParameterGroups(CodeModel codeModel)
        {
            if (codeModel == null)
            {
                throw new ArgumentNullException("codeModel");
            }

            HashSet<CompositeType> generatedParameterGroups = new HashSet<CompositeType>();

            foreach (Method method in codeModel.Methods)
            {
                //Copy out flattening transformations as they should be the last
                List<ParameterTransformation> flatteningTransformations = method.InputParameterTransformation.ToList();
                method.InputParameterTransformation.Clear();

                //This group name is normalized by each languages code generator later, so it need not happen here.
                IEnumerable<ParameterGroup> parameterGroups = ExtractParameterGroups(method);

                List<Parameter> parametersToAddToMethod = new List<Parameter>();
                List<Parameter> parametersToRemoveFromMethod = new List<Parameter>();

                foreach (ParameterGroup parameterGroup in parameterGroups)
                {
                    CompositeType parameterGroupType =
                        generatedParameterGroups.FirstOrDefault(item => item.Name.RawValue == parameterGroup.Name);

                    if (parameterGroupType == null)
                    {
                        IEnumerable<Method> methodsWhichUseGroup = GetMethodsUsingParameterGroup(codeModel.Methods, parameterGroup);

                        parameterGroupType = New<CompositeType>(parameterGroup.Name,new
                        {
                            Documentation = GenerateParameterGroupModelText(methodsWhichUseGroup)
                        });
                        generatedParameterGroups.Add(parameterGroupType);

                        //Add to the service client
                        codeModel.Add(parameterGroupType);
                    }

                    foreach (Property property in parameterGroup.ParameterMapping.Keys)
                    {
                        Property matchingProperty = parameterGroupType.Properties.FirstOrDefault(
                                item => item.Name.RawValue == property.Name.RawValue &&
                                        item.IsReadOnly == property.IsReadOnly &&
                                        item.DefaultValue .RawValue== property.DefaultValue.RawValue &&
                                        item.SerializedName.RawValue == property.SerializedName.RawValue);
                        if (matchingProperty == null)
                        {
                            parameterGroupType.Add(property);
                        }
                    }

                    bool isGroupParameterRequired = parameterGroupType.Properties.Any(p => p.IsRequired);

                    //Create the new parameter object based on the parameter group type
                    Parameter newParameter = New<Parameter>(new
                    {
                        Name = parameterGroup.Name,
                        IsRequired = isGroupParameterRequired,
                        Location = ParameterLocation.None,
                        SerializedName = string.Empty,
                        ModelType = parameterGroupType,
                        Documentation = "Additional parameters for the operation"
                    });
                    parametersToAddToMethod.Add(newParameter);

                    //Link the grouped parameters to their parent, and remove them from the method parameters
                    foreach (Property property in parameterGroup.ParameterMapping.Keys)
                    {
                        Parameter p = parameterGroup.ParameterMapping[property];

                        var parameterTransformation = new ParameterTransformation
                        {
                            OutputParameter = p
                        };

                        parameterTransformation.ParameterMappings.Add(new ParameterMapping
                        {
                            InputParameter = newParameter,
                            InputParameterProperty = property.GetClientName()
                        });
                        method.InputParameterTransformation.Add(parameterTransformation);
                        parametersToRemoveFromMethod.Add(p);
                    }
                }
                method.Remove(p => parametersToRemoveFromMethod.Contains(p));
                method.AddRange(parametersToAddToMethod);

                // Copy back flattening transformations if any
                flatteningTransformations.ForEach(t => method.InputParameterTransformation.Add(t));
            }
        }
예제 #2
0
        private static Parameter CreateParameterFromGrouping(IEnumerable<ParameterTransformation> grouping, Method method, CodeModel codeModel)
        {
            var properties = new List<Property>();
            string parameterGroupName = null;
            foreach (var parameter in grouping.Select(g => g.OutputParameter))
            {
                Newtonsoft.Json.Linq.JContainer extensionObject = parameter.Extensions[ParameterGroupExtension] as Newtonsoft.Json.Linq.JContainer;
                string specifiedGroupName = extensionObject.Value<string>("name");
                if (specifiedGroupName == null)
                {
                    string postfix = extensionObject.Value<string>("postfix") ?? "Parameters";
                    parameterGroupName = method.Group + "-" + method.Name + "-" + postfix;
                }
                else
                {
                    parameterGroupName = specifiedGroupName;
                }

                Property groupProperty = New<Property>(new
                {
                    IsReadOnly = false, //Since these properties are used as parameters they are never read only
                    Name = parameter.Name,
                    IsRequired = parameter.IsRequired,
                    DefaultValue = parameter.DefaultValue,
                    //Constraints = parameter.Constraints, Omit these since we don't want to perform parameter validation
                    Documentation = parameter.Documentation,
                    ModelType = parameter.ModelType,
                    SerializedName = default(string) //Parameter is never serialized directly
                });
                properties.Add(groupProperty);
            }
            
            var parameterGroupType = New <CompositeType>(parameterGroupName, new
            {
                Documentation = "Additional parameters for the " + method.Name + " operation."
            });

            //Add to the service client
            codeModel.Add(parameterGroupType);

            foreach (Property property in properties)
            {
                parameterGroupType.Add(property);
            }

            bool isGroupParameterRequired = parameterGroupType.Properties.Any(p => p.IsRequired);

            //Create the new parameter object based on the parameter group type
            return New<Parameter>(new
            {
                Name = parameterGroupName,
                IsRequired = isGroupParameterRequired,
                Location = ParameterLocation.None,
                SerializedName = string.Empty,
                ModelType = parameterGroupType,
                Documentation = "Additional parameters for the operation"
            });
        }
예제 #3
0
        /// <summary>
        /// Adds ListNext() method for each List method with x-ms-pageable extension.
        /// </summary>
        /// <param name="codeModelient"></param>
        /// <param name="codeNamer"></param>
        public static void AddPageableMethod(CodeModel codeModel)
        {
            if (codeModel == null)
            {
                throw new ArgumentNullException("codeModel");
            }

            foreach (var method in codeModel.Methods.Distinct(each => each.Group + each.Name).ToArray())
            {
                if (method.Extensions.ContainsKey(PageableExtension))
                {
                    var pageableExtension = JsonConvert.DeserializeObject<PageableExtension>(method.Extensions[PageableExtension].ToString());
                    if (string.IsNullOrWhiteSpace(pageableExtension.NextLinkName))
                    {
                        continue;
                    }

                    Method nextLinkMethod = null;
                    if (!string.IsNullOrEmpty(pageableExtension.OperationName))
                    {
                        nextLinkMethod = codeModel.Methods.FirstOrDefault(m =>
                            pageableExtension.OperationName.EqualsIgnoreCase(m.SerializedName));
                        if (nextLinkMethod != null)
                        {
                            nextLinkMethod.Extensions["nextLinkMethod"] = true;
                            method.Extensions["nextMethodName"] = nextLinkMethod.Name;
                            method.Extensions["nextMethodGroup"] = nextLinkMethod.Group;
                        }
                    }

                    if (nextLinkMethod == null)
                    {
                        nextLinkMethod = Duplicate<Method>(method);

                        if (!string.IsNullOrEmpty(pageableExtension.OperationName))
                        {
                            nextLinkMethod.Name = CodeNamer.Instance.GetMethodName(SwaggerModeler.GetMethodName(
                                new Operation { OperationId = pageableExtension.OperationName }));
                            nextLinkMethod.Group = CodeNamer.Instance.GetMethodGroupName(SwaggerModeler.GetMethodGroup(
                                new Operation { OperationId = pageableExtension.OperationName }));
                        }
                        else
                        {
                            nextLinkMethod.Name = nextLinkMethod.Name + "Next";
                        }
                        method.Extensions["nextMethodName"] = nextLinkMethod.Name;
                        method.Extensions["nextMethodGroup"] = nextLinkMethod.Group;
                        nextLinkMethod.Extensions["nextLinkMethod"] = true;
                        nextLinkMethod.ClearParameters();
                        nextLinkMethod.Url = "{nextLink}";
                        nextLinkMethod.IsAbsoluteUrl = true;
                        var nextLinkParameter = New<Parameter>(new
                        {
                            Name = "nextPageLink",
                            SerializedName = "nextLink",
                            ModelType = New<PrimaryType>(KnownPrimaryType.String),
                            Documentation = "The NextLink from the previous successful call to List operation.",
                            IsRequired = true,
                            Location = ParameterLocation.Path
                        });
                        nextLinkParameter.Extensions[SkipUrlEncodingExtension] = true;
                        nextLinkMethod.Add(nextLinkParameter);

                        // Need copy all the header parameters from List method to ListNext method
                       foreach (var param in method.Parameters.Where(p => p.Location == ParameterLocation.Header))
                       {
                            nextLinkMethod.Add(Duplicate(param));
                       }

                        // Copy all grouped parameters that only contain header parameters
                        nextLinkMethod.InputParameterTransformation.Clear();
                        method.InputParameterTransformation.GroupBy(t => t.ParameterMappings[0].InputParameter)
                            .ForEach(grouping => {
                                if (grouping.All(t => t.OutputParameter.Location == ParameterLocation.Header))
                                {
                                    // All grouped properties were header parameters, reuse data type
                                    nextLinkMethod.Add(grouping.Key);
                                    grouping.ForEach(t => nextLinkMethod.InputParameterTransformation.Add(t));
                                }
                                else if (grouping.Any(t => t.OutputParameter.Location == ParameterLocation.Header))
                                {
                                    // Some grouped properties were header parameters, creating new data types
                                    var headerGrouping = grouping.Where(t => t.OutputParameter.Location == ParameterLocation.Header);
                                    headerGrouping.ForEach(t => nextLinkMethod.InputParameterTransformation.Add((ParameterTransformation) t.Clone()));
                                    var newGroupingParam = CreateParameterFromGrouping(headerGrouping, nextLinkMethod, codeModel);
                                    nextLinkMethod.Add(newGroupingParam);
                                    //grouping.Key.Name = newGroupingParam.Name;
                                    // var inputParameter = (Parameter) nextLinkMethod.InputParameterTransformation.First().ParameterMappings[0].InputParameter.Clone();
                                    var inputParameter = Duplicate(nextLinkMethod.InputParameterTransformation.First().ParameterMappings[0].InputParameter);
                                    inputParameter.Name = CodeNamer.Instance.GetParameterName(newGroupingParam.Name);

                                    inputParameter.IsRequired = newGroupingParam.IsRequired;
                                    nextLinkMethod.InputParameterTransformation.ForEach(t => t.ParameterMappings[0].InputParameter = inputParameter);
                                }
                            });

                        codeModel.Add( nextLinkMethod);
                        
                    }
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Creates azure specific properties.
        /// </summary>
        /// <param name="codeModelient"></param>
        public static void AddAzureProperties(CodeModel codeModel)
        {
            if (codeModel == null)
            {
                throw new ArgumentNullException("codeModel");
            }

            var apiVersion = codeModel.Properties
                .FirstOrDefault(p => ApiVersion.EqualsIgnoreCase(p.SerializedName));
            if (apiVersion != null)
            {
                apiVersion.DefaultValue = codeModel.ApiVersion;
                apiVersion.IsReadOnly = true;
                apiVersion.IsRequired = false;
            }

            var subscriptionId =
                codeModel.Properties.FirstOrDefault(
                    p => p.Name.EqualsIgnoreCase( "subscriptionId"));
            if (subscriptionId != null)
            {
                subscriptionId.IsRequired = true;
            }

            var acceptLanguage = codeModel.Properties
                .FirstOrDefault(p => AcceptLanguage.EqualsIgnoreCase(p.SerializedName));
            if (acceptLanguage == null)
            {
                acceptLanguage = New<Property>(new
                {
                    Name = AcceptLanguage,
                    Documentation = "Gets or sets the preferred language for the response.",
                    SerializedName = AcceptLanguage,
                    DefaultValue = "en-US"
                });
                codeModel.Add( acceptLanguage);
            }
            acceptLanguage.IsReadOnly = false;
            acceptLanguage.IsRequired = false;
            acceptLanguage.ModelType = New<PrimaryType>(KnownPrimaryType.String);
            codeModel.Methods
                .Where(m => !m.Parameters.Any(p => AcceptLanguage.EqualsIgnoreCase(p.SerializedName)))
                .ForEach(m2 => m2.Add(New<Parameter>(new 
                    {
                        ClientProperty = acceptLanguage,
                        Location = ParameterLocation.Header
                    }).LoadFrom(acceptLanguage)));

            codeModel.Insert(New<Property>(new
            {
                Name = "Credentials",
                SerializedName = "credentials",
                ModelType = New<PrimaryType>(KnownPrimaryType.Credentials),
                IsRequired = true,
                IsReadOnly = true,
                Documentation = "Credentials needed for the client to connect to Azure."
            }));

            codeModel.Add(New<Property>(new
            {
                Name = "LongRunningOperationRetryTimeout",
                SerializedName = "longRunningOperationRetryTimeout",
                ModelType = New<PrimaryType>(KnownPrimaryType.Int),
                Documentation = "Gets or sets the retry timeout in seconds for Long Running Operations. Default value is 30.",
                DefaultValue = "30"
            }));

            codeModel.Add( New<Property>(new 
            {
                Name = "GenerateClientRequestId",
                SerializedName = "generateClientRequestId",
                ModelType = New<PrimaryType>(KnownPrimaryType.Boolean),
                Documentation = "When set to true a unique x-ms-client-request-id value is generated and included in each request. Default is true.",
                DefaultValue = "true"
            }));
        }
예제 #5
0
        /// <summary>
        /// Creates long running operation methods.
        /// </summary>
        /// <param name="codeModelient"></param>
        public static void AddLongRunningOperations(CodeModel codeModel)
        {
            if (codeModel == null)
            {
                throw new ArgumentNullException("codeModel");
            }

            foreach( var method in codeModel.Methods.Where( each => each.Extensions.ContainsKey(LongRunningExtension)).Distinct( each  => each.Group + each.Name ).ToArray())
            {
                var isLongRunning = method.Extensions[LongRunningExtension];
                if (true == isLongRunning as bool?)
                {
                    // copy the method 
                    var m = Duplicate(method);

                    // change the name, remove the extension.
                    m.Name = "Begin" + m.Name.ToPascalCase();
                    m.Extensions.Remove(LongRunningExtension);

                    codeModel.Add(m);

                }
            }
        }
예제 #6
0
        /// <summary>
        /// Set default response to CloudError if not defined explicitly.
        /// </summary>
        /// <param name="codeModelient"></param>
        public static void SetDefaultResponses(CodeModel codeModel)
        {
            if (codeModel == null)
            {
                throw new ArgumentNullException("codeModel");
            }

            // Create CloudError if not already defined
            CompositeType cloudError = codeModel.ModelTypes.FirstOrDefault(c =>
                c.Name.EqualsIgnoreCase("cloudError"));
            if (cloudError == null)
            {
                cloudError = New<CompositeType>( new
                {
                    Name = "cloudError",
                    SerializedName = "cloudError"
                });
                cloudError.Extensions[ExternalExtension] = true;
                codeModel.Add(cloudError);
            }
            // Set default response if not defined explicitly
            foreach (var method in codeModel.Methods)
            {
                if (method.DefaultResponse.Body == null && method.ReturnType.Body != null)
                {
                    method.DefaultResponse = new Response(cloudError, method.ReturnType.Headers);
                }                
            }
        }