/// <summary>
        /// For the field name provided, determine if there are any similar field names
        /// that may be the result of a typo.
        /// </summary>
        private IEnumerable<string> getSuggestedFieldNames(
          IGraphType type,
          string fieldName)
        {
            if (type is IComplexGraphType)
            {
                var complexType = type as IComplexGraphType;
                return StringUtils.SuggestionList(fieldName, complexType.Fields.Select(x => x.Name));
            }

            return Enumerable.Empty<string>();
        }
        /// <summary>
        /// if a variable defintion has a default value, it is effectively non-null.
        /// </summary>
        private GraphType effectiveType(IGraphType varType, VariableDefinition varDef)
        {
            if (varDef.DefaultValue == null || varType is NonNullGraphType)
            {
                return (GraphType)varType;
            }

            var type = varType.GetType();
            var genericType = typeof(NonNullGraphType<>).MakeGenericType(type);

            var nonNull = (NonNullGraphType)Activator.CreateInstance(genericType);
            nonNull.ResolvedType = varType;
            return nonNull;
        }
        private void Field(IGraphType type, Field field, ValidationContext context)
        {
            if (type == null)
            {
                return;
            }

            if (type.IsLeafType())
            {
                if (field.SelectionSet != null && field.SelectionSet.Selections.Any())
                {
                    var error = new ValidationError(context.OriginalQuery, "5.2.3", NoSubselectionAllowedMessage(field.Name, context.Print(type)), field.SelectionSet);
                    context.ReportError(error);
                }
            }
            else if(field.SelectionSet == null || !field.SelectionSet.Selections.Any())
            {
                var error = new ValidationError(context.OriginalQuery, "5.2.3", RequiredSubselectionMessage(field.Name, context.Print(type)), field);
                context.ReportError(error);
            }
        }
Beispiel #4
0
 /// <inheritdoc/>
 public virtual Task <bool> AllowField(IGraphType parent, IFieldType field) => parent.IsIntrospectionType() && (field.Name == "appliedDirectives" || field.Name == "isRepeatable") ? Forbidden : Allowed;
 /// <inheritdoc cref="Create{TSourceType, TReturnType}(Type)"/>
 public static FieldBuilder <TSourceType, TReturnType> Create <TSourceType, TReturnType>(IGraphType type)
 => FieldBuilder <TSourceType, TReturnType> .Create(type);
Beispiel #6
0
 /// <inheritdoc/>
 public override Task <bool> AllowField(IGraphType parent, IFieldType field) => Allowed;
Beispiel #7
0
 public bool Matches(object value, IGraphType type)
 {
     return(value is Domain.Models.Variable);
 }
Beispiel #8
0
 public static void ShouldBeOfNonNullableListType <TType>(this IGraphType type)
     where TType : GraphType
 {
     Assert.AreEqual(typeof(NonNullGraphType <ListGraphType <TType> >), type.GetType());
 }
 public static bool IsPossibleType(this IAbstractGraphType abstractType, IGraphType type)
 {
     return abstractType.PossibleTypes.Any(x => x.Equals(type));
 }
