Esempio n. 1
0
        private void MapSelectionSubSet(SelectionSubset selSubset, TypeDefBase typeDef)
        {
            switch (typeDef)
            {
            case ScalarTypeDef _:
            case EnumTypeDef _:
                // that should never happen
                AddError($"Scalar or Enum may not have a selection subset", selSubset);
                break;

            case ObjectTypeDef objTypeDef:
                MapObjectSelectionSubset(selSubset, objTypeDef);
                break;

            case InterfaceTypeDef intTypeDef:
                foreach (var objType in intTypeDef.PossibleTypes)
                {
                    MapObjectSelectionSubset(selSubset, objType);
                }
                break;

            case UnionTypeDef unionTypeDef:
                foreach (var objType in unionTypeDef.PossibleTypes)
                {
                    MapObjectSelectionSubset(selSubset, objType, isForUnion: true);
                }
                break;
            }
        }
Esempio n. 2
0
        // Might be called for ObjectType or Interface (for intf - just to check fields exist)
        private void MapObjectSelectionSubset(SelectionSubset selSubset, ObjectTypeDef objectTypeDef, IList <RequestDirective> directives, bool isForUnion = false)
        {
            var mappedFields = MapSelectionItems(selSubset.Items, objectTypeDef, directives, isForUnion);

            selSubset.MappedItemSets.Add(new MappedObjectItemSet()
            {
                ObjectTypeDef = objectTypeDef, Items = mappedFields
            });
        }
        }     //method

        private MappedSelectionSubSet GetMappedSubset(SelectionSubset subSet, IList <ObjectTypeDef> objectTypeDefs, Type entityType,
                                                      NamedRequestObject requestObj)
        {
            var mappedSubset = subSet.MappedSubSets.FirstOrDefault(
                ms => (ms.Mapping.EntityType == entityType || ms.Mapping.EntityType.IsAssignableFrom(entityType)) &&
                objectTypeDefs.Contains(ms.Mapping.TypeDef));

            if (mappedSubset == null)
            {
                var types = string.Join(",", objectTypeDefs);
                this._requestContext.AddError($"Failed to find mapping from entity type {entityType} to GraphQLType(s) [{types}].",
                                              requestObj);
                AbortRequest();
            }
            return(mappedSubset);
        }
Esempio n. 4
0
        // Might be called for ObjectType or Interface (for intf - just to check fields exist)
        private void MapObjectSelectionSubset(SelectionSubset selSubset, ObjectTypeDef objectTypeDef, bool isForUnion = false)
        {
            // Map arguments on fields, add directives, map fragments
            foreach (var item in selSubset.Items)
            {
                AddRuntimeRequestDirectives(item);
                switch (item)
                {
                case SelectionField selFld:
                    var fldDef = objectTypeDef.Fields[selFld.Name];
                    if (fldDef == null)
                    {
                        // if field not found, the behavior depends if it is a union; it is error for a union
                        if (!isForUnion)
                        {
                            AddError($"Field '{selFld.Name}' not found on type '{objectTypeDef.Name}'.", selFld);
                        }
                        continue;
                    }
                    selFld.MappedArgs = MapArguments(selFld.Args, fldDef.Args, selFld);
                    AddRuntimeModelDirectives(fldDef);
                    MapSelectionFieldSubsetIfPresent(selFld, fldDef.TypeRef.TypeDef);
                    break;

                case FragmentSpread fspread:
                    // Named fragment refs are NOT set by parser; parser sets only Inline fragmDefs; we need to match named fragms here
                    if (!fspread.IsInline && fspread.Fragment == null)
                    {
                        fspread.Fragment = GetFragmentDef(fspread.Name);
                        if (fspread.Fragment == null)
                        {
                            AddError($"Fragment {fspread.Name} not defined.", fspread);
                        }
                    }
                    break;
                } //switch
            }     //foreach item

            if (_requestContext.Failed)
            {
                return;
            }

            // Now create mappings for all possible entity types
            foreach (var typeMapping in objectTypeDef.Mappings)
            {
                // It is possible mapped set already exists (with unions and especially fragments)
                var existing = selSubset.MappedSubSets.FirstOrDefault(ms => ms.Mapping == typeMapping);
                if (existing != null)
                {
                    continue;
                }
                var mappedItems = new List <MappedSelectionItem>();
                foreach (var item in selSubset.Items)
                {
                    switch (item)
                    {
                    case SelectionField selFld:
                        var fldDef = typeMapping.TypeDef.Fields[selFld.Name];
                        if (fldDef == null)
                        {
                            // it is not error, it should have been caught earlier; it is unmatch for union
                            continue;
                        }
                        var fldResolver = typeMapping.GetResolver(fldDef);
                        //.FirstOrDefault(fr => fr.Field.Name == selFld.Name);
                        var mappedFld = new MappedSelectionField(selFld, fldResolver);
                        mappedItems.Add(mappedFld);
                        break;

                    case FragmentSpread fs:
                        var onType = fs.Fragment.OnTypeRef?.TypeDef;
                        var skip   = onType != null && onType.Kind == TypeKind.Object && onType != objectTypeDef;
                        if (skip)
                        {
                            continue;
                        }
                        if (fs.IsInline) // only inline fragments should be mapped from here; named fragments are mapped separately, upfront
                        {
                            MapObjectSelectionSubset(fs.Fragment.SelectionSubset, objectTypeDef, isForUnion);
                        }
                        var mappedSpread = new MappedFragmentSpread(fs);
                        mappedItems.Add(mappedSpread);
                        break;
                    } //switch
                }     //foreach item

                selSubset.MappedSubSets.Add(new MappedSelectionSubSet()
                {
                    Mapping = typeMapping, MappedItems = mappedItems
                });
            } //foreach typeMapping
        }
        private async Task ExecuteObjectsSelectionSubsetAsync(IList <OutputObjectScope> parentScopes,
                                                              ObjectTypeDef objTypeDef, SelectionSubset subSet)
        {
            var outItemSet   = subSet.MappedItemSets.FirstOrDefault(fi => fi.ObjectTypeDef == objTypeDef);
            var mappedFields = _requestContext.GetIncludedMappedFields(outItemSet);

            // init scopes
            foreach (var scope in parentScopes)
            {
                scope.Init(objTypeDef, mappedFields);
            }

            for (int fldIndex = 0; fldIndex < mappedFields.Count; fldIndex++)
            {
                var mappedField        = mappedFields[fldIndex];
                var returnsComplexType = mappedField.FieldDef.Flags.IsSet(FieldFlags.ReturnsComplexType);
                var fieldContext       = new FieldContext(_requestContext, this, mappedField, fldIndex, parentScopes);
                foreach (var scope in fieldContext.AllParentScopes)
                {
                    if (fieldContext.BatchResultWasSet && scope.HasValue(fldIndex))
                    {
                        continue;
                    }
                    fieldContext.CurrentScope = scope;
                    object result = null;
                    switch (mappedField.FieldDef.ExecutionType)
                    {
                    case FieldExecutionType.Reader:
                        result = InvokeFieldReader(fieldContext, fieldContext.CurrentScope.Entity);
                        break;

                    case FieldExecutionType.Resolver:
                        result = await InvokeResolverAsync(fieldContext);

                        break;
                    }
                    var outValue = fieldContext.ConvertToOuputValue(result);
                    if (!fieldContext.BatchResultWasSet)
                    {
                        scope.SetValue(fldIndex, outValue);
                    }
                } //foreach scope
                // if there are any non-null object-type results, add this field context to this special list
                //   to execute selection subsets in the next round.
                if (returnsComplexType && fieldContext.AllResultScopes.Count > 0)
                {
                    _executedObjectFieldContexts.Add(fieldContext);
                }
            } //foreach fldIndex
        }     //method