private void AddArrayHandler(
            ClassBuilder classBuilder,
            ConstructorBuilder constructorBuilder,
            MethodBuilder methodBuilder,
            ListTypeDescriptor listTypeDescriptor,
            HashSet <string> processed,
            bool isNonNullable)
        {
            methodBuilder.AddParameter(
                ParameterBuilder.New()
                .SetType(listTypeDescriptor.ToEntityIdBuilder())
                .SetName(ListParamName));
            var listVarName = listTypeDescriptor.Name.WithLowerFirstChar() + "s";

            if (!isNonNullable)
            {
                methodBuilder.AddCode(EnsureProperNullability(ListParamName, isNonNullable));
            }

            methodBuilder.AddCode(
                AssignmentBuilder.New()
                .SetLefthandSide($"var {listVarName}")
                .SetRighthandSide(
                    CodeBlockBuilder.New()
                    .AddCode("new ")
                    .AddCode(TypeNames.List)
                    .AddCode("<")
                    .AddCode(
                        listTypeDescriptor.InnerType.ToBuilder()
                        .SkipTrailingSpace())
                    .AddCode(">")
                    .AddCode("()")));
            methodBuilder.AddEmptyLine();

            var loopbuilder = ForEachBuilder.New()
                              .SetLoopHeader(
                CodeBlockBuilder.New()
                .AddCode(listTypeDescriptor.InnerType.ToEntityIdBuilder())
                .AddCode($"child in {ListParamName}"))
                              .AddCode(
                MethodCallBuilder.New()
                .SetPrefix($"{listVarName}.")
                .SetMethodName("Add")
                .AddArgument(
                    BuildMapMethodCall(
                        listTypeDescriptor.InnerType,
                        "child")));

            methodBuilder.AddCode(loopbuilder);
            methodBuilder.AddEmptyLine();
            methodBuilder.AddCode($"return {listVarName};");

            AddMapMethod(
                listVarName,
                listTypeDescriptor.InnerType,
                classBuilder,
                constructorBuilder,
                processed);
        }
Example #2
0
        private void AddEntityHandler(
            ClassBuilder classBuilder,
            ConstructorBuilder constructorBuilder,
            MethodBuilder method,
            ComplexTypeDescriptor complexTypeDescriptor,
            HashSet <string> processed,
            bool isNonNullable)
        {
            method.AddParameter(
                EntityIdParamName,
                x => x.SetType(TypeNames.EntityId.MakeNullable(!isNonNullable)));

            if (!isNonNullable)
            {
                method.AddCode(
                    EnsureProperNullability(
                        EntityIdParamName,
                        isNonNullable));
            }

            if (complexTypeDescriptor is InterfaceTypeDescriptor interfaceTypeDescriptor)
            {
                foreach (ObjectTypeDescriptor implementee in interfaceTypeDescriptor.ImplementedBy)
                {
                    NameString dataMapperName =
                        CreateEntityMapperName(
                            implementee.RuntimeType.Name,
                            implementee.Name);

                    if (processed.Add(dataMapperName))
                    {
                        var dataMapperType =
                            TypeNames.IEntityMapper.WithGeneric(
                                CreateEntityTypeName(implementee.Name),
                                implementee.RuntimeType.Name);

                        AddConstructorAssignedField(
                            dataMapperType,
                            GetFieldName(dataMapperName),
                            classBuilder,
                            constructorBuilder);
                    }

                    method.AddCode(GenerateEntityHandlerIfClause(implementee, isNonNullable));
                }
            }

            method.AddCode(ExceptionBuilder.New(TypeNames.NotSupportedException));
        }
Example #3
0
        private void GenerateIfForEachImplementedBy(
            MethodBuilder method,
            ComplexTypeDescriptor complexTypeDescriptor,
            Func <ObjectTypeDescriptor, IfBuilder> generator)
        {
            if (!(complexTypeDescriptor is InterfaceTypeDescriptor interfaceTypeDescriptor) ||
                !interfaceTypeDescriptor.ImplementedBy.Any())
            {
                return;
            }

            var ifChain = generator(interfaceTypeDescriptor.ImplementedBy.First());

            foreach (ObjectTypeDescriptor objectTypeDescriptor in
                     interfaceTypeDescriptor.ImplementedBy.Skip(1))
            {
                ifChain.AddIfElse(
                    generator(objectTypeDescriptor)
                    .SkipIndents());
            }

            ifChain.AddElse(
                CodeInlineBuilder.New()
                .SetText($"throw new {TypeNames.NotSupportedException}();"));

            method.AddCode(ifChain);
        }
Example #4
0
        private void AddDataTypeDeserializerMethod(
            ClassBuilder classBuilder,
            MethodBuilder methodBuilder,
            ComplexTypeDescriptor complexTypeDescriptor,
            HashSet <string> processed)
        {
            if (complexTypeDescriptor is InterfaceTypeDescriptor interfaceTypeDescriptor)
            {
                AddInterfaceDataTypeDeserializerToMethod(methodBuilder, interfaceTypeDescriptor);
            }
            else
            {
                MethodCallBuilder returnStatement = MethodCallBuilder
                                                    .New()
                                                    .SetReturn()
                                                    .SetNew()
                                                    .SetMethodName(complexTypeDescriptor.Name);

                foreach (PropertyDescriptor property in complexTypeDescriptor.Properties)
                {
                    returnStatement.AddArgument(BuildUpdateMethodCall(property));
                }

                methodBuilder.AddCode(returnStatement);
            }

            AddRequiredDeserializeMethods(complexTypeDescriptor, classBuilder, processed);
        }