Beispiel #10
0
 /// <summary>
 /// Determines if the target graph type COULD BE spread into the active context graph type.
 /// </summary>
 /// <param name="schema">The target schema in case any additional graph types need to be accessed.</param>
 /// <param name="typeInContext">The graph type currently active on the context.</param>
 /// <param name="targetGraphType">The target graph type of the spread named fragment.</param>
 /// <returns><c>true</c> if the target type can be spread in context; otherwise, false.</returns>
 protected override bool CanAcceptGraphType(ISchema schema, IGraphType typeInContext, IGraphType targetGraphType)
 {
     // when spreading a framgent targeting an object into the context of another object
     // the two graph types must be the same
     return(typeInContext == targetGraphType);
 }
 public static void Field(
     this IObjectGraphType obj,
     string name,
     IGraphType type,
     string description = null,
     QueryArguments arguments = null,
     Func<ResolveFieldContext, object> resolve = null)
 {
     var field = new FieldType();
     field.Name = name;
     field.Description = description;
     field.Arguments = arguments;
     field.ResolvedType = type;
     field.Resolver = resolve != null ? new FuncFieldResolver<object>(resolve) : null;
     obj.AddField(field);
 }
        private List <Conflict> FindConflictsBetweenSubSelectionSets(
            ValidationContext context,
            Dictionary <SelectionSet, CachedField> cachedFieldsAndFragmentNames,
            PairSet comparedFragmentPairs,
            bool areMutuallyExclusive,
            IGraphType parentType1,
            SelectionSet selectionSet1,
            IGraphType parentType2,
            SelectionSet selectionSet2)
        {
            var conflicts = new List <Conflict>();

            var cachedField1 = GetFieldsAndFragmentNames(
                context,
                cachedFieldsAndFragmentNames,
                parentType1,
                selectionSet1);

            var fieldMap1      = cachedField1.NodeAndDef;
            var fragmentNames1 = cachedField1.Names;

            var cachedField2 = GetFieldsAndFragmentNames(
                context,
                cachedFieldsAndFragmentNames,
                parentType2,
                selectionSet2);

            var fieldMap2      = cachedField2.NodeAndDef;
            var fragmentNames2 = cachedField2.Names;

            // (H) First, collect all conflicts between these two collections of field.
            CollectConflictsBetween(
                context,
                conflicts,
                cachedFieldsAndFragmentNames,
                comparedFragmentPairs,
                areMutuallyExclusive,
                fieldMap1,
                fieldMap2);

            // (I) Then collect conflicts between the first collection of fields and
            // those referenced by each fragment name associated with the second.
            if (fragmentNames2.Count != 0)
            {
                var comparedFragments = new ObjMap <bool>();

                for (var j = 0; j < fragmentNames2.Count; j++)
                {
                    CollectConflictsBetweenFieldsAndFragment(
                        context,
                        conflicts,
                        cachedFieldsAndFragmentNames,
                        comparedFragments,
                        comparedFragmentPairs,
                        areMutuallyExclusive,
                        fieldMap1,
                        fragmentNames2[j]);
                }
            }

            // (I) Then collect conflicts between the second collection of fields and
            // those referenced by each fragment name associated with the first.
            if (fragmentNames1.Count != 0)
            {
                var comparedFragments = new ObjMap <bool>();

                for (var i = 0; i < fragmentNames1.Count; i++)
                {
                    CollectConflictsBetweenFieldsAndFragment(
                        context,
                        conflicts,
                        cachedFieldsAndFragmentNames,
                        comparedFragments,
                        comparedFragmentPairs,
                        areMutuallyExclusive,
                        fieldMap2,
                        fragmentNames1[i]);
                }
            }

            // (J) Also collect conflicts between any fragment names by the first and
            // fragment names by the second. This compares each item in the first set of
            // names to each item in the second set of names.
            for (var i = 0; i < fragmentNames1.Count; i++)
            {
                for (var j = 0; j < fragmentNames2.Count; j++)
                {
                    CollectConflictsBetweenFragments(
                        context,
                        conflicts,
                        cachedFieldsAndFragmentNames,
                        comparedFragmentPairs,
                        areMutuallyExclusive,
                        fragmentNames1[i],
                        fragmentNames2[j]);
                }
            }

            return(conflicts);
        }
        public Dictionary<string, Fields> CollectFields(
            ExecutionContext context,
            IGraphType specificType,
            SelectionSet selectionSet,
            Dictionary<string, Fields> fields,
            List<string> visitedFragmentNames)
        {
            if (fields == null)
            {
                fields = new Dictionary<string, Fields>();
            }

            selectionSet.Selections.Apply(selection =>
            {
                if (selection is Field)
                {
                    var field = (Field)selection;
                    if (!ShouldIncludeNode(context, field.Directives))
                    {
                        return;
                    }

                    var name = field.Alias ?? field.Name;
                    if (!fields.ContainsKey(name))
                    {
                        fields[name] = new Fields();
                    }
                    fields[name].Add(field);
                }
                else if (selection is FragmentSpread)
                {
                    var spread = (FragmentSpread)selection;

                    if (visitedFragmentNames.Contains(spread.Name)
                        || !ShouldIncludeNode(context, spread.Directives))
                    {
                        return;
                    }

                    visitedFragmentNames.Add(spread.Name);

                    var fragment = context.Fragments.FindDefinition(spread.Name);
                    if (fragment == null
                        || !ShouldIncludeNode(context, fragment.Directives)
                        || !DoesFragmentConditionMatch(context, fragment.Type.Name, specificType))
                    {
                        return;
                    }

                    CollectFields(context, specificType, fragment.SelectionSet, fields, visitedFragmentNames);
                }
                else if (selection is InlineFragment)
                {
                    var inline = (InlineFragment)selection;

                    var name = inline.Type != null ? inline.Type.Name : specificType.Name;

                    if (!ShouldIncludeNode(context, inline.Directives)
                      || !DoesFragmentConditionMatch(context, name, specificType))
                    {
                        return;
                    }

                    CollectFields(context, specificType, inline.SelectionSet, fields, visitedFragmentNames);
                }
            });

            return fields;
        }
        public bool DoesFragmentConditionMatch(ExecutionContext context, string fragmentName, IGraphType type)
        {
            if (string.IsNullOrWhiteSpace(fragmentName))
            {
                return true;
            }

            var conditionalType = context.Schema.FindType(fragmentName);

            if (conditionalType == null)
            {
                return false;
            }

            if (conditionalType.Equals(type))
            {
                return true;
            }

            if (conditionalType is IAbstractGraphType)
            {
                var abstractType = (IAbstractGraphType)conditionalType;
                return abstractType.IsPossibleType(type);
            }

            return false;
        }
        public object CoerceValue(ISchema schema, IGraphType type, IValue input, Variables variables = null)
        {
            if (type is NonNullGraphType)
            {
                var nonNull = type as NonNullGraphType;
                return CoerceValue(schema, nonNull.ResolvedType, input, variables);
            }

            if (input == null)
            {
                return null;
            }

            var variable = input as VariableReference;
            if (variable != null)
            {
                return variables != null
                    ? variables.ValueFor(variable.Name)
                    : null;
            }

            if (type is ListGraphType)
            {
                var listType = type as ListGraphType;
                var listItemType = listType.ResolvedType;
                var list = input as ListValue;
                return list != null
                    ? list.Values.Map(item => CoerceValue(schema, listItemType, item, variables)).ToArray()
                    : new[] { CoerceValue(schema, listItemType, input, variables) };
            }

            if (type is IObjectGraphType || type is InputObjectGraphType)
            {
                var complexType = type as IComplexGraphType;
                var obj = new Dictionary<string, object>();

                var objectValue = input as ObjectValue;
                if (objectValue == null)
                {
                    return null;
                }

                complexType.Fields.Apply(field =>
                {
                    var objectField = objectValue.Field(field.Name);
                    if (objectField != null)
                    {
                        var fieldValue = CoerceValue(schema, field.ResolvedType, objectField.Value, variables);
                        fieldValue = fieldValue ?? field.DefaultValue;

                        obj[field.Name] = fieldValue;
                    }
                });

                return obj;
            }

            if (type is ScalarGraphType)
            {
                var scalarType = type as ScalarGraphType;
                return scalarType.ParseLiteral(input);
            }

            return null;
        }
        public bool IsValidValue(ISchema schema, IGraphType type, object input)
        {
            if (type is NonNullGraphType)
            {
                if (input == null)
                {
                    return false;
                }

                var nonNullType = ((NonNullGraphType)type).ResolvedType;

                if (nonNullType is ScalarGraphType)
                {
                    var val = ValueFromScalar((ScalarGraphType)nonNullType, input);
                    return val != null;
                }

                return IsValidValue(schema, nonNullType, input);
            }

            if (input == null)
            {
                return true;
            }

            if (type is ListGraphType)
            {
                var listType = (ListGraphType)type;
                var listItemType = listType.ResolvedType;

                var list = input as IEnumerable;
                if (list != null && !(input is string))
                {
                    return list.All(item => IsValidValue(schema, listItemType, item));
                }

                return IsValidValue(schema, listItemType, input);
            }

            if (type is IObjectGraphType || type is InputObjectGraphType)
            {
                var dict = input as Dictionary<string, object>;
                var complexType = type as IComplexGraphType;

                if (dict == null)
                {
                    return false;
                }

                // ensure every provided field is defined
                if (type is InputObjectGraphType
                    && dict.Keys.Any(key => complexType.Fields.FirstOrDefault(field => field.Name == key) == null))
                {
                    return false;
                }

                return complexType.Fields.All(field =>
                {
                    object fieldValue = null;
                    dict.TryGetValue(field.Name, out fieldValue);
                    return IsValidValue(
                        schema,
                        field.ResolvedType,
                        fieldValue);
                });
            }

            if (type is ScalarGraphType)
            {
                var scalar = (ScalarGraphType)type;
                var value = ValueFromScalar(scalar, input);
                return value != null;
            }

            return false;
        }
        public async Task<object> CompleteValueAsync(ExecutionContext context, IGraphType fieldType, Fields fields, object result)
        {
            var field = fields != null ? fields.FirstOrDefault() : null;
            var fieldName = field != null ? field.Name : null;

            var nonNullType = fieldType as NonNullGraphType;
            if (nonNullType != null)
            {
                var type = nonNullType.ResolvedType;
                var completed = await CompleteValueAsync(context, type, fields, result).ConfigureAwait(false);
                if (completed == null)
                {
                    var error = new ExecutionError("Cannot return null for non-null type. Field: {0}, Type: {1}!."
                        .ToFormat(fieldName, type.Name));
                    error.AddLocation(field, context.Document);
                    throw error;
                }

                return completed;
            }

            if (result == null)
            {
                return null;
            }

            if (fieldType is ScalarGraphType)
            {
                var scalarType = fieldType as ScalarGraphType;
                var coercedValue = scalarType.Serialize(result);
                return coercedValue;
            }

            if (fieldType is ListGraphType)
            {
                var list = result as IEnumerable;

                if (list == null)
                {
                    var error = new ExecutionError("User error: expected an IEnumerable list though did not find one.");
                    error.AddLocation(field, context.Document);
                    throw error;
                }

                var listType = fieldType as ListGraphType;
                var itemType = listType.ResolvedType;

                var results = await list.MapAsync(async item => await CompleteValueAsync(context, itemType, fields, item).ConfigureAwait(false)).ConfigureAwait(false);

                return results;
            }

            var objectType = fieldType as IObjectGraphType;

            if (fieldType is IAbstractGraphType)
            {
                var abstractType = fieldType as IAbstractGraphType;
                objectType = abstractType.GetObjectType(result);

                if (objectType != null && !abstractType.IsPossibleType(objectType))
                {
                    var error = new ExecutionError(
                        "Runtime Object type \"{0}\" is not a possible type for \"{1}\""
                        .ToFormat(objectType, abstractType));
                    error.AddLocation(field, context.Document);
                    throw error;
                }
            }

            if (objectType == null)
            {
                return null;
            }

            if (objectType.IsTypeOf != null && !objectType.IsTypeOf(result))
            {
                var error = new ExecutionError(
                    "Expected value of type \"{0}\" but got: {1}."
                    .ToFormat(objectType, result));
                error.AddLocation(field, context.Document);
                throw error;
            }

            var subFields = new Dictionary<string, Fields>();
            var visitedFragments = new List<string>();

            fields.Apply(f =>
            {
                subFields = CollectFields(context, objectType, f.SelectionSet, subFields, visitedFragments);
            });

            return await ExecuteFieldsAsync(context, objectType, result, subFields).ConfigureAwait(false);
        }
