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); }
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); }
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); }
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)); }
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); }
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); } }
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 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); }