Example #5
0
        public static CodeBlockBuilder AddBody(this MethodBuilder method)
        {
            var code = CodeBlockBuilder.New();

            method.AddCode(code);
            return(code);
        }
Example #6
0
        private void AddScalarTypeDeserializerMethod(
            MethodBuilder methodBuilder,
            ILeafTypeDescriptor namedType)
        {
            string deserializeMethod = namedType.SerializationType.ToString() switch
            {
                TypeNames.String => nameof(JsonElement.GetString),
                TypeNames.Uri => nameof(JsonElement.GetString),
                TypeNames.Byte => nameof(JsonElement.GetByte),
                TypeNames.ByteArray => nameof(JsonElement.GetBytesFromBase64),
                TypeNames.Int16 => nameof(JsonElement.GetInt16),
                TypeNames.Int32 => nameof(JsonElement.GetInt32),
                TypeNames.Int64 => nameof(JsonElement.GetInt64),
                TypeNames.UInt16 => nameof(JsonElement.GetUInt16),
                TypeNames.UInt32 => nameof(JsonElement.GetUInt32),
                TypeNames.UInt64 => nameof(JsonElement.GetUInt64),
                TypeNames.Single => nameof(JsonElement.GetSingle),
                TypeNames.Double => nameof(JsonElement.GetDouble),
                TypeNames.Decimal => nameof(JsonElement.GetDecimal),
                TypeNames.DateTimeOffset => nameof(JsonElement.GetString),
                TypeNames.DateTime => nameof(JsonElement.GetString),
                TypeNames.TimeSpan => nameof(JsonElement.GetString),
                TypeNames.Boolean => nameof(JsonElement.GetBoolean),
                TypeNames.Guid => nameof(JsonElement.GetGuid),
                _ => throw new NotSupportedException("Serialization format not supported.")
            };

            methodBuilder.AddCode(
                $"return {GetFieldName(namedType.Name)}Parser.Parse({_objParamName}.Value" +
                $".{deserializeMethod}()!);");
        }
    }
        private void AddScalarTypeDeserializerMethod(
            MethodBuilder methodBuilder,
            NamedTypeDescriptor namedType)
        {
            string deserializeMethod = namedType.GraphQLTypeName?.Value switch
            {
                String => nameof(JsonElement.GetString),
                ID => nameof(JsonElement.GetString),
                Url => nameof(JsonElement.GetString),
                Uuid => nameof(JsonElement.GetString),
                DateTime => nameof(JsonElement.GetString),
                Date => nameof(JsonElement.GetString),
                TimeSpan => nameof(JsonElement.GetString),
                Boolean => nameof(JsonElement.GetBoolean),
                Byte => nameof(JsonElement.GetByte),
                Short => nameof(JsonElement.GetInt16),
                Int => nameof(JsonElement.GetInt32),
                Long => nameof(JsonElement.GetInt64),
                Float => nameof(JsonElement.GetDouble),
                Decimal => nameof(JsonElement.GetDecimal),
                ByteArray => nameof(JsonElement.GetBytesFromBase64),
                _ => "Get" + (namedType.SerializationType?.Split('.').Last() ??
                              namedType.Name.WithCapitalFirstChar())
            };

            methodBuilder.AddCode(
                $"return {namedType.Name.ToFieldName()}Parser.Parse({_objParamName}.Value" +
                $".{deserializeMethod}()!);");
        }
    }
Example #8
0
        private void AddComplexDataHandler(
            ClassBuilder classBuilder,
            ConstructorBuilder constructorBuilder,
            MethodBuilder method,
            ComplexTypeDescriptor complexTypeDescriptor,
            HashSet <string> processed,
            bool isNonNullable)
        {
            if (complexTypeDescriptor.ParentRuntimeType is null)
            {
                throw new InvalidOperationException();
            }

            method.AddParameter(
                ParameterBuilder.New()
                .SetType(complexTypeDescriptor.ParentRuntimeType.ToString())
                .SetName(_dataParameterName));

            if (!isNonNullable)
            {
                method.AddCode(
                    EnsureProperNullability(
                        _dataParameterName,
                        isNonNullable));
            }

            var variableName = "returnValue";

            method.AddCode($"{complexTypeDescriptor.RuntimeType.Name} {variableName} = default!;");
            method.AddEmptyLine();

            GenerateIfForEachImplementedBy(
                method,
                complexTypeDescriptor,
                o => GenerateComplexDataInterfaceIfClause(o, variableName));

            method.AddCode($"return {variableName};");

            AddRequiredMapMethods(
                _dataParameterName,
                complexTypeDescriptor,
                classBuilder,
                constructorBuilder,
                processed);
        }