Beispiel #18
0
 public static bool IsCompositeType(this IGraphType type)
 {
     return(type is IObjectGraphType ||
            type is IInterfaceGraphType ||
            type is UnionGraphType);
 }
 private bool isInterfaceType(IGraphType parentType)
 {
     return(parentType is IInterfaceGraphType);
 }
Beispiel #20
0
        public static IValue AstFromValue(this object value, ISchema schema, IGraphType type)
        {
            if (type is NonNullGraphType nonnull)
            {
                return(AstFromValue(value, schema, nonnull.ResolvedType));
            }

            if (value == null || type == null)
            {
                return(new NullValue());
            }

            // Convert IEnumerable to GraphQL list. If the GraphQLType is a list, but
            // the value is not an IEnumerable, convert the value using the list's item type.
            if (type is ListGraphType listType)
            {
                var itemType = listType.ResolvedType;

                if (!(value is string) && value is IEnumerable list)
                {
                    var values = list
                                 .Cast <object>()
                                 .Select(item => AstFromValue(item, schema, itemType))
                                 .ToList();

                    return(new ListValue(values));
                }

                return(AstFromValue(value, schema, itemType));
            }

            // Populate the fields of the input object by creating ASTs from each value
            // in the dictionary according to the fields in the input type.
            if (type is IInputObjectGraphType input)
            {
                if (!(value is Dictionary <string, object> dict))
                {
                    return(null);
                }

                var fields = dict
                             .Select(pair =>
                {
                    var fieldType = input.GetField(pair.Key)?.ResolvedType;
                    return(new ObjectField(pair.Key, AstFromValue(pair.Value, schema, fieldType)));
                })
                             .ToList();

                return(new ObjectValue(fields));
            }


            Invariant.Check(
                type.IsInputType(),
                $"Must provide Input Type, cannot use: {type}");


            var inputType = type as ScalarGraphType;

            // Since value is an internally represented value, it must be serialized
            // to an externally represented value before converting into an AST.
            var serialized = inputType.Serialize(value);

            if (serialized == null)
            {
                return(null);
            }

            if (serialized is bool b)
            {
                return(new BooleanValue(b));
            }

            if (serialized is int i)
            {
                return(new IntValue(i));
            }

            if (serialized is long l)
            {
                return(new LongValue(l));
            }

            if (serialized is decimal @decimal)
            {
                return(new DecimalValue(@decimal));
            }

            if (serialized is double d)
            {
                return(new FloatValue(d));
            }

            if (serialized is DateTime time)
            {
                return(new DateTimeValue(time));
            }

            if (serialized is Uri uri)
            {
                return(new UriValue(uri));
            }

            if (serialized is DateTimeOffset offset)
            {
                return(new DateTimeOffsetValue(offset));
            }

            if (serialized is TimeSpan span)
            {
                return(new TimeSpanValue(span));
            }

            if (serialized is Guid guid)
            {
                return(new GuidValue(guid));
            }

            if (serialized is short int16)
            {
                return(new ShortValue(int16));
            }

            if (serialized is ushort uint16)
            {
                return(new UShortValue(uint16));
            }

            if (serialized is uint uint32)
            {
                return(new UIntValue(uint32));
            }

            if (serialized is ulong uint64)
            {
                return(new ULongValue(uint64));
            }

            if (serialized is string)
            {
                if (type is EnumerationGraphType)
                {
                    return(new EnumValue(serialized.ToString()));
                }

                return(new StringValue(serialized.ToString()));
            }

            var converter = schema.FindValueConverter(serialized, type);

            if (converter != null)
            {
                return(converter.Convert(serialized, type));
            }

            throw new ExecutionError($"Cannot convert value to AST: {serialized}");
        }
        /// <summary>
        /// Go through all of the implementations of type, as well as the interfaces
        /// that they implement. If any of those types include the provided field,
        /// suggest them, sorted by how often the type is referenced,  starting
        /// with Interfaces.
        /// </summary>
        private IEnumerable<string> getSuggestedTypeNames(
          ISchema schema,
          IGraphType type,
          string fieldName)
        {
            if (type is IAbstractGraphType)
            {
                var suggestedObjectTypes = new List<string>();
                var interfaceUsageCount = new LightweightCache<string, int>(key => 0);

                var absType = type as IAbstractGraphType;
                absType.PossibleTypes.Apply(possibleType =>
                {
                    if (!possibleType.HasField(fieldName))
                    {
                        return;
                    }

                    // This object defines this field.
                    suggestedObjectTypes.Add(possibleType.Name);

                    possibleType.ResolvedInterfaces.Apply(possibleInterface =>
                    {
                        if (possibleInterface.HasField(fieldName))
                        {
                            // This interface type defines this field.
                            interfaceUsageCount[possibleInterface.Name] = interfaceUsageCount[possibleInterface.Name] + 1;
                        }
                    });
                });

                var suggestedInterfaceTypes = interfaceUsageCount.Keys.OrderBy(x => interfaceUsageCount[x]);
                return suggestedInterfaceTypes.Concat(suggestedObjectTypes);
            }

            return Enumerable.Empty<string>();
        }
        public void ApplyTypeReference(IGraphType type)
        {
            CheckSealed();

            if (type is IComplexGraphType complexType)
            {
                foreach (var field in complexType.Fields)
                {
                    field.ResolvedType = ConvertTypeReference(type, field.ResolvedType);

                    if (field.Arguments == null)
                    {
                        continue;
                    }

                    foreach (var arg in field.Arguments)
                    {
                        arg.ResolvedType = ConvertTypeReference(type, arg.ResolvedType);
                    }
                }
            }

            if (type is IObjectGraphType objectType)
            {
                objectType.ResolvedInterfaces = objectType
                                                .ResolvedInterfaces
                                                .Select(i =>
                {
                    var interfaceType = (IInterfaceGraphType)ConvertTypeReference(objectType, i);

                    if (objectType.IsTypeOf == null && interfaceType.ResolveType == null)
                    {
                        throw new ExecutionError((
                                                     "Interface type {0} does not provide a \"resolveType\" function " +
                                                     "and possible Type \"{1}\" does not provide a \"isTypeOf\" function.  " +
                                                     "There is no way to resolve this possible type during execution.")
                                                 .ToFormat(interfaceType.Name, objectType.Name));
                    }

                    interfaceType.AddPossibleType(objectType);

                    return(interfaceType);
                })
                                                .ToList();
            }

            if (type is UnionGraphType union)
            {
                union.PossibleTypes = union
                                      .PossibleTypes
                                      .Select(t =>
                {
                    var unionType = ConvertTypeReference(union, t) as IObjectGraphType;

                    if (union.ResolveType == null && unionType != null && unionType.IsTypeOf == null)
                    {
                        throw new ExecutionError((
                                                     "Union type {0} does not provide a \"resolveType\" function " +
                                                     "and possible Type \"{1}\" does not provide a \"isTypeOf\" function. " +
                                                     "There is no way to resolve this possible type during execution.")
                                                 .ToFormat(union.Name, unionType.Name));
                    }

                    return(unionType);
                })
                                      .ToList();
            }
        }
 public ComplexGraphProperty(SerializableProperty property, IGraphType propertyType)
 {
     _property = property;
     _propertyType = propertyType;
     _args = property.CreateVisitArgs();
 }
        private List <Conflict> FindConflictsWithinSelectionSet(
            ValidationContext context,
            Dictionary <SelectionSet, CachedField> cachedFieldsAndFragmentNames,
            PairSet comparedFragmentPairs,
            IGraphType parentType,
            SelectionSet selectionSet)
        {
            var conflicts = new List <Conflict>();

            CachedField cachedField = GetFieldsAndFragmentNames(
                context,
                cachedFieldsAndFragmentNames,
                parentType,
                selectionSet);

            var fieldMap      = cachedField.NodeAndDef;
            var fragmentNames = cachedField.Names;

            CollectConflictsWithin(
                context,
                conflicts,
                cachedFieldsAndFragmentNames,
                comparedFragmentPairs,
                fieldMap);

            if (fragmentNames.Count != 0)
            {
                // (B) Then collect conflicts between these fields and those represented by
                // each spread fragment name found.
                var comparedFragments = new ObjMap <bool>();
                for (int i = 0; i < fragmentNames.Count; i++)
                {
                    CollectConflictsBetweenFieldsAndFragment(
                        context,
                        conflicts,
                        cachedFieldsAndFragmentNames,
                        comparedFragments,
                        comparedFragmentPairs,
                        false,
                        fieldMap,
                        fragmentNames[i]);

                    // (C) Then compare this fragment with all other fragments found in this
                    // selection set to collect conflicts between fragments spread together.
                    // This compares each item in the list of fragment names to every other
                    // item in that same list (except for itself).
                    for (int j = i + 1; j < fragmentNames.Count; j++)
                    {
                        CollectConflictsBetweenFragments(
                            context,
                            conflicts,
                            cachedFieldsAndFragmentNames,
                            comparedFragmentPairs,
                            false,
                            fragmentNames[i],
                            fragmentNames[j]);
                    }
                }
            }
            return(conflicts);
        }
        /// <summary>
        /// Creates a new instance of the indicated type, populating it with the dictionary.
        /// Can use any constructor of the indicated type, provided that there are keys in the
        /// dictionary that correspond (case sensitive) to the names of the constructor parameters.
        /// </summary>
        /// <param name="source">The source of values.</param>
        /// <param name="type">The type to create.</param>
        /// <param name="mappedType">
        /// GraphType for matching dictionary keys with <paramref name="type"/> property names.
        /// GraphType contains information about this matching in Metadata property.
        /// In case of configuring field as Field(x => x.FName).Name("FirstName") source dictionary
        /// will have 'FirstName' key but its value should be set to 'FName' property of created object.
        /// </param>
        public static object ToObject(this IDictionary <string, object> source, Type type, IGraphType mappedType = null)
        {
            // Given Field(x => x.FName).Name("FirstName") and key == "FirstName" returns "FName"
            string GetPropertyName(string key, out FieldType field)
            {
                var complexType = mappedType.GetNamedType() as IComplexGraphType;

                // type may not contain mapping information
                field = complexType?.GetField(key);
                return(field?.GetMetadata(ComplexGraphType <object> .ORIGINAL_EXPRESSION_PROPERTY_NAME, key) ?? key);
            }

            // Returns keys from source that match constructor signature
            string[] MatchSourceKeys(ParameterInfo[] parameters)
            {
                // parameterless constructors are the most common use case
                if (parameters.Length == 0)
                {
                    return(Array.Empty <string>());
                }

                // otherwise we have to iterate over the parameters - worse performance but this is rather rare case
                List <string> keys = null;

                if (parameters.All(p => source.Any(keyValue =>
                {
                    bool matched = string.Equals(GetPropertyName(keyValue.Key, out var _), p.Name, StringComparison.InvariantCultureIgnoreCase);
                    if (matched)
                    {
                        (keys ??= new List <string>()).Add(keyValue.Key);
                    }
                    return(matched);
                })))
                {
                    return(keys.ToArray());
                }

                return(null);
            }

            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            // force sourceType to be IDictionary<string, object>
            if (ValueConverter.TryConvertTo(source, type, out object result, typeof(IDictionary <string, object>)))
            {
                return(result);
            }

            // attempt to use the most specific constructor sorting in decreasing order of parameters number
            var ctorCandidates = _types.GetOrAdd(type, t => t.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).OrderByDescending(ctor => ctor.GetParameters().Length).ToArray());

            ConstructorInfo targetCtor = null;

            ParameterInfo[] ctorParameters = null;
            string[]        matchedKeys    = null;

            foreach (var ctor in ctorCandidates)
            {
                var parameters = ctor.GetParameters();
                matchedKeys = MatchSourceKeys(parameters);
                if (matchedKeys != null)
                {
                    targetCtor     = ctor;
                    ctorParameters = parameters;
                    break;
                }
            }

            if (targetCtor == null)
            {
                throw new ArgumentException($"Type '{type}' does not contain a constructor that could be used for current input arguments.", nameof(type));
            }

            object[] ctorArguments = ctorParameters.Length == 0 ? Array.Empty <object>() : new object[ctorParameters.Length];

            for (int i = 0; i < ctorParameters.Length; ++i)
            {
                object arg = GetPropertyValue(source[matchedKeys[i]], ctorParameters[i].ParameterType);
                ctorArguments[i] = arg;
            }

            object obj = targetCtor.Invoke(ctorArguments);

            foreach (var item in source)
            {
                // these parameters have already been used in the constructor, no need to set property
                if (matchedKeys.Length > 0 && matchedKeys.Any(k => k == item.Key))
                {
                    continue;
                }

                string       propertyName = GetPropertyName(item.Key, out var field);
                PropertyInfo propertyInfo = null;

                try
                {
                    propertyInfo = type.GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
                }
                catch (AmbiguousMatchException)
                {
                    propertyInfo = type.GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
                }

                if (propertyInfo != null && propertyInfo.CanWrite)
                {
                    object value = GetPropertyValue(item.Value, propertyInfo.PropertyType, field?.ResolvedType);
                    propertyInfo.SetValue(obj, value, null); //issue: this works even if propertyInfo is ValueType and value is null
                }
            }

            return(obj);
        }
 private bool isObjectType(IGraphType parentType)
 {
     return(parentType is IObjectGraphType);
 }
