/// <summary>
        /// Checks whether the return type of a given method can be wrapped in a Java interface impl and wrapper
        /// can expose it through HasInner interface.
        /// </summary>
        /// <param name="method">the method to check its return type eligibility to be wrappable</param>
        /// <returns></returns>
        public static bool HasWrappableReturnType(this Azure.Fluent.Model.MethodJvaf method)
        {
            if (method.ReturnTypeJva != null)
            {
                CompositeTypeJvaf returnModelType = null;
                IModelType        mtype           = method.ReturnTypeJva.BodyClientType;
                if (mtype is CompositeTypeJvaf)
                {
                    returnModelType = (CompositeTypeJvaf)mtype;
                }
                else if (mtype is SequenceTypeJva)
                {
                    mtype = ((SequenceTypeJva)mtype).ElementType;

                    if (mtype is CompositeTypeJvaf)
                    {
                        returnModelType = (CompositeTypeJvaf)mtype;
                    }
                }
                //
                if (returnModelType != null)
                {
                    string returnModelTypeName = returnModelType.Name.Value;
                    return(returnModelTypeName.EndsWith("Inner", StringComparison.OrdinalIgnoreCase));
                }
                else
                {
                    return(false);
                }
            }
            else
            {
                return(false);
            }
        }
Exemple #2
0
        /// <summary>
        /// Derive and return optional definition stages from the create member variables.
        /// </summary>
        protected List <FluentDefinitionOrUpdateStage> OptionalDefinitionStages(List <FluentDefinitionOrUpdateStage> initialStages)
        {
            if (this.optDefStages != null)
            {
                return(this.optDefStages);
            }

            this.optDefStages = new List <FluentDefinitionOrUpdateStage>();
            if (!this.SupportsCreating)
            {
                return(this.optDefStages);
            }

            var dmvs = this.disambiguatedMemberVariables ?? throw new ArgumentNullException("dMemberVariables");

            var payloadInnerModelVariable = this.CompositePayloadVariable;

            // Stages for setting optional properties of "create body payload"
            //
            if (payloadInnerModelVariable != null)
            {
                string payloadInnerModelVariableName = payloadInnerModelVariable.VariableName;

                CompositeTypeJvaf payloadType = (CompositeTypeJvaf)payloadInnerModelVariable.FromParameter.ClientType;

                var payloadOptinalProperties = payloadType
                                               .ComposedProperties
                                               .Where(p => !p.IsReadOnly && !p.IsRequired)
                                               .Where(p => !propertiesOfPayloadToSkip.Contains(p.Name.ToString(), StringComparer.OrdinalIgnoreCase))
                                               .OrderBy(p => p.Name.ToLowerInvariant());

                FluentDefinitionOrUpdateStage creatableStage = new FluentDefinitionOrUpdateStage(this.resourceName, "WithCreate");
                foreach (Property pro in payloadOptinalProperties)
                {
                    string methodName          = $"with{pro.Name.ToPascalCase()}";
                    string parameterName       = pro.Name;
                    string methodParameterDecl = $"{pro.ModelTypeName} {parameterName}";
                    FluentDefinitionOrUpdateStageMethod method = new FluentDefinitionOrUpdateStageMethod(methodName, methodParameterDecl, pro.ModelType as IModelTypeJv)
                    {
                        CommentFor = new Dictionary <string, string> {
                            { parameterName, pro.Documentation }
                        },
                        Body = $"{(dmvs.MemeberVariablesForCreate[payloadInnerModelVariableName]).VariableAccessor}.{methodName}({parameterName});"
                    };

                    string interfaceName = $"With{pro.Name.ToPascalCase()}";
                    FluentDefinitionOrUpdateStage stage = new FluentDefinitionOrUpdateStage(this.resourceName, interfaceName);
                    this.optDefStages.Add(stage);

                    stage.Methods.Add(method);
                    stage.Methods.ForEach(m =>
                    {
                        m.NextStage = creatableStage;
                    });
                }
            }
            return(this.optDefStages);
        }