Example #9
0
        private void AddInterfaceDataTypeDeserializerToMethod(
            MethodBuilder methodBuilder,
            InterfaceTypeDescriptor interfaceTypeDescriptor)
        {
            methodBuilder.AddCode(
                AssignmentBuilder
                .New()
                .SetLefthandSide($"var {_typename}")
                .SetRighthandSide(MethodCallBuilder
                                  .Inline()
                                  .SetMethodName(
                                      _obj,
                                      nameof(Nullable <EntityId> .Value),
                                      nameof(JsonElement.GetProperty))
                                  .AddArgument(__typename.AsStringToken())
                                  .Chain(x => x.SetMethodName(nameof(JsonElement.GetString)))));

            // If the type is an interface
            foreach (ObjectTypeDescriptor concreteType in interfaceTypeDescriptor.ImplementedBy)
            {
                MethodCallBuilder returnStatement = MethodCallBuilder
                                                    .New()
                                                    .SetReturn()
                                                    .SetNew()
                                                    .SetMethodName(
                    $"{concreteType.RuntimeType.Namespace}.State." +
                    CreateDataTypeName(concreteType.Name))
                                                    .AddArgument("typename");

                foreach (PropertyDescriptor property in concreteType.Properties)
                {
                    returnStatement.AddArgument(
                        CodeBlockBuilder
                        .New()
                        .AddCode($"{GetParameterName(property.Name)}: ")
                        .AddCode(BuildUpdateMethodCall(property)));
                }

                IfBuilder ifStatement = IfBuilder
                                        .New()
                                        .SetCondition(
                    $"typename?.Equals(\"{concreteType.Name}\", " +
                    $"{TypeNames.OrdinalStringComparison}) ?? false")
                                        .AddCode(returnStatement);

                methodBuilder
                .AddEmptyLine()
                .AddCode(ifStatement);
            }

            methodBuilder
            .AddEmptyLine()
            .AddCode(ExceptionBuilder.New(TypeNames.NotSupportedException));
        }
Example #10
0
        private void AddArrayHandler(
            ClassBuilder classBuilder,
            MethodBuilder methodBuilder,
            ListTypeDescriptor listTypeDescriptor,
            HashSet <string> processed)
        {
            var listVarName = listTypeDescriptor.Name.WithLowerFirstChar() + "s";

            methodBuilder.AddCode(
                AssignmentBuilder.New()
                .SetLefthandSide($"var {listVarName}")
                .SetRighthandSide(
                    CodeBlockBuilder.New()
                    .AddCode("new ")
                    .AddCode(TypeNames.List)
                    .AddCode("<")
                    .AddCode(listTypeDescriptor.InnerType.ToEntityIdBuilder()
                             .SkipTrailingSpace())
                    .AddCode(">")
                    .AddCode("()")
                    ));
            methodBuilder.AddEmptyLine();

            methodBuilder.AddCode(
                ForEachBuilder.New()
                .SetLoopHeader(
                    $"{TypeNames.JsonElement} child in {_objParamName}.Value.EnumerateArray()")
                .AddCode(
                    MethodCallBuilder.New()
                    .SetPrefix($"{listVarName}.")
                    .SetMethodName("Add")
                    .AddArgument(
                        BuildUpdateMethodCall(listTypeDescriptor.InnerType, "child"))));

            methodBuilder.AddEmptyLine();
            methodBuilder.AddCode($"return {listVarName};");

            AddDeserializeMethod(listTypeDescriptor.InnerType, classBuilder, processed);
        }
Example #11
0
        private void AddDataHandler(
            ClassBuilder classBuilder,
            ConstructorBuilder constructorBuilder,
            MethodBuilder method,
            ComplexTypeDescriptor namedTypeDescriptor,
            HashSet <string> processed,
            bool isNonNullable)
        {
            method.AddParameter(
                _dataParameterName,
                x => x.SetType(namedTypeDescriptor.ParentRuntimeType !.ToString()));

            if (!isNonNullable)
            {
                method.AddCode(EnsureProperNullability(_dataParameterName, isNonNullable));
            }

            var variableName = "returnValue";

            method.AddCode($"{namedTypeDescriptor.RuntimeType.Name} {variableName} = default!;");
            method.AddEmptyLine();

            GenerateIfForEachImplementedBy(
                method,
                namedTypeDescriptor,
                o => GenerateDataInterfaceIfClause(o, isNonNullable, variableName));

            method.AddCode($"return {variableName};");

            AddRequiredMapMethods(
                _dataParameterName,
                namedTypeDescriptor,
                classBuilder,
                constructorBuilder,
                processed);
        }