Beispiel #27
0
        public void Enter(INode node)
        {
            _ancestorStack.Push(node);

            if (node is SelectionSet)
            {
                _parentTypeStack.Push(GetLastType());
                return;
            }

            if (node is Field field)
            {
                var parentType = _parentTypeStack.Peek().GetNamedType();
                var fieldType  = GetFieldDef(_schema, parentType, field);
                _fieldDefStack.Push(fieldType);
                var targetType = fieldType?.ResolvedType;
                _typeStack.Push(targetType);
                return;
            }

            if (node is Directive directive)
            {
                _directive = _schema.FindDirective(directive.Name);
            }

            if (node is Operation op)
            {
                IGraphType type = null;
                if (op.OperationType == OperationType.Query)
                {
                    type = _schema.Query;
                }
                else if (op.OperationType == OperationType.Mutation)
                {
                    type = _schema.Mutation;
                }
                else if (op.OperationType == OperationType.Subscription)
                {
                    type = _schema.Subscription;
                }
                _typeStack.Push(type);
                return;
            }

            if (node is FragmentDefinition def1)
            {
                var type = _schema.FindType(def1.Type.Name);
                _typeStack.Push(type);
                return;
            }

            if (node is InlineFragment def)
            {
                var type = def.Type != null?_schema.FindType(def.Type.Name) : GetLastType();

                _typeStack.Push(type);
                return;
            }

            if (node is VariableDefinition varDef)
            {
                var inputType = varDef.Type.GraphTypeFromType(_schema);
                _inputTypeStack.Push(inputType);
                return;
            }

            if (node is Argument argAst)
            {
                QueryArgument argDef  = null;
                IGraphType    argType = null;

                var args = GetDirective() != null?GetDirective()?.Arguments : GetFieldDef()?.Arguments;

                if (args != null)
                {
                    argDef  = args.Find(argAst.Name);
                    argType = argDef?.ResolvedType;
                }

                _argument = argDef;
                _inputTypeStack.Push(argType);
            }

            if (node is ListValue)
            {
                var type = GetInputType().GetNamedType();
                _inputTypeStack.Push(type);
            }

            if (node is ObjectField objectField)
            {
                var        objectType = GetInputType().GetNamedType();
                IGraphType fieldType  = null;

                if (objectType is IInputObjectGraphType complexType)
                {
                    var inputField = complexType.GetField(objectField.Name);

                    fieldType = inputField?.ResolvedType;
                }

                _inputTypeStack.Push(fieldType);
            }
        }