Exemple #3
0
        public NonWrappableModel(CompositeTypeJvaf rawModel)
        {
            var innerModelName = rawModel.Name.Value;

            if (innerModelName.EndsWith("Inner", StringComparison.OrdinalIgnoreCase))
            {
                throw new ArgumentException($"NonWrappableModel requires an inner model without 'Inner' suffix but received inner model '{innerModelName}'.");
            }
            this.RawModel = rawModel;
        }
        /// <summary>
        /// Creates WrappableFluentModel describing a Fluent Model that wraps the given Inner Model.
        /// </summary>
        /// <param name="innerModel">the inner model [that has 'Inner' suffix in it's name]</param>
        public WrappableFluentModel(CompositeTypeJvaf innerModel)
        {
            var innerModelName = innerModel.Name.Value;

            if (!innerModelName.EndsWith("Inner", StringComparison.OrdinalIgnoreCase))
            {
                throw new ArgumentException($"WrappableFluentModel requires 'Inner' suffix for the inner model it wraps but received inner model '{innerModelName}' without suffix.");
            }
            this.JavaInterfaceName = Utils.TrimInnerSuffix(innerModelName);
            this.RawModel          = innerModel;
        }
        public FluentModel(CompositeTypeJvaf innerModel)
        {
            var n = innerModel.Name.Value;

            if (!n.EndsWith("Inner", StringComparison.OrdinalIgnoreCase))
            {
                throw new ArgumentException($"Fluent inner model should have inner suffix {n}");
            }
            this.javaInterfaceName = n.Substring(0, n.Length - "Inner".Length);
            this.InnerModel        = innerModel;
        }
        private CompositeTypeJvaf standardInnerModel;   // The derived standard inner model.
        /// <summary>
        /// The "Segment Fluent Method Group" composes a bunch of methods, now given all these methods identify
        /// the "Standard Inner Model" from the standard methods.
        /// </summary>
        public void DeriveStandardInnerModelForMethodGroup()
        {
            if (this.derivedStandardInnerModel)
            {
                return;
            }

            this.derivedStandardInnerModel = true;

            // Find "ONE" fluent model that can be used across "Standard methods"
            // 1. (GetByResourceGroup | ListByResourceGroup | ListBySubscription | Create in RG)
            // 2. (GetByImmediateParent | ListByImmediateParent | Create in Parent)
            //
            // Derive an "inner model then a fluent model" that represents the return type of standard methods
            // in this fluent model. We want all thoses standard methods to return same fluent type though the
            // inner methods can return different inner model types.
            //
            if (ResourceGetDescription.SupportsGetByResourceGroup)
            {
                this.standardInnerModel = ResourceGetDescription.GetByResourceGroupMethod.InnerReturnType;
            }
            else if (ResourceCreateDescription.SupportsCreating)
            {
                this.standardInnerModel = ResourceCreateDescription.CreateMethod.InnerReturnType;
            }
            else if (ResourceListingDescription.SupportsListByResourceGroup)
            {
                this.standardInnerModel = ResourceListingDescription.ListByResourceGroupMethod.InnerReturnType;
            }
            else if (ResourceListingDescription.SupportsListBySubscription)
            {
                this.standardInnerModel = ResourceListingDescription.ListBySubscriptionMethod.InnerReturnType;
            }
            //
            else if (ResourceGetDescription.SupportsGetByImmediateParent)
            {
                this.standardInnerModel = ResourceGetDescription.GetByImmediateParentMethod.InnerReturnType;
            }
            else if (ResourceListingDescription.SupportsListByImmediateParent)
            {
                this.standardInnerModel = ResourceListingDescription.ListByImmediateParentMethod.InnerReturnType;
            }
            else if (ResourceUpdateDescription.SupportsUpdating)
            {
                this.standardInnerModel = ResourceUpdateDescription.UpdateMethod.InnerReturnType;
            }
        }
Exemple #7
0
 public static bool IsTrackedResource(CompositeTypeJvaf model)
 {
     if (model == null)
     {
         return(false);
     }
     else
     {
         //
         bool hasId       = model.ComposedProperties.Any(p => p.Name.ToLowerInvariant().Equals("id") /*&& p.IsReadOnly*/);
         bool hasName     = model.ComposedProperties.Any(p => p.Name.ToLowerInvariant().Equals("name") /*&& p.IsReadOnly*/);
         bool hasType     = model.ComposedProperties.Any(p => p.Name.ToLowerInvariant().Equals("type") /*&& p.IsReadOnly*/);
         bool hasLocation = model.ComposedProperties.Any(p => p.Name.ToLowerInvariant().Equals("location"));
         bool hasTags     = model.ComposedProperties.Any(p => p.Name.ToLowerInvariant().Equals("tags"));
         //
         return(hasId && hasName && hasType && hasLocation && hasTags);
     }
 }
        public StandardModel(FluentMethodGroup group, CompositeTypeJvaf standardInnerModel) : base(standardInnerModel)
        {
            switch (group.Type)
            {
            case MethodGroupType.GroupableTopLevel:
                this.Type = StanardModelType.GroupableTopLevel;
                break;

            case MethodGroupType.NonGroupableTopLevel:
                this.Type = StanardModelType.NonGroupableTopLevel;
                break;

            case MethodGroupType.Nested:
                this.Type = StanardModelType.Nested;
                break;

            default:
                throw new ArgumentException($"group with type '{group.Type}' is not eligible to have a standard model.");
            }
            this.FluentMethodGroup = group;
        }