Example #12
0
        private void AddArrayHandler(
            ClassBuilder classBuilder,
            MethodBuilder methodBuilder,
            ListTypeDescriptor listTypeDescriptor,
            HashSet <string> processed)
        {
            var listVarName = GetParameterName(listTypeDescriptor.Name) + "s";

            methodBuilder
            .AddCode(
                AssignmentBuilder
                .New()
                .SetLefthandSide($"var {listVarName}")
                .SetRighthandSide(
                    CodeBlockBuilder
                    .New()
                    .AddCode("new ")
                    .AddCode(TypeNames.List)
                    .AddCode("<")
                    .AddCode(
                        listTypeDescriptor.InnerType
                        .ToEntityIdBuilder()
                        .SkipTrailingSpace())
                    .AddCode(">")
                    .AddCode("()")))
            .AddEmptyLine()
            .AddCode(
                ForEachBuilder
                .New()
                .SetLoopHeader(
                    $"{TypeNames.JsonElement} {_child} in {_obj}.Value.EnumerateArray()")
                .AddCode(
                    MethodCallBuilder
                    .New()
                    .SetMethodName(listVarName, nameof(List <object> .Add))
                    .AddArgument(
                        BuildUpdateMethodCall(
                            listTypeDescriptor.InnerType,
                            CodeInlineBuilder.From(_child)))))
            .AddEmptyLine()
            .AddCode($"return {listVarName};");

            AddDeserializeMethod(listTypeDescriptor.InnerType, classBuilder, processed);
        }
        private void AddDeserializeMethod(
            ITypeDescriptor typeReference,
            ClassBuilder classBuilder,
            HashSet <string> processed)
        {
            string methodName = DeserializerMethodNameFromTypeName(typeReference);

            if (processed.Add(methodName))
            {
                MethodBuilder methodBuilder = classBuilder
                                              .AddMethod()
                                              .SetPrivate()
                                              .SetReturnType(typeReference.ToEntityIdBuilder())
                                              .SetName(methodName);

                methodBuilder
                .AddParameter(_obj)
                .SetType(TypeNames.JsonElement.MakeNullable());

                if (typeReference.IsEntityType() || typeReference.ContainsEntity())
                {
                    methodBuilder
                    .AddParameter(_entityIds)
                    .SetType(TypeNames.ISet.WithGeneric(TypeNames.EntityId));
                }

                IfBuilder jsonElementNullCheck = IfBuilder
                                                 .New()
                                                 .SetCondition($"!{_obj}.HasValue")
                                                 .AddCode(
                    typeReference.IsNonNullableType()
                            ? ExceptionBuilder.New(TypeNames.ArgumentNullException)
                            : CodeLineBuilder.From("return null;"));

                methodBuilder
                .AddCode(jsonElementNullCheck)
                .AddEmptyLine();

                AddDeserializeMethodBody(classBuilder, methodBuilder, typeReference, processed);
            }
        }
        private void AddScalarTypeDeserializerMethod(
            MethodBuilder methodBuilder,
            ILeafTypeDescriptor namedType)
        {
            string deserializeMethod = namedType.SerializationType.ToString() switch
            {
                TypeNames.String => nameof(JsonElement.GetString),
                TypeNames.Uri => nameof(JsonElement.GetString),
                TypeNames.Byte => nameof(JsonElement.GetByte),
                TypeNames.ByteArray => nameof(JsonElement.GetBytesFromBase64),
                TypeNames.Int16 => nameof(JsonElement.GetInt16),
                TypeNames.Int32 => nameof(JsonElement.GetInt32),
                TypeNames.Int64 => nameof(JsonElement.GetInt64),
                TypeNames.UInt16 => nameof(JsonElement.GetUInt16),
                TypeNames.UInt32 => nameof(JsonElement.GetUInt32),
                TypeNames.UInt64 => nameof(JsonElement.GetUInt64),
                TypeNames.Single => nameof(JsonElement.GetSingle),
                TypeNames.Double => nameof(JsonElement.GetDouble),
                TypeNames.Decimal => nameof(JsonElement.GetDecimal),
                TypeNames.DateTimeOffset => nameof(JsonElement.GetString),
                TypeNames.DateTime => nameof(JsonElement.GetString),
                TypeNames.TimeSpan => nameof(JsonElement.GetString),
                TypeNames.Boolean => nameof(JsonElement.GetBoolean),
                TypeNames.Guid => nameof(JsonElement.GetGuid),
                _ => throw new NotSupportedException("Serialization format not supported.")
            };

            methodBuilder.AddCode(
                MethodCallBuilder
                .New()
                .SetReturn()
                .SetMethodName(
                    GetFieldName(namedType.Name) + "Parser",
                    nameof(ILeafValueParser <object, object> .Parse))
                .AddArgument(MethodCallBuilder
                             .Inline()
                             .SetMethodName(_obj, nameof(Nullable <JsonElement> .Value), deserializeMethod)
                             .SetNullForgiving()));
        }
    }
        private void AddDataHandler(
            ClassBuilder classBuilder,
            ConstructorBuilder constructorBuilder,
            MethodBuilder method,
            NamedTypeDescriptor namedTypeDescriptor,
            HashSet <string> processed,
            bool isNonNullable)
        {
            method.AddParameter(
                ParameterBuilder.New()
                .SetType(
                    $"global::{namedTypeDescriptor.Namespace}.State." +
                    DataTypeNameFromTypeName(namedTypeDescriptor.GraphQLTypeName))
                .SetName(DataParamName));

            if (!isNonNullable)
            {
                method.AddCode(
                    EnsureProperNullability(
                        DataParamName,
                        isNonNullable));
            }

            var variableName = "returnValue";

            method.AddCode($"{namedTypeDescriptor.Name} {variableName} = default!;");
            method.AddEmptyLine();

            if (namedTypeDescriptor.ImplementedBy.Any())
            {
                var ifChain = InterfaceImplementeeIf(namedTypeDescriptor.ImplementedBy[0]);

                foreach (NamedTypeDescriptor interfaceImplementee in
                         namedTypeDescriptor.ImplementedBy.Skip(1))
                {
                    var singleIf = InterfaceImplementeeIf(interfaceImplementee).SkipIndents();
                    ifChain.AddIfElse(singleIf);
                }

                ifChain.AddElse(
                    CodeInlineBuilder.New()
                    .SetText($"throw new {TypeNames.NotSupportedException}();"));

                method.AddCode(ifChain);
            }

            IfBuilder InterfaceImplementeeIf(NamedTypeDescriptor interfaceImplementee)
            {
                var ifCorrectType = IfBuilder.New();

                if (isNonNullable)
                {
                    ifCorrectType.SetCondition(
                        $"{DataParamName}.__typename.Equals(\"" +
                        $"{interfaceImplementee.GraphQLTypeName}\", " +
                        $"{TypeNames.OrdinalStringComparisson})");
                }
                else
                {
                    ifCorrectType.SetCondition(
                        $"{DataParamName}?.__typename.Equals(\"" +
                        $"{interfaceImplementee.GraphQLTypeName}\", " +
                        $"{TypeNames.OrdinalStringComparisson}) ?? false");
                }


                var constructorCall = MethodCallBuilder.New()
                                      .SetPrefix($"{variableName} = new ")
                                      .SetMethodName(interfaceImplementee.Name);

                foreach (PropertyDescriptor prop in interfaceImplementee.Properties)
                {
                    var propAccess = $"{DataParamName}.{prop.Name}";
                    if (prop.Type.IsEntityType())
                    {
                        constructorCall.AddArgument(
                            BuildMapMethodCall(
                                DataParamName,
                                prop,
                                true));
                    }
                    else
                    {
                        constructorCall.AddArgument(
                            $"{propAccess} ?? throw new {TypeNames.ArgumentNullException}()");
                    }
                }

                ifCorrectType.AddCode(constructorCall);
                return(ifCorrectType);
            }

            method.AddCode($"return {variableName};");

            AddRequiredMapMethods(
                DataParamName,
                namedTypeDescriptor,
                classBuilder,
                constructorBuilder,
                processed);
        }