Beispiel #28
0
 public IValue Convert(object value, IGraphType type)
 {
     return(new VariableValue((Domain.Models.Variable)value));
 }
Beispiel #29
0
 public IValue Convert(object value, IGraphType type)
 {
     return(new JsonValueNode(ParseJson(value)));
 }
Beispiel #30
0
 public static void ShouldBeOfListType <TType>(this IGraphType type)
     where TType : GraphType
 {
     Assert.AreEqual(typeof(ListGraphType <TType>), type.GetType());
 }
Beispiel #31
0
 public bool Matches(object value, IGraphType type)
 {
     return(type is JsonGraphType);
 }
 public SchemaBuilder RegisterType(IGraphType type)
 {
     _types[type.Name] = type;
     return(this);
 }
Beispiel #33
0
 /// <summary>
 /// Indicates if the graph type is an input object graph type.
 /// </summary>
 public static bool IsInputObjectType(this IGraphType type)
 {
     var(namedType, namedType2) = type.GetNamedTypes();
     return(namedType is IInputObjectGraphType ||
            typeof(IInputObjectGraphType).IsAssignableFrom(namedType2));
 }
Beispiel #34
0
 /// <inheritdoc/>
 public override Task <bool> AllowType(IGraphType type) => Allowed;
Beispiel #35
0
 internal static bool IsGraphQLTypeReference(this IGraphType type)
 {
     var(namedType, _) = type.GetNamedTypes();
     return(namedType is GraphQLTypeReference);
 }