Exemple #9
0
        /// <summary>
        /// Derive and return required definition stages from the create member variables.
        /// </summary>
        protected List <FluentDefinitionOrUpdateStage> RequiredDefinitionStages(List <FluentDefinitionOrUpdateStage> initialStages)
        {
            if (this.reqDefStages != null)
            {
                return(this.reqDefStages);
            }

            this.reqDefStages = new List <FluentDefinitionOrUpdateStage>();
            if (!this.SupportsCreating)
            {
                return(this.reqDefStages);
            }

            var dmvs = this.disambiguatedMemberVariables ?? throw new ArgumentNullException("dMemberVariables");
            FluentDefinitionOrUpdateStage currentStage = null;

            if (initialStages != null)
            {
                this.reqDefStages.AddRange(initialStages);
                currentStage = this.reqDefStages.LastOrDefault();
            }

            // 1. stages for setting create arguments except "create body payload"
            //
            foreach (var memberVariable in this.NotParentRefNotCompositePayloadButPositionalAndOtherMemberVariables)
            {
                string methodName          = $"with{memberVariable.FromParameter.Name.ToPascalCase()}";
                string parameterName       = memberVariable.VariableName;
                string methodParameterDecl = $"{memberVariable.VariableTypeName} {parameterName}";
                FluentDefinitionOrUpdateStageMethod method = new FluentDefinitionOrUpdateStageMethod(methodName, methodParameterDecl, memberVariable.VariableType)
                {
                    CommentFor = new Dictionary <string, string> {
                        { parameterName, memberVariable.FromParameter.Documentation }
                    },
                    Body = $"{(dmvs.MemeberVariablesForCreate[memberVariable.VariableName]).VariableAccessor} = {parameterName};"
                };

                string interfaceName = $"With{memberVariable.FromParameter.Name.ToPascalCase()}";
                FluentDefinitionOrUpdateStage nextStage = new FluentDefinitionOrUpdateStage(this.resourceName, interfaceName);
                this.reqDefStages.Add(nextStage);
                nextStage.Methods.Add(method);
                //
                if (currentStage != null)
                {
                    currentStage.Methods.ForEach(m =>
                    {
                        m.NextStage = nextStage;
                    });
                }
                currentStage = nextStage;
            }

            // 2. stages for setting required properties of "create body composite payload"
            //
            var compositePayloadVariable = this.CompositePayloadVariable;

            if (compositePayloadVariable != null)
            {
                string payloadInnerModelVariableName = compositePayloadVariable.VariableName;

                CompositeTypeJvaf payloadType = (CompositeTypeJvaf)compositePayloadVariable.FromParameter.ClientType;

                var payloadRequiredProperties = payloadType.ComposedProperties
                                                .Where(p => !p.IsReadOnly && p.IsRequired)
                                                .Where(p => !propertiesOfPayloadToSkip.Contains(p.Name.ToString(), StringComparer.OrdinalIgnoreCase))
                                                .OrderBy(p => p.Name.ToLowerInvariant());

                foreach (Property pro in payloadRequiredProperties)
                {
                    string methodName          = $"with{pro.Name.ToPascalCase()}";
                    string parameterName       = pro.Name;
                    string methodParameterDecl = $"{pro.ModelTypeName} {parameterName}";
                    FluentDefinitionOrUpdateStageMethod method = new FluentDefinitionOrUpdateStageMethod(methodName, methodParameterDecl, pro.ModelType as IModelTypeJv)
                    {
                        CommentFor = new Dictionary <string, string> {
                            { parameterName, pro.Documentation }
                        },
                        Body = $"{(dmvs.MemeberVariablesForCreate[payloadInnerModelVariableName]).VariableAccessor}.{methodName}({parameterName});"
                    };

                    string interfaceName = $"With{pro.Name.ToPascalCase()}";
                    FluentDefinitionOrUpdateStage nextStage = new FluentDefinitionOrUpdateStage(this.resourceName, interfaceName);
                    this.reqDefStages.Add(nextStage);

                    nextStage.Methods.Add(method);
                    if (currentStage != null)
                    {
                        currentStage.Methods.ForEach(m =>
                        {
                            m.NextStage = nextStage;
                        });
                    }
                    currentStage = nextStage;
                }
            }

            FluentDefinitionOrUpdateStage creatableStage = new FluentDefinitionOrUpdateStage(this.resourceName, "WithCreate");

            if (currentStage != null)
            {
                currentStage.Methods.ForEach(m =>
                {
                    m.NextStage = creatableStage;
                });
            }
            return(this.reqDefStages);
        }
        /// <summary>
        /// Create and return "Update Stages" from the member variables.
        /// </summary>
        public virtual List <FluentDefinitionOrUpdateStage> UpdateStages()
        {
            if (this.updateStages != null)
            {
                return(this.updateStages);
            }

            this.updateStages = new List <FluentDefinitionOrUpdateStage>();
            if (!this.SupportsUpdating)
            {
                return(this.updateStages);
            }

            var dmvs = this.disambiguatedMemberVariables ?? throw new ArgumentNullException("dMemberVariables");

            FluentDefinitionOrUpdateStage updateGrouping = new FluentDefinitionOrUpdateStage(this.resourceName, "Update");

            // During resource update changing parent ref properties and other path properties are not allowed
            //
            IEnumerable <FluentModelMemberVariable> nonExpandableUpdatableMemberVariables = this.NotParentRefNotPositionalPathAndNotCompositePayloadMemberVariables;

            foreach (var memberVariable in nonExpandableUpdatableMemberVariables)
            {
                string methodName          = $"with{memberVariable.FromParameter.Name.ToPascalCase()}";
                string parameterName       = memberVariable.VariableName;
                string methodParameterDecl = $"{memberVariable.VariableTypeName} {parameterName}";
                FluentDefinitionOrUpdateStageMethod method = new FluentDefinitionOrUpdateStageMethod(methodName, methodParameterDecl, memberVariable.VariableType)
                {
                    CommentFor = new Dictionary <string, string> {
                        { parameterName, memberVariable.FromParameter.Documentation }
                    },
                    Body = $"{(dmvs.MemeberVariablesForUpdate[memberVariable.VariableName]).VariableAccessor} = {parameterName};"
                };

                string interfaceName = $"With{memberVariable.FromParameter.Name.ToPascalCase()}";
                FluentDefinitionOrUpdateStage stage = new FluentDefinitionOrUpdateStage(this.resourceName, interfaceName);
                this.updateStages.Add(stage);

                stage.Methods.Add(method);
                stage.Methods.ForEach(m =>
                {
                    m.NextStage = updateGrouping;
                });
            }

            var payloadInnerModelVariable = this.CompositePayloadVariable;

            if (payloadInnerModelVariable != null)
            {
                string payloadInnerModelVariableName = payloadInnerModelVariable.VariableName;

                CompositeTypeJvaf payloadType = (CompositeTypeJvaf)payloadInnerModelVariable.FromParameter.ClientType;

                var payloadOptionalProperties = payloadType
                                                .ComposedProperties
                                                .Where(p => !p.IsReadOnly && !p.IsRequired)
                                                .Where(p => !propertiesOfPayloadToSkip.Contains(p.Name.ToString(), StringComparer.OrdinalIgnoreCase))
                                                .OrderBy(p => p.Name.ToLowerInvariant());

                foreach (Property pro in payloadOptionalProperties)
                {
                    string methodName          = $"with{pro.Name.ToPascalCase()}";
                    string parameterName       = pro.Name;
                    string methodParameterDecl = $"{pro.ModelTypeName} {parameterName}";
                    FluentDefinitionOrUpdateStageMethod method = new FluentDefinitionOrUpdateStageMethod(methodName, methodParameterDecl, pro.ModelType as IModelTypeJv)
                    {
                        CommentFor = new Dictionary <string, string> {
                            { parameterName, pro.Documentation }
                        },
                        Body = $"{(dmvs.MemeberVariablesForUpdate[payloadInnerModelVariableName]).VariableAccessor}.{methodName}({parameterName});"
                    };

                    string interfaceName = $"With{pro.Name.ToPascalCase()}";
                    FluentDefinitionOrUpdateStage stage = new FluentDefinitionOrUpdateStage(this.resourceName, interfaceName);
                    this.updateStages.Add(stage);

                    stage.Methods.Add(method);
                    stage.Methods.ForEach(m =>
                    {
                        m.NextStage = updateGrouping;
                    });
                }
            }
            return(this.updateStages);
        }
Exemple #11
0
        internal void DeriveStandrdFluentModelForMethodGroup()
        {
            if (this.derivedFluentModels)
            {
                return;
            }

            this.derivedFluentModels = true;

            // Find "ONE" fluent model that can be used across "Standard methods" (GetByResourceGroup |
            // ListByResourceGroup | ListBySubscription | GetByImmediateParent | ListByImmediateParent |
            // Create in RG, Update)
            //
            // Derive an "inner model then a fluent model" that represents the return type of standard methods
            // in this fluent model. We want all thoses standard methods to return same fluent type though the
            // inner methods can return different inner model types.
            //
            CompositeTypeJvaf standardModelInner = null;

            this.innersRequireWrapping = new Dictionary <string, CompositeTypeJvaf>();

            if (ResourceGetDescription.SupportsGetByResourceGroup)
            {
                standardModelInner = ResourceGetDescription.GetByResourceGroupMethod.InnerReturnType;
            }
            else if (ResourceCreateDescription.SupportsCreating)
            {
                standardModelInner = ResourceCreateDescription.CreateMethod.InnerReturnType;
            }
            else if (ResourceListingDescription.SupportsListByResourceGroup)
            {
                standardModelInner = ResourceListingDescription.ListByResourceGroupMethod.InnerReturnType;
            }
            else if (ResourceListingDescription.SupportsListBySubscription)
            {
                standardModelInner = ResourceListingDescription.ListBySubscriptionMethod.InnerReturnType;
            }
            else if (ResourceGetDescription.SupportsGetByImmediateParent)
            {
                standardModelInner = ResourceGetDescription.GetByImmediateParentMethod.InnerReturnType;
            }
            else if (ResourceListingDescription.SupportsListByImmediateParent)
            {
                standardModelInner = ResourceListingDescription.ListByImmediateParentMethod.InnerReturnType;
            }
            else if (ResourceUpdateDescription.SupportsUpdating)
            {
                standardModelInner = ResourceUpdateDescription.UpdateMethod.InnerReturnType;
            }

            // For the "standard model" (FModel) in a FluentMethodGroup we need to gen "FModel wrapModel(ModelInner)"
            // but if there are different ModelInner types mapping that needs to be mapped to the same FModel
            // we will be generating one over load per inner -> FModel mapping
            //
            if (standardModelInner != null)
            {
                this.standardFluentModel = new FluentModel(standardModelInner);

                if (ResourceGetDescription.SupportsGetByResourceGroup)
                {
                    var im = ResourceGetDescription.GetByResourceGroupMethod.InnerReturnType;
                    this.innersRequireWrapping.AddIfNotExists(im.ClassName, im);
                }
                if (ResourceCreateDescription.SupportsCreating)
                {
                    var im = ResourceCreateDescription.CreateMethod.InnerReturnType;
                    this.innersRequireWrapping.AddIfNotExists(im.ClassName, im);
                }
                if (ResourceListingDescription.SupportsListByResourceGroup)
                {
                    var im = ResourceListingDescription.ListByResourceGroupMethod.InnerReturnType;
                    this.innersRequireWrapping.AddIfNotExists(im.ClassName, im);
                }
                if (ResourceListingDescription.SupportsListBySubscription)
                {
                    var im = ResourceListingDescription.ListBySubscriptionMethod.InnerReturnType;
                    this.innersRequireWrapping.AddIfNotExists(im.ClassName, im);
                }
                if (ResourceGetDescription.SupportsGetByImmediateParent)
                {
                    var im = ResourceGetDescription.GetByImmediateParentMethod.InnerReturnType;
                    this.innersRequireWrapping.AddIfNotExists(im.ClassName, im);
                }
                if (ResourceListingDescription.SupportsListByImmediateParent)
                {
                    var im = ResourceListingDescription.ListByImmediateParentMethod.InnerReturnType;
                    this.innersRequireWrapping.AddIfNotExists(im.ClassName, im);
                }
                if (ResourceUpdateDescription.SupportsUpdating)
                {
                    var im = ResourceUpdateDescription.UpdateMethod.InnerReturnType;
                    this.innersRequireWrapping.AddIfNotExists(im.ClassName, im);
                }
                // Remove wrapping for standard model as each fluent method group takes care of it locally
                //
                this.innersRequireWrapping.Remove(this.standardFluentModel.InnerModel.ClassName);
            }
        }