Example #16
0
        private void AddUpdateEntityMethod(
            ClassBuilder classBuilder,
            MethodBuilder methodBuilder,
            INamedTypeDescriptor namedTypeDescriptor,
            HashSet <string> processed)
        {
            var entityIdVarName = "entityId";

            methodBuilder.AddCode(
                AssignmentBuilder.New()
                .SetLefthandSide(
                    CodeBlockBuilder.New()
                    .AddCode(TypeNames.EntityId)
                    .AddCode($" {entityIdVarName}"))
                .SetRighthandSide($"{_extractIdFieldName}({_objParamName}.Value)"));

            methodBuilder.AddCode($"{_entityIdsParam}.Add({entityIdVarName});");
            methodBuilder.AddEmptyLine();

            var entityVarName = "entity";

            if (namedTypeDescriptor is InterfaceTypeDescriptor interfaceTypeDescriptor)
            {
                // If the type is an interface
                foreach (ObjectTypeDescriptor concreteType in interfaceTypeDescriptor.ImplementedBy)
                {
                    methodBuilder.AddEmptyLine();
                    var ifStatement = IfBuilder.New()
                                      .SetCondition(
                        $"entityId.Name.Equals(\"{concreteType.Name}\", " +
                        $"{TypeNames.OrdinalStringComparison})");

                    var entityTypeName = CreateEntityTypeName(concreteType.Name);

                    WriteEntityLoader(
                        ifStatement,
                        entityTypeName,
                        entityVarName,
                        entityIdVarName);

                    WritePropertyAssignments(
                        ifStatement,
                        concreteType.Properties,
                        entityVarName);

                    ifStatement.AddEmptyLine();
                    ifStatement.AddCode($"return {entityIdVarName};");
                    methodBuilder.AddCode(ifStatement);
                }

                methodBuilder.AddEmptyLine();
                methodBuilder.AddCode($"throw new {TypeNames.NotSupportedException}();");
            }
            else if (namedTypeDescriptor is ComplexTypeDescriptor complexTypeDescriptor)
            {
                WriteEntityLoader(
                    methodBuilder,
                    CreateEntityTypeName(namedTypeDescriptor.Name),
                    entityVarName,
                    entityIdVarName);

                WritePropertyAssignments(
                    methodBuilder,
                    complexTypeDescriptor.Properties,
                    entityVarName);

                methodBuilder.AddEmptyLine();
                methodBuilder.AddCode($"return {entityIdVarName};");
            }

            AddRequiredDeserializeMethods(
                namedTypeDescriptor,
                classBuilder,
                processed);
        }
        protected override void Generate(
            CodeWriter writer,
            ITypeDescriptor typeDescriptor,
            out string fileName)
        {
            var(classBuilder, constructorBuilder) = CreateClassBuilder(false);

            NamedTypeDescriptor descriptor = (NamedTypeDescriptor)typeDescriptor.NamedType();

            // Setup class
            fileName = descriptor.ExtractMapperName();

            classBuilder
            .AddImplements(
                TypeNames.IEntityMapper
                .WithGeneric(descriptor.ExtractTypeName(), descriptor.Name))
            .SetName(fileName);

            constructorBuilder.SetTypeName(descriptor.Name);

            if (descriptor.ContainsEntity())
            {
                AddConstructorAssignedField(
                    TypeNames.IEntityStore,
                    StoreFieldName,
                    classBuilder,
                    constructorBuilder);
            }

            // Define map method
            MethodBuilder mapMethod = MethodBuilder.New()
                                      .SetName(_mapMethodName)
                                      .SetAccessModifier(AccessModifier.Public)
                                      .SetReturnType(descriptor.Name)
                                      .AddParameter(
                ParameterBuilder.New()
                .SetType(
                    descriptor.Kind == TypeKind.EntityType
                                ? EntityTypeNameFromGraphQLTypeName(descriptor.GraphQLTypeName)
                                : descriptor.Name)
                .SetName(_entityParamName));

            var constructorCall =
                MethodCallBuilder
                .New()
                .SetMethodName($"return new {descriptor.Name}");

            if (typeDescriptor is NamedTypeDescriptor namedTypeDescriptor)
            {
                foreach (PropertyDescriptor property in namedTypeDescriptor.Properties)
                {
                    constructorCall.AddArgument(BuildMapMethodCall(_entityParamName, property));
                }
            }

            mapMethod.AddCode(constructorCall);

            if (constructorBuilder.HasParameters())
            {
                classBuilder.AddConstructor(constructorBuilder);
            }

            classBuilder.AddMethod(mapMethod);

            var processed = new HashSet <string>();

            AddRequiredMapMethods(
                _entityParamName,
                descriptor,
                classBuilder,
                constructorBuilder,
                processed);

            CodeFileBuilder
            .New()
            .SetNamespace(descriptor.Namespace)
            .AddType(classBuilder)
            .Build(writer);
        }
Example #18
0
        private void AddDataTypeDeserializerMethod(
            ClassBuilder classBuilder,
            MethodBuilder methodBuilder,
            NamedTypeDescriptor namedTypeDescriptor,
            HashSet <string> processed)
        {
            if (namedTypeDescriptor.IsInterface)
            {
                methodBuilder.AddCode(
                    "var typename = obj.Value.GetProperty(\"__typename\").GetString();");

                // If the type is an interface
                foreach (NamedTypeDescriptor concreteType in namedTypeDescriptor.ImplementedBy)
                {
                    methodBuilder.AddEmptyLine();
                    var ifStatement = IfBuilder.New()
                                      .SetCondition(
                        $"typename?.Equals(\"{concreteType.GraphQLTypeName}\", " +
                        $"{TypeNames.OrdinalStringComparisson}) ?? false");

                    var dataTypeName = $"global::{concreteType.Namespace}.State."
                                       + DataTypeNameFromTypeName(concreteType.GraphQLTypeName);

                    var returnStatement = MethodCallBuilder.New()
                                          .SetPrefix("return new ")
                                          .SetMethodName(dataTypeName);

                    returnStatement.AddArgument("typename");
                    foreach (PropertyDescriptor property in concreteType.Properties)
                    {
                        returnStatement.AddArgument(
                            CodeBlockBuilder.New()
                            .AddCode($"{property.Name.WithLowerFirstChar()}: ")
                            .AddCode(BuildUpdateMethodCall(property)));
                    }

                    ifStatement.AddCode(returnStatement);
                    methodBuilder.AddCode(ifStatement);
                }

                methodBuilder.AddEmptyLine();
                methodBuilder.AddCode($"throw new {TypeNames.NotSupportedException}();");
            }
            else
            {
                var returnStatement = MethodCallBuilder.New()
                                      .SetPrefix("return new ")
                                      .SetMethodName(namedTypeDescriptor.Name);

                foreach (PropertyDescriptor property in namedTypeDescriptor.Properties)
                {
                    returnStatement.AddArgument(BuildUpdateMethodCall(property));
                }

                methodBuilder.AddCode(returnStatement);
            }

            AddRequiredDeserializeMethods(
                namedTypeDescriptor,
                classBuilder,
                processed);
        }
        private void AddEntityHandler(
            ClassBuilder classBuilder,
            ConstructorBuilder constructorBuilder,
            MethodBuilder method,
            NamedTypeDescriptor namedTypeDescriptor,
            HashSet <string> processed,
            bool isNonNullable)
        {
            var nullabilityAdditive = "?";

            if (isNonNullable)
            {
                nullabilityAdditive = "";
            }

            method.AddParameter(
                ParameterBuilder.New()
                .SetType(TypeNames.EntityId + nullabilityAdditive)
                .SetName(EntityIdParamName));

            if (!isNonNullable)
            {
                method.AddCode(
                    EnsureProperNullability(
                        EntityIdParamName,
                        isNonNullable));
            }


            foreach (NamedTypeDescriptor implementee in namedTypeDescriptor.ImplementedBy)
            {
                var dataMapperName =
                    EntityMapperNameFromGraphQLTypeName(
                        implementee.Name,
                        implementee.GraphQLTypeName);

                if (processed.Add(dataMapperName))
                {
                    var dataMapperType =
                        $"{TypeNames.IEntityMapper}<" +
                        $"{EntityTypeNameFromGraphQLTypeName(implementee.GraphQLTypeName)}, " +
                        $"{implementee.Name}>";

                    AddConstructorAssignedField(
                        dataMapperType,
                        dataMapperName.ToFieldName(),
                        classBuilder,
                        constructorBuilder);
                }
            }

            foreach (NamedTypeDescriptor interfaceImplementee in namedTypeDescriptor.ImplementedBy)
            {
                method.AddCode(InterfaceImplementeeIf(interfaceImplementee));
            }

            method.AddCode(ExceptionBuilder.New(TypeNames.NotSupportedException));

            IfBuilder InterfaceImplementeeIf(NamedTypeDescriptor interfaceImplementee)
            {
                var dataMapperName =
                    EntityMapperNameFromGraphQLTypeName(
                        interfaceImplementee.Name,
                        interfaceImplementee.GraphQLTypeName)
                    .ToFieldName();

                var ifCorrectType = IfBuilder.New();

                if (isNonNullable)
                {
                    ifCorrectType.SetCondition(
                        $"{EntityIdParamName}.Name.Equals(\"" +
                        $"{interfaceImplementee.GraphQLTypeName}\", " +
                        $"{TypeNames.OrdinalStringComparisson})");
                }
                else
                {
                    ifCorrectType.SetCondition(
                        $"{EntityIdParamName}.Value.Name.Equals(\"" +
                        $"{interfaceImplementee.GraphQLTypeName}\", " +
                        $"{TypeNames.OrdinalStringComparisson})");
                }

                MethodCallBuilder constructorCall = MethodCallBuilder.New()
                                                    .SetPrefix($"return {dataMapperName}.")
                                                    .SetWrapArguments()
                                                    .SetMethodName(nameof(IEntityMapper <object, object> .Map));

                MethodCallBuilder argument = MethodCallBuilder.New()
                                             .SetMethodName($"{StoreFieldName}.{nameof(IEntityStore.GetEntity)}")
                                             .SetDetermineStatement(false)
                                             .AddGeneric(
                    EntityTypeNameFromGraphQLTypeName(interfaceImplementee.GraphQLTypeName))
                                             .AddArgument(isNonNullable ? EntityIdParamName : $"{EntityIdParamName}.Value");

                constructorCall.AddArgument(
                    NullCheckBuilder.New()
                    .SetDetermineStatement(false)
                    .SetCondition(argument)
                    .SetCode(ExceptionBuilder
                             .New(TypeNames.GraphQLClientException)
                             .SetDetermineStatement(false)));

                method.AddEmptyLine();
                ifCorrectType.AddCode(constructorCall);
                return(ifCorrectType);
            }
        }
Example #20
0
        private void AddUpdateEntityMethod(
            ClassBuilder classBuilder,
            MethodBuilder methodBuilder,
            INamedTypeDescriptor namedTypeDescriptor,
            HashSet <string> processed)
        {
            methodBuilder.AddCode(
                AssignmentBuilder
                .New()
                .SetLefthandSide($"{TypeNames.EntityId} {_entityId}")
                .SetRighthandSide(
                    MethodCallBuilder
                    .Inline()
                    .SetMethodName(_extractId)
                    .AddArgument($"{_obj}.{nameof(Nullable<EntityId>.Value)}")));

            methodBuilder.AddCode(
                MethodCallBuilder
                .New()
                .SetMethodName(_entityIds, nameof(List <object> .Add))
                .AddArgument(_entityId));

            methodBuilder.AddEmptyLine();

            if (namedTypeDescriptor is InterfaceTypeDescriptor interfaceTypeDescriptor)
            {
                // If the type is an interface
                foreach (ObjectTypeDescriptor concreteType in interfaceTypeDescriptor.ImplementedBy)
                {
                    IfBuilder ifStatement = IfBuilder
                                            .New()
                                            .SetCondition(
                        MethodCallBuilder
                        .Inline()
                        .SetMethodName(
                            _entityId,
                            nameof(EntityId.Name),
                            nameof(string.Equals))
                        .AddArgument(concreteType.Name.AsStringToken())
                        .AddArgument(TypeNames.OrdinalStringComparison));

                    var entityTypeName = CreateEntityTypeName(concreteType.Name);

                    WriteEntityLoader(
                        ifStatement,
                        entityTypeName);

                    WritePropertyAssignments(
                        ifStatement,
                        concreteType.Properties);

                    ifStatement
                    .AddEmptyLine()
                    .AddCode($"return {_entityId};");

                    methodBuilder
                    .AddEmptyLine()
                    .AddCode(ifStatement);
                }

                methodBuilder.AddEmptyLine();
                methodBuilder.AddCode(ExceptionBuilder.New(TypeNames.NotSupportedException));
            }
            else if (namedTypeDescriptor is ComplexTypeDescriptor complexTypeDescriptor)
            {
                WriteEntityLoader(methodBuilder, CreateEntityTypeName(namedTypeDescriptor.Name));
                WritePropertyAssignments(methodBuilder, complexTypeDescriptor.Properties);

                methodBuilder.AddEmptyLine();
                methodBuilder.AddCode($"return {_entityId};");
            }

            AddRequiredDeserializeMethods(namedTypeDescriptor, classBuilder, processed);
        }
        private void AddArrayHandler(
            ClassBuilder classBuilder,
            ConstructorBuilder constructorBuilder,
            MethodBuilder methodBuilder,
            ListTypeDescriptor listTypeDescriptor,
            HashSet <string> processed,
            bool isNonNullable)
        {
            methodBuilder
            .AddParameter(_list)
            .SetType(listTypeDescriptor.ToEntityIdBuilder());

            var listVarName = GetParameterName(listTypeDescriptor.Name) + "s";

            if (!isNonNullable)
            {
                methodBuilder.AddCode(EnsureProperNullability(_list, isNonNullable));
            }

            methodBuilder.AddCode(
                AssignmentBuilder
                .New()
                .SetLefthandSide($"var {listVarName}")
                .SetRighthandSide(
                    CodeBlockBuilder
                    .New()
                    .AddCode("new ")
                    .AddCode(TypeNames.List)
                    .AddCode("<")
                    .AddCode(listTypeDescriptor.InnerType.ToBuilder().SkipTrailingSpace())
                    .AddCode(">")
                    .AddCode("()")));
            methodBuilder.AddEmptyLine();

            ForEachBuilder forEachBuilder = ForEachBuilder
                                            .New()
                                            .SetLoopHeader(
                CodeBlockBuilder
                .New()
                .AddCode(listTypeDescriptor.InnerType.ToEntityIdBuilder())
                .AddCode($"{_child} in {_list}"))
                                            .AddCode(
                MethodCallBuilder
                .New()
                .SetMethodName(listVarName, nameof(List <object> .Add))
                .AddArgument(MethodCallBuilder
                             .Inline()
                             .SetMethodName(MapMethodNameFromTypeName(listTypeDescriptor.InnerType))
                             .AddArgument(_child)));

            methodBuilder
            .AddCode(forEachBuilder)
            .AddEmptyLine()
            .AddCode($"return {listVarName};");

            AddMapMethod(
                listVarName,
                listTypeDescriptor.InnerType,
                classBuilder,
                constructorBuilder,
                processed);
        }
Example #22
0
        protected override void Generate(
            CodeWriter writer,
            ITypeDescriptor typeDescriptor,
            out string fileName)
        {
            var(classBuilder, constructorBuilder) = CreateClassBuilder(false);

            ComplexTypeDescriptor descriptor =
                typeDescriptor as ComplexTypeDescriptor ??
                throw new InvalidOperationException(
                          "A result entity mapper can only be generated for complex types");

            // Setup class
            fileName = descriptor.ExtractMapperName();

            classBuilder
            .AddImplements(
                TypeNames.IEntityMapper
                .WithGeneric(descriptor.ExtractTypeName(), descriptor.RuntimeType.Name))
            .SetName(fileName);

            constructorBuilder.SetTypeName(descriptor.Name);

            if (descriptor.ContainsEntity())
            {
                AddConstructorAssignedField(
                    TypeNames.IEntityStore,
                    StoreFieldName,
                    classBuilder,
                    constructorBuilder);
            }

            // Define map method
            MethodBuilder mapMethod = MethodBuilder.New()
                                      .SetName(_mapMethodName)
                                      .SetAccessModifier(AccessModifier.Public)
                                      .SetReturnType(descriptor.RuntimeType.Name)
                                      .AddParameter(
                ParameterBuilder.New()
                .SetType(
                    descriptor.Kind == TypeKind.EntityType
                                ? CreateEntityTypeName(descriptor.Name)
                                : descriptor.Name)
                .SetName(_entityParamName));

            var constructorCall =
                MethodCallBuilder
                .New()
                .SetMethodName($"return new {descriptor.RuntimeType.Name}");

            if (typeDescriptor is ComplexTypeDescriptor complexTypeDescriptor)
            {
                foreach (PropertyDescriptor property in complexTypeDescriptor.Properties)
                {
                    constructorCall.AddArgument(BuildMapMethodCall(_entityParamName, property));
                }
            }

            mapMethod.AddCode(constructorCall);

            if (constructorBuilder.HasParameters())
            {
                classBuilder.AddConstructor(constructorBuilder);
            }

            classBuilder.AddMethod(mapMethod);

            AddRequiredMapMethods(
                _entityParamName,
                descriptor,
                classBuilder,
                constructorBuilder,
                new HashSet <string>());

            CodeFileBuilder
            .New()
            .SetNamespace(descriptor.RuntimeType.NamespaceWithoutGlobal)
            .AddType(classBuilder)
            .Build(writer);
        }
        private void AddBuildDataMethod(
            InterfaceTypeDescriptor resultNamedType,
            ClassBuilder classBuilder)
        {
            var concreteType =
                CreateResultInfoName(resultNamedType.ImplementedBy.First().RuntimeType.Name);

            MethodBuilder buildDataMethod = classBuilder
                                            .AddMethod()
                                            .SetPrivate()
                                            .SetName("BuildData")
                                            .SetReturnType($"({resultNamedType.RuntimeType.Name}, {concreteType})")
                                            .AddParameter(_obj, x => x.SetType(TypeNames.JsonElement))
                                            .AddCode(
                AssignmentBuilder
                .New()
                .SetLefthandSide($"using {TypeNames.IEntityUpdateSession} {_session}")
                .SetRighthandSide(
                    MethodCallBuilder
                    .Inline()
                    .SetMethodName(_entityStore, nameof(IEntityStore.BeginUpdate))))
                                            .AddCode(
                AssignmentBuilder
                .New()
                .SetLefthandSide($"var {_entityIds}")
                .SetRighthandSide(MethodCallBuilder
                                  .Inline()
                                  .SetNew()
                                  .SetMethodName(TypeNames.HashSet)
                                  .AddGeneric(TypeNames.EntityId)))
                                            .AddEmptyLine();

            foreach (PropertyDescriptor property in
                     resultNamedType.Properties.Where(prop => prop.Type.IsEntityType()))
            {
                buildDataMethod.AddCode(
                    AssignmentBuilder
                    .New()
                    .SetLefthandSide(CodeBlockBuilder
                                     .New()
                                     .AddCode(property.Type.ToEntityIdBuilder())
                                     .AddCode($"{GetParameterName(property.Name)}Id"))
                    .SetRighthandSide(BuildUpdateMethodCall(property)));
            }

            buildDataMethod
            .AddEmptyLine()
            .AddCode(
                AssignmentBuilder
                .New()
                .SetLefthandSide($"var {_resultInfo}")
                .SetRighthandSide(
                    CreateResultInfoMethodCall(resultNamedType, concreteType)))
            .AddEmptyLine()
            .AddCode(
                TupleBuilder
                .Inline()
                .SetDetermineStatement(true)
                .SetReturn()
                .AddMember(MethodCallBuilder
                           .Inline()
                           .SetMethodName(
                               _resultDataFactory,
                               nameof(IOperationResultDataFactory <object> .Create))
                           .AddArgument(_resultInfo))
                .AddMember(_resultInfo));
        }