Beispiel #36
0
 /// <inheritdoc/>
 public virtual Task <bool> AllowType(IGraphType type) => type is __AppliedDirective || type is __DirectiveArgument ? Forbidden : Allowed;
Beispiel #37
0
 /// <summary>
 /// Determines if this graph type is an introspection type.
 /// </summary>
 internal static bool IsIntrospectionType(this IGraphType type) => type?.Name?.StartsWith("__", StringComparison.InvariantCulture) ?? false;
Beispiel #38
0
        public static IEnumerable <string> IsValidLiteralValue(this IGraphType type, IValue valueAst, ISchema schema)
        {
            if (type is NonNullGraphType nonNull)
            {
                var ofType = nonNull.ResolvedType;

                if (valueAst == null || valueAst is NullValue)
                {
                    if (ofType != null)
                    {
                        return(new[] { $"Expected \"{ofType.Name}!\", found null." });
                    }

                    return(new[] { "Expected non-null value, found null" });
                }

                return(IsValidLiteralValue(ofType, valueAst, schema));
            }
            else if (valueAst is NullValue)
            {
                return(Array.Empty <string>());
            }

            if (valueAst == null)
            {
                return(Array.Empty <string>());
            }

            // This function only tests literals, and assumes variables will provide
            // values of the correct type.
            if (valueAst is VariableReference)
            {
                return(Array.Empty <string>());
            }

            if (type is ListGraphType list)
            {
                var ofType = list.ResolvedType;

                if (valueAst is ListValue listValue)
                {
                    return(listValue.Values
                           .SelectMany(value =>
                                       IsValidLiteralValue(ofType, value, schema)
                                       .Select((err, index) => $"In element #{index + 1}: {err}")
                                       )
                           .ToList());
                }

                return(IsValidLiteralValue(ofType, valueAst, schema));
            }

            if (type is IInputObjectGraphType inputType)
            {
                if (!(valueAst is ObjectValue objValue))
                {
                    return(new[] { $"Expected \"{inputType.Name}\", found not an object." });
                }

                var fields    = inputType.Fields.ToList();
                var fieldAsts = objValue.ObjectFields.ToList();

                var errors = new List <string>();

                // ensure every provided field is defined
                foreach (var providedFieldAst in fieldAsts)
                {
                    var found = fields.Find(x => x.Name == providedFieldAst.Name);
                    if (found == null)
                    {
                        errors.Add($"In field \"{providedFieldAst.Name}\": Unknown field.");
                    }
                }

                // ensure every defined field is valid
                foreach (var field in fields)
                {
                    var fieldAst = fieldAsts.Find(x => x.Name == field.Name);
                    var result   = IsValidLiteralValue(field.ResolvedType, fieldAst?.Value, schema);

                    errors.AddRange(result.Select(err => $"In field \"{field.Name}\": {err}"));
                }

                return(errors);
            }

            var scalar = (ScalarGraphType)type;

            var parseResult = scalar.ParseLiteral(valueAst);

            if (parseResult == null)
            {
                return(new[] { $"Expected type \"{type.Name}\", found {AstPrinter.Print(valueAst)}." });
            }

            return(Array.Empty <string>());
        }
Beispiel #39
0
 /// <summary>
 /// Indicates if the graph type is a scalar graph type.
 /// </summary>
 public static bool IsLeafType(this IGraphType type)
 {
     var(namedType, namedType2) = type.GetNamedTypes();
     return(namedType is ScalarGraphType ||
            typeof(ScalarGraphType).IsAssignableFrom(namedType2));
 }
Beispiel #40
0
        public static bool IsLeafType(this IGraphType type)
        {
            var namedType = type.GetNamedType();

            return(namedType is ScalarGraphType || namedType is EnumerationGraphType);
        }
        public void AddType(IGraphType type, TypeCollectionContext context)
        {
            CheckSealed();

            if (type == null || type is GraphQLTypeReference)
            {
                return;
            }

            if (type is NonNullGraphType || type is ListGraphType)
            {
                throw new ExecutionError("Only add root types.");
            }

            var name = type.CollectTypes(context).TrimGraphQLTypes();

            lock (_lock)
            {
                SetGraphType(name, type);
            }

            if (type is IComplexGraphType complexType)
            {
                foreach (var field in complexType.Fields)
                {
                    HandleField(type.GetType(), field, context);
                }
            }

            if (type is IObjectGraphType obj)
            {
                foreach (var objectInterface in obj.Interfaces)
                {
                    AddTypeIfNotRegistered(objectInterface, context);

                    if (this[objectInterface] is IInterfaceGraphType interfaceInstance)
                    {
                        obj.AddResolvedInterface(interfaceInstance);
                        interfaceInstance.AddPossibleType(obj);

                        if (interfaceInstance.ResolveType == null && obj.IsTypeOf == null)
                        {
                            throw new ExecutionError((
                                                         "Interface type {0} does not provide a \"resolveType\" function " +
                                                         "and possible Type \"{1}\" does not provide a \"isTypeOf\" function.  " +
                                                         "There is no way to resolve this possible type during execution.")
                                                     .ToFormat(interfaceInstance.Name, obj.Name));
                        }
                    }
                }
            }

            if (type is UnionGraphType union)
            {
                if (!union.Types.Any() && !union.PossibleTypes.Any())
                {
                    throw new ExecutionError("Must provide types for Union {0}.".ToFormat(union));
                }

                foreach (var unionedType in union.PossibleTypes)
                {
                    AddTypeIfNotRegistered(unionedType, context);

                    if (union.ResolveType == null && unionedType.IsTypeOf == null)
                    {
                        throw new ExecutionError((
                                                     "Union type {0} does not provide a \"resolveType\" function " +
                                                     "and possible Type \"{1}\" does not provide a \"isTypeOf\" function. " +
                                                     "There is no way to resolve this possible type during execution.")
                                                 .ToFormat(union.Name, unionedType.Name));
                    }
                }

                foreach (var unionedType in union.Types)
                {
                    AddTypeIfNotRegistered(unionedType, context);

                    var objType = this[unionedType] as IObjectGraphType;

                    if (union.ResolveType == null && objType != null && objType.IsTypeOf == null)
                    {
                        throw new ExecutionError((
                                                     "Union type {0} does not provide a \"resolveType\" function " +
                                                     "and possible Type \"{1}\" does not provide a \"isTypeOf\" function. " +
                                                     "There is no way to resolve this possible type during execution.")
                                                 .ToFormat(union.Name, objType.Name));
                    }

                    union.AddPossibleType(objType);
                }
            }
        }
Beispiel #42
0
        public static bool IsInputObjectType(this IGraphType type)
        {
            var namedType = type.GetNamedType();

            return(namedType is IInputObjectGraphType);
        }
 public string Print(IGraphType type)
 {
     return SchemaPrinter.ResolveName(type);
 }