private MethodDeclarationSyntax GenerateConversionMethod(TransportModelEntity entityModel)
        {
            var members = CsEmitterHelper.GetMembers(entityModel, null, true);

            List <ExpressionSyntax> initializers = new List <ExpressionSyntax>();

            foreach (var member in members)
            {
                var propertyName = NameHelper.GetSafeVariableName(member.Key);

                if (member.Value.Type is ITransportModelTypeReferenceTransportModelItem <TransportModelItem> itemReference &&
                    !(itemReference.TransportModelItem is TransportModelEnum))
                {
                    if (itemReference.IsCollection)
                    {
                        initializers.Add(
                            AssignmentExpression(
                                SyntaxKind.SimpleAssignmentExpression,
                                IdentifierName(propertyName),
                                InvocationExpression(
                                    MemberAccessExpression(
                                        SyntaxKind.SimpleMemberAccessExpression,
                                        ThisExpression(),
                                        GenericName(
                                            Identifier("GetTransportModelNodes"),
                                            TypeArgumentList(
                                                SeparatedList <TypeSyntax>(
                                                    new[]
                        {
                            ParseTypeName(CsEmitterHelper.GetCSharpModelFullyQualifiedName(itemReference.TransportModelItem, this.settings, ModelType.Transport))
                        })))))
                                .WithArgumentList(ArgumentList(SeparatedList <ArgumentSyntax>(new[] { Argument(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ThisExpression(), IdentifierName(propertyName))) })))
                                ));
                    }
                    else
                    {
                        initializers.Add(
                            AssignmentExpression(
                                SyntaxKind.SimpleAssignmentExpression,
                                IdentifierName(propertyName),
                                ConditionalExpression(
                                    BinaryExpression(SyntaxKind.NotEqualsExpression, MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ThisExpression(), IdentifierName(propertyName)), IdentifierName("null")),
                                    CastExpression(ParseTypeName(CsEmitterHelper.GetPropertyTypeName(member.Value, this.settings, ModelType.Transport)),
                                                   InvocationExpression(
                                                       MemberAccessExpression(
                                                           SyntaxKind.SimpleMemberAccessExpression,
                                                           MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ThisExpression(), IdentifierName(propertyName)),
                                                           IdentifierName("GetTransportModelNode")))
                                                   .WithArgumentList(ArgumentList())),
                                    IdentifierName("null")
                                    )));
                    }
                }
                else
                {
                    initializers.Add(
                        AssignmentExpression(
                            SyntaxKind.SimpleAssignmentExpression,
                            IdentifierName(propertyName),
                            MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ThisExpression(), IdentifierName(propertyName))));
                }
            }

            return(MethodDeclaration(ParseTypeName(typeof(object).FullName), "GetTransportModelNode")
                   .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.OverrideKeyword)))
                   .WithParameterList(ParameterList())
                   .WithBody(
                       Block(
                           List <StatementSyntax>(
                               new[] {
                ReturnStatement(
                    ObjectCreationExpression(ParseTypeName(CsEmitterHelper.GetCSharpModelFullyQualifiedName(entityModel, this.settings, ModelType.Transport)))
                    .WithArgumentList(ArgumentList())
                    .WithInitializer(
                        InitializerExpression(SyntaxKind.ObjectInitializerExpression, SeparatedList <ExpressionSyntax>(initializers))))
            }))));
        }
        private IEnumerable <ParameterSyntax> GetConstructorParameters(TransportModelEntity entityModel, out List <StatementSyntax> propertyInitializers, out List <ArgumentSyntax> baseConstructorArguments)
        {
            List <ParameterSyntax> result       = new List <ParameterSyntax>();
            List <StatementSyntax> initializers = new List <StatementSyntax>();
            List <ArgumentSyntax>  baseArgs     = new List <ArgumentSyntax>();

            var members     = CsEmitterHelper.GetMembers(entityModel);
            var baseMembers = entityModel.BaseEntity != null
                ? CsEmitterHelper.GetMembers(entityModel.BaseEntity.TransportModelItem, entityModel.BaseEntity.GenericArguments)
                : new Dictionary <string, TransportModelEntityMember>();

            foreach (var member in members)
            {
                if (member.Key != "kind")
                {
                    result.Add(Parameter(List <AttributeListSyntax>(), TokenList(), ParseTypeName(CsEmitterHelper.GetAstModelPropertyTypeName(member.Value, this.settings, true)), Identifier(NameHelper.GetSafeVariableName(member.Key)), null));

                    if (baseMembers.ContainsKey(member.Key))
                    {
                        baseArgs.Add(Argument(IdentifierName(NameHelper.GetSafeVariableName(member.Key))));
                    }
                    else
                    {
                        if (CsEmitterHelper.IsNodeCollection(member.Value.Type))
                        {
                            initializers.Add(
                                ExpressionStatement(
                                    InvocationExpression(
                                        MemberAccessExpression(
                                            SyntaxKind.SimpleMemberAccessExpression,
                                            MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ThisExpression(), IdentifierName(NameHelper.GetSafeVariableName(member.Key))),
                                            IdentifierName("AddRange")),
                                        ArgumentList(SeparatedList <ArgumentSyntax>(new[] { Argument(IdentifierName(NameHelper.GetSafeVariableName(member.Key))) })))));
                        }
                        else
                        {
                            initializers.Add(
                                ExpressionStatement(
                                    AssignmentExpression(
                                        SyntaxKind.SimpleAssignmentExpression,
                                        MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ThisExpression(), IdentifierName(NameHelper.GetSafeVariableName(member.Key))),
                                        IdentifierName(NameHelper.GetSafeVariableName(member.Key)))));
                        }
                    }
                }
            }

            if (entityModel.TsDiscriminant is TransportModelEntityTsDiscriminantBrand brandDiscriminant)
            {
                var member = entityModel.GetMemberByName(brandDiscriminant.BrandPropertyName);
                if (member != null)
                {
                    initializers.Add(
                        ExpressionStatement(
                            AssignmentExpression(
                                SyntaxKind.SimpleAssignmentExpression,
                                MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ThisExpression(), IdentifierName(NameHelper.GetSafeVariableName(member.Name))),
                                ObjectCreationExpression(ParseTypeName(CsEmitterHelper.GetAstModelPropertyTypeName(member, this.settings)), ArgumentList(), null))));
                }
            }

            propertyInitializers     = initializers;
            baseConstructorArguments = baseArgs;
            return(result);
        }
        public StatementSyntax EmitForEntity(TransportModelEntity entity, TransportModelEnum syntaxKindEnum)
        {
            var discriminant = entity.TsDiscriminant as TransportModelEntityTsDiscriminantSyntaxKind;

            var recognizedNodeVarName = "concreteNode";

            var block = Block();
            List <ArgumentSyntax> constructorArguments = new List <ArgumentSyntax>();

            block = block.AddStatements(
                LocalDeclarationStatement(
                    VariableDeclaration(
                        ParseTypeName("var"),
                        SeparatedList <VariableDeclaratorSyntax>(new[]
            {
                VariableDeclarator(recognizedNodeVarName)
                .WithInitializer(EqualsValueClause(CastExpression(ParseTypeName(CsEmitterHelper.GetCSharpModelFullyQualifiedName(entity, this.settings, ModelType.Transport)), IdentifierName(this.nodeParameterName))))
            })))
                );

            foreach (var member in CsEmitterHelper.GetMembers(entity))
            {
                if (member.Key != "kind")
                {
                    if (CsEmitterHelper.IsNode(member.Value.Type))
                    {
                        if (member.Value.Type.IsCollection)
                        {
                            constructorArguments.Add(
                                Argument(
                                    InvocationExpression(
                                        MemberAccessExpression(
                                            SyntaxKind.SimpleMemberAccessExpression,
                                            ThisExpression(),
                                            GenericName(
                                                Identifier(this.convertFromNodeCollectionMethodName),
                                                TypeArgumentList(SeparatedList <TypeSyntax>(new[]
                            {
                                ParseTypeName(CsEmitterHelper.GetCSharpModelFullyQualifiedName(((ITransportModelTypeReferenceTransportModelItem <TransportModelItem>)member.Value.Type).TransportModelItem, this.settings, ModelType.Ast))
                            })))),
                                        ArgumentList(SeparatedList <ArgumentSyntax>(new[]
                            {
                                Argument(
                                    MemberAccessExpression(
                                        SyntaxKind.SimpleMemberAccessExpression,
                                        IdentifierName(recognizedNodeVarName),
                                        IdentifierName(NameHelper.GetSafeVariableName(member.Key))))
                            })))
                                    ));
                        }
                        else
                        {
                            constructorArguments.Add(
                                Argument(
                                    CastExpression(
                                        ParseTypeName(CsEmitterHelper.GetAstModelPropertyTypeName(member.Value, this.settings, true)),
                                        InvocationExpression(
                                            MemberAccessExpression(
                                                SyntaxKind.SimpleMemberAccessExpression,
                                                ThisExpression(),
                                                IdentifierName(this.convertFromNodeMethodName)),
                                            ArgumentList(SeparatedList <ArgumentSyntax>(new[]
                            {
                                Argument(
                                    MemberAccessExpression(
                                        SyntaxKind.SimpleMemberAccessExpression,
                                        IdentifierName(recognizedNodeVarName),
                                        IdentifierName(NameHelper.GetSafeVariableName(member.Key))))
                            })))
                                        )
                                    ));
                        }
                    }
                    else
                    {
                        constructorArguments.Add(
                            Argument(
                                CastExpression(
                                    ParseTypeName(CsEmitterHelper.GetAstModelPropertyTypeName(member.Value, this.settings, true)),
                                    MemberAccessExpression(
                                        SyntaxKind.SimpleMemberAccessExpression,
                                        IdentifierName(recognizedNodeVarName),
                                        IdentifierName(NameHelper.GetSafeVariableName(member.Key))))));
                    }
                }
            }

            block = block.AddStatements(
                LocalDeclarationStatement(
                    VariableDeclaration(
                        ParseTypeName("var"),
                        SeparatedList <VariableDeclaratorSyntax>(new[]
            {
                VariableDeclarator("result")
                .WithInitializer(
                    EqualsValueClause(
                        ObjectCreationExpression(ParseTypeName(CsEmitterHelper.GetCSharpModelFullyQualifiedName(entity, this.settings, ModelType.Ast)))
                        .WithArgumentList(ArgumentList(SeparatedList <ArgumentSyntax>(constructorArguments)))))
            }))
                    ));

            block = block.AddStatements(ReturnStatement(IdentifierName("result")));

            var result = IfStatement(
                BinaryExpression(
                    SyntaxKind.EqualsExpression,
                    MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName(this.nodeParameterName), IdentifierName("kind")),
                    MemberAccessExpression(
                        SyntaxKind.SimpleMemberAccessExpression,
                        IdentifierName(CsEmitterHelper.GetCSharpModelFullyQualifiedName(syntaxKindEnum, this.settings, ModelType.Transport)),
                        IdentifierName(discriminant.SyntaxKindValueName))),
                block);

            return(result);
        }