private void EmitInterface(TransportModelInterface model, ICodeStream output)
        {
            var outputFile = (CodeFileCSharp)output.CreateCodeFile($"{CsEmitterHelper.GetCSharpModelShortName(model, ModelType.Transport)}.cs");

            var unit = CompilationUnit();

            unit = unit.AddUsings(
                UsingDirective(ParseName(nameof(System))));

            var entityInterface = InterfaceDeclaration(CsEmitterHelper.GetCSharpModelShortName(model, ModelType.Transport));

            entityInterface = entityInterface.AddModifiers(Token(SyntaxKind.PublicKeyword));

            if (model.GenericParameters.Count > 0)
            {
                entityInterface = entityInterface.WithTypeParameterList(TypeParameterList(SeparatedList <TypeParameterSyntax>(model.GenericParameters.Select(p => TypeParameter(p.Key)))));

                entityInterface = entityInterface.WithConstraintClauses(List <TypeParameterConstraintClauseSyntax>(
                                                                            model.GenericParameters.Select(p =>
                                                                                                           TypeParameterConstraintClause(
                                                                                                               IdentifierName(p.Key),
                                                                                                               SeparatedList <TypeParameterConstraintSyntax>(new[] { TypeConstraint(ParseTypeName(CsEmitterHelper.GetModelGenericParameterConstraintTypeName(p.Value, ModelType.Transport))) })))));
            }

            List <string> baseTypes = new List <string>();

            foreach (var interfaceModel in model.Interfaces)
            {
                baseTypes.Add(CsEmitterHelper.GetCSharpModelFullyQualifiedName(interfaceModel, this.settings, ModelType.Transport));
            }

            if (baseTypes.Count > 0)
            {
                entityInterface = entityInterface.WithBaseList(BaseList(SeparatedList <BaseTypeSyntax>(baseTypes.Select(t => SimpleBaseType(ParseTypeName(t))))));
            }

            entityInterface = entityInterface.WithMembers(List <MemberDeclarationSyntax>(model.Members.Select(m =>
                                                                                                              PropertyDeclaration(ParseTypeName(CsEmitterHelper.GetPropertyTypeName(m.Value, this.settings, ModelType.Transport)), NameHelper.GetSafeVariableName(m.Value.Name))
                                                                                                              .WithAccessorList(
                                                                                                                  SyntaxFactory.AccessorList(
                                                                                                                      SyntaxFactory.List <AccessorDeclarationSyntax>(new AccessorDeclarationSyntax[]
            {
                SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
                .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)),
                SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
                .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
            })))
                                                                                                              )));

            var nsContainer = NamespaceDeclaration(ParseName(this.settings.CsTransportModelNamespace));

            nsContainer           = nsContainer.AddMembers(entityInterface);
            unit                  = unit.AddMembers(nsContainer);
            outputFile.SyntaxTree = unit.SyntaxTree;
        }
        private void EmitEntity(TransportModelEntity entityModel, ICodeStream output)
        {
            var outputFile = (CodeFileCSharp)output.CreateCodeFile($"{CsEmitterHelper.GetCSharpModelShortName(entityModel, ModelType.Transport)}.cs");

            var unit = CompilationUnit();

            unit = unit.AddUsings(
                UsingDirective(ParseName(nameof(System))));

            var entityClass = ClassDeclaration(CsEmitterHelper.GetCSharpModelShortName(entityModel, ModelType.Transport));

            entityClass = entityClass.AddModifiers(Token(SyntaxKind.PublicKeyword));

            if (entityModel.TsDiscriminant is TransportModelEntityTsDiscriminantSyntaxKind kindDiscriminant)
            {
                entityClass = entityClass.AddMembers(
                    ConstructorDeclaration(CsEmitterHelper.GetCSharpModelShortName(entityModel, ModelType.Transport))
                    .AddModifiers(Token(SyntaxKind.PublicKeyword))
                    .WithBody(Block().AddStatements(
                                  ExpressionStatement(
                                      AssignmentExpression(
                                          SyntaxKind.SimpleAssignmentExpression,
                                          MemberAccessExpression(
                                              SyntaxKind.SimpleMemberAccessExpression,
                                              ThisExpression(),
                                              IdentifierName("kind")),
                                          MemberAccessExpression(
                                              SyntaxKind.SimpleMemberAccessExpression,
                                              IdentifierName($"{this.settings.CsTransportModelNamespace}.SyntaxKind"),
                                              IdentifierName(kindDiscriminant.SyntaxKindValueName)))))));
            }

            if (entityModel.GenericParameters.Count > 0)
            {
                entityClass = entityClass.WithTypeParameterList(TypeParameterList(SeparatedList <TypeParameterSyntax>(entityModel.GenericParameters.Select(p => TypeParameter(p.Key)))));

                entityClass = entityClass.WithConstraintClauses(List <TypeParameterConstraintClauseSyntax>(
                                                                    entityModel.GenericParameters.Select(p =>
                                                                                                         TypeParameterConstraintClause(
                                                                                                             IdentifierName(p.Key),
                                                                                                             SeparatedList <TypeParameterConstraintSyntax>(new[] { TypeConstraint(ParseTypeName(CsEmitterHelper.GetModelGenericParameterConstraintTypeName(p.Value, ModelType.Transport))) })))));
            }

            List <string> baseTypes = new List <string>();

            if (entityModel.BaseEntity != null)
            {
                baseTypes.Add(CsEmitterHelper.GetCSharpModelReferenceName(entityModel.BaseEntity, this.settings, ModelType.Transport));
            }

            foreach (var interfaceModel in entityModel.Interfaces)
            {
                baseTypes.Add(CsEmitterHelper.GetCSharpModelFullyQualifiedName(interfaceModel, this.settings, ModelType.Transport));
            }

            if (baseTypes.Count > 0)
            {
                entityClass = entityClass.WithBaseList(BaseList(SeparatedList <BaseTypeSyntax>(baseTypes.Select(t => SimpleBaseType(ParseTypeName(t))))));
            }

            entityClass = entityClass.AddMembers(entityModel.Members.Select(m =>
                                                                            PropertyDeclaration(ParseTypeName(CsEmitterHelper.GetPropertyTypeName(m.Value, this.settings, ModelType.Transport)), NameHelper.GetSafeVariableName(m.Value.Name))
                                                                            .WithAccessorList(
                                                                                SyntaxFactory.AccessorList(
                                                                                    SyntaxFactory.List <AccessorDeclarationSyntax>(new AccessorDeclarationSyntax[]
            {
                SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
                .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)),
                SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
                .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
            })))
                                                                            .AddModifiers(Token(SyntaxKind.PublicKeyword))
                                                                            ).ToArray <MemberDeclarationSyntax>());

            var nsContainer = NamespaceDeclaration(ParseName(this.settings.CsTransportModelNamespace));

            nsContainer           = nsContainer.AddMembers(entityClass);
            unit                  = unit.AddMembers(nsContainer);
            outputFile.SyntaxTree = unit.SyntaxTree;
        }
        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))))
            }))));
        }