private CachedField GetFieldsAndFragmentNames( Dictionary <GraphQLSelectionSet, CachedField> cachedFieldsAndFragmentNames, IType parentType, GraphQLSelectionSet selectionSet) { cachedFieldsAndFragmentNames.TryGetValue(selectionSet, out var cached); if (cached == null) { var nodeAndDef = new Dictionary <string, List <FieldDefPair> >(); var fragmentNames = new Dictionary <string, bool>(); CollectFieldsAndFragmentNames( parentType, selectionSet, nodeAndDef, fragmentNames); cached = new CachedField { NodeAndDef = nodeAndDef, Names = fragmentNames.Keys.ToList() }; cachedFieldsAndFragmentNames.Add(selectionSet, cached); } return(cached); }
public void NotMergeAliasedFields() { var outerSelection = new GraphQLSelectionSet { Selections = new List <ASTNode> { FirstTestField, AliasedTestField } }; var query = new ObjectGraphType { Name = "Query" }; query.Fields.Add(new FieldType { Name = "test", ResolvedType = new StringGraphType() }); var context = new ExecutionContext { Schema = new Schema { Query = query } }; var fields = CollectFrom(context, query, outerSelection); fields["test"].Field.SelectionSet.Selections.ShouldHaveSingleItem(); fields["test"].Field.SelectionSet.Selections.ShouldContain(x => x == FirstInnerField); fields["alias"].Field.SelectionSet.Selections.ShouldHaveSingleItem(); fields["alias"].Field.SelectionSet.Selections.ShouldContain(x => x == SecondInnerField); }
private static MapObject GetHashMap( GraphQLSelectionSet selectionSet, Type unsafeType) { var mapObject = new MapObject(); var type = GetTypeIfArray(unsafeType); foreach (var selection in selectionSet.Selections) { if (!(selection is GraphQLFieldSelection fieldSelection)) { continue; } var name = GetName(fieldSelection.Name.Value, type); if (fieldSelection.SelectionSet == null) { mapObject = mapObject.With(name, true); } else { var property = type.GetProperty(name); var ignore = property.GetCustomAttribute <JsonIgnoreAttribute>() != null; if (ignore) { continue; } var newType = property.PropertyType; mapObject = mapObject.With(name, GetHashMap(fieldSelection.SelectionSet, newType)); } } return(mapObject); }
private void GetFieldsAndFragmentNames( GraphQLSelectionSet node, Dictionary <string, ICollection <NodeAndDefinitions> > nodeDefinitions, ICollection <string> fragmentNames, GraphQLBaseType parentType, string presumedParentName = null) { foreach (var selection in node.Selections) { switch (selection.Kind) { case ASTNodeKind.Field: var fieldSelection = selection as GraphQLFieldSelection; var fieldName = fieldSelection.Name.Value; GraphQLObjectTypeFieldInfo fieldDefinition = null; if (parentType is GraphQLComplexType) { fieldDefinition = ((GraphQLComplexType)parentType).GetFieldInfo(fieldName); } var responseName = fieldSelection.Alias != null ? fieldSelection.Alias.Value : fieldName; if (!nodeDefinitions.ContainsKey(responseName)) { nodeDefinitions.Add(responseName, new List <NodeAndDefinitions>()); } nodeDefinitions[responseName].Add(new NodeAndDefinitions() { PresumedParentName = presumedParentName, ParentType = parentType, Selection = fieldSelection, FieldDefinition = fieldDefinition }); break; case ASTNodeKind.FragmentSpread: fragmentNames.Add(((GraphQLFragmentSpread)selection).Name.Value); break; case ASTNodeKind.InlineFragment: var inlineFragment = selection as GraphQLInlineFragment; var typeCondition = inlineFragment.TypeCondition; var inlineFragmentType = typeCondition != null ? this.SchemaRepository.GetSchemaOutputTypeByName(typeCondition.Name.Value) : parentType; this.GetFieldsAndFragmentNames( inlineFragment.SelectionSet, nodeDefinitions, fragmentNames, inlineFragmentType, typeCondition?.Name?.Value); break; } } }
/// <summary> /// Returns a list of fragment spreads within the specified node. /// </summary> public List <GraphQLFragmentSpread> GetFragmentSpreads(GraphQLSelectionSet node) { var spreads = new List <GraphQLFragmentSpread>(); var setsToVisit = new Stack <GraphQLSelectionSet>(); setsToVisit.Push(node); while (setsToVisit.Count > 0) { var set = setsToVisit.Pop(); foreach (var selection in set.Selections) { if (selection is GraphQLFragmentSpread spread) { spreads.Add(spread); } else if (selection is IHasSelectionSetNode hasSet && hasSet.SelectionSet != null) { setsToVisit.Push(hasSet.SelectionSet); } } } return(spreads); }
private IEnumerable <Conflict> FindCnflictsWithinSelectionSet(GraphQLSelectionSet node) { var fieldMap = new Dictionary <string, ICollection <NodeAndDefinitions> >(); var fragmentNames = new List <string>(); var conflicts = new List <Conflict>(); var parentObject = this.GetLastType(); this.GetFieldsAndFragmentNames( node, fieldMap, fragmentNames, parentObject); conflicts.AddRange(this.CollectConflictsWithin(node, fieldMap)); for (var i = 0; i < fragmentNames.Count; i++) { conflicts.AddRange(this.CollectConflictsBetweenFieldsAndFragment( fieldMap, fragmentNames.ElementAt(i), false)); for (var j = i + 1; j < fragmentNames.Count; j++) { conflicts.AddRange(this.CollectConflictsBetweenFragments( fragmentNames.ElementAt(i), fragmentNames.ElementAt(j), false)); } } return(conflicts); }
private IEnumerable <GraphQLFragmentSpread> GetFragmentSpreads(GraphQLSelectionSet selectionSet) { if (selectionSet == null || selectionSet.Selections == null) { return new GraphQLFragmentSpread[] { } } ; var spreads = selectionSet.Selections .Where(e => e.Kind == ASTNodeKind.FragmentSpread) .Cast <GraphQLFragmentSpread>() .ToList(); var fields = selectionSet.Selections .Where(e => e.Kind == ASTNodeKind.Field) .Cast <GraphQLFieldSelection>() .ToList(); foreach (var field in fields) { spreads.AddRange(this.GetFragmentSpreads(field.SelectionSet)); } var inlineSpreads = selectionSet.Selections .Where(e => e.Kind == ASTNodeKind.InlineFragment) .Cast <GraphQLInlineFragment>() .ToList(); foreach (var spread in inlineSpreads) { spreads.AddRange(this.GetFragmentSpreads(spread.SelectionSet)); } return(spreads); }
public void BeMergedCorrectlyInCaseOfFields() { var outerSelection = new GraphQLSelectionSet { Selections = new List <ASTNode> { FirstTestField, SecondTestField } }; var query = new ObjectGraphType { Name = "Query" }; query.Fields.Add(new FieldType { Name = "test", ResolvedType = new StringGraphType() }); var context = new ExecutionContext { Schema = new Schema { Query = query } }; var fields = CollectFrom(context, query, outerSelection); fields.ContainsKey("test").ShouldBeTrue(); fields["test"].Field.SelectionSet.Selections.ShouldContain(x => x == FirstInnerField); fields["test"].Field.SelectionSet.Selections.ShouldContain(x => x == SecondInnerField); }
private IEnumerable <Conflict> CollectConflictsWithin( GraphQLSelectionSet node, IDictionary <string, ICollection <NodeAndDefinitions> > fieldMap) { foreach (var pair in fieldMap) { var fields = pair.Value; if (fields.Count > 1) { for (var i = 0; i < fields.Count; i++) { for (var j = i + 1; j < fields.Count; j++) { var conflict = this.FindConflict( false, // within one collection is never mutually exclusive pair.Key, fields.ElementAt(i), fields.ElementAt(j)); if (conflict != null) { yield return(conflict); } } } } } }
public SetSelection(GraphQLSelectionSet op) { this.op = op; var nodes = op.Selections.Select(Visit).ToList(); this.Fields = nodes.OfType <FieldSelection>().ToList(); this.Fragments = nodes.OfType <SetSelection>().ToList(); }
private List <Conflict> FindConflictsWithinGraphQLSelectionSet( Dictionary <GraphQLSelectionSet, CachedField> cachedFieldsAndFragmentNames, PairSet comparedFragmentPairs, INamedType parentType, GraphQLSelectionSet selectionSet) { var conflicts = new List <Conflict>(); var cachedField = GetFieldsAndFragmentNames( cachedFieldsAndFragmentNames, parentType, selectionSet); var fieldMap = cachedField.NodeAndDef; var fragmentNames = cachedField.Names; CollectConflictsWithin( 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 (var i = 0; i < fragmentNames.Count; i++) { CollectConflictsBetweenFieldsAndFragment( 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 (var j = i + 1; j < fragmentNames.Count; j++) { CollectConflictsBetweenFragments( conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, false, fragmentNames[i], fragmentNames[j]); } } } return(conflicts); }
private void CollectFieldsAndFragmentNames( IType parentType, GraphQLSelectionSet selectionSet, Dictionary <string, List <FieldDefPair> > nodeAndDefs, Dictionary <string, bool> fragments) { var selections = selectionSet.Selections.ToArray(); for (var i = 0; i < selections.Length; i++) { var selection = selections[i]; if (selection is GraphQLFieldSelection field) { var fieldName = field.Name.Value; IField fieldDef = null; if (isObjectType(parentType) || isInterfaceType(parentType)) { fieldDef = _context.Schema.GetField( ((INamedType)parentType).Name, fieldName); } var responseName = !string.IsNullOrWhiteSpace(field.Alias?.Value) ? field.Alias.Value : fieldName; if (!nodeAndDefs.ContainsKey(responseName)) { nodeAndDefs[responseName] = new List <FieldDefPair>(); } nodeAndDefs[responseName].Add(new FieldDefPair { ParentType = parentType, Field = field, FieldDef = fieldDef }); } else if (selection is GraphQLFragmentSpread fragmentSpread) { fragments[fragmentSpread.Name.Value] = true; } else if (selection is GraphQLInlineFragment inlineFragment) { var typeCondition = inlineFragment.TypeCondition; var inlineFragmentType = typeCondition != null ? Ast.TypeFromAst(_context.Schema, typeCondition) : parentType; CollectFieldsAndFragmentNames( inlineFragmentType, inlineFragment.SelectionSet, nodeAndDefs, fragments); } } }
private string PrintSelectionSet(GraphQLSelectionSet selectionSet) { if (selectionSet == null) { return(string.Empty); } return(Block(selectionSet.Selections?.Select(Print))); }
public SetSelection(GraphQLSelectionSet op) { this.op = op; List <object> nodes = op.Selections.Select(this.Visit).ToList(); this.fields.AddRange(nodes.OfType <FieldSelection>()); this.inlineFragments.AddRange(nodes.OfType <SetSelection>()); this.fragmentNames = nodes.OfType <GraphQLName>().ToList(); }
public virtual GraphQLSelectionSet BeginVisitSelectionSet( GraphQLSelectionSet selectionSet) { foreach (var selection in selectionSet.Selections) { BeginVisitNode(selection); } return(selectionSet); }
public SelectionSet SelectionSet(GraphQLSelectionSet source) { var set = new SelectionSet().WithLocation(source, _body); source?.Selections.Apply(s => { set.Add(Selection(s)); }); return(set); }
public Dictionary <string, IList <GraphQLFieldSelection> > CollectFields( GraphQLComplexType runtimeType, GraphQLSelectionSet selectionSet) { var fields = new Dictionary <string, IList <GraphQLFieldSelection> >(); foreach (var selection in selectionSet.Selections) { this.CollectFieldsInSelection(runtimeType, selection, fields); } return(fields); }
public override GraphQLSelectionSet BeginVisitSelectionSet(GraphQLSelectionSet node) { var conflicts = this.FindCnflictsWithinSelectionSet(node); foreach (var conflict in conflicts) { this.Errors.Add(new GraphQLException(this.FieldsConflictMessage(conflict), conflict.Field1.Concat(conflict.Field2))); } return(base.BeginVisitSelectionSet(node)); }
private IEnumerable <Conflict> FindConflictsBetweenSubSelectionSets( GraphQLBaseType type1, GraphQLBaseType type2, GraphQLSelectionSet selectionSet1, GraphQLSelectionSet selectionSet2, bool areMutuallyExclusive) { var conflicts = new List <Conflict>(); var fieldMap1 = new Dictionary <string, ICollection <NodeAndDefinitions> >(); var fragmentNames1 = new List <string>(); this.GetFieldsAndFragmentNames( selectionSet1, fieldMap1, fragmentNames1, type1); var fieldMap2 = new Dictionary <string, ICollection <NodeAndDefinitions> >(); var fragmentNames2 = new List <string>(); this.GetFieldsAndFragmentNames( selectionSet2, fieldMap2, fragmentNames2, type2); conflicts.AddRange(this.CollectConflictsBetween(areMutuallyExclusive, fieldMap1, fieldMap2)); foreach (var frag in fragmentNames2) { conflicts.AddRange(this.CollectConflictsBetweenFieldsAndFragment( fieldMap1, frag, areMutuallyExclusive)); } foreach (var frag in fragmentNames1) { conflicts.AddRange(this.CollectConflictsBetweenFieldsAndFragment( fieldMap2, frag, areMutuallyExclusive)); } foreach (var frag1 in fragmentNames1) { foreach (var frag2 in fragmentNames2) { conflicts.AddRange(this.CollectConflictsBetweenFragments( frag1, frag2, areMutuallyExclusive)); } } return(conflicts); }
public SelectionSet SelectionSet(GraphQLSelectionSet source) { var set = new SelectionSet().WithLocation(source, _body); if (source != null) { foreach (var s in source.Selections) { set.Add(Selection(s)); } } return(set); }
public List <GraphQLFragmentSpread> GetFragmentSpreads(GraphQLSelectionSet node) { var spreads = new List <GraphQLFragmentSpread>(); var setsToVisit = new Stack <GraphQLSelectionSet>(new[] { node }); while (setsToVisit.Count > 0) { var set = setsToVisit.Pop(); foreach (var selection in set.Selections) { switch (selection) { case GraphQLFragmentSpread spread: spreads.Add(spread); break; case GraphQLInlineFragment inlineFragment: { if (inlineFragment.SelectionSet != null) { setsToVisit.Push(inlineFragment.SelectionSet); } break; } case GraphQLOperationDefinition operationDefinition: { if (operationDefinition.SelectionSet != null) { setsToVisit.Push(operationDefinition.SelectionSet); } break; } case GraphQLFieldSelection fieldSelection: { if (fieldSelection.SelectionSet != null) { setsToVisit.Push(fieldSelection.SelectionSet); } break; } } } } return(spreads); }
private SelectExpandClause BuildSelectExpandClause(IEdmEntitySet entitySet, GraphQLSelectionSet selectionSet) { var selectItems = new List <SelectItem>(); foreach (ASTNode astNode in selectionSet.Selections) { if (astNode is GraphQLFieldSelection fieldSelection) { IEdmProperty edmProperty = FindEdmProperty(entitySet.EntityType(), fieldSelection.Name.Value); if (fieldSelection.SelectionSet == null) { var structuralProperty = (IEdmStructuralProperty)edmProperty; selectItems.Add(new PathSelectItem(new ODataSelectPath(new PropertySegment(structuralProperty)))); } else { var navigationProperty = (IEdmNavigationProperty)edmProperty; IEdmEntitySet parentEntitySet; if (navigationProperty.ContainsTarget) { ModelBuilder.ManyToManyJoinDescription joinDescription = _edmModel.GetManyToManyJoinDescription(navigationProperty); parentEntitySet = OeEdmClrHelper.GetEntitySet(_edmModel, joinDescription.TargetNavigationProperty); } else { parentEntitySet = OeEdmClrHelper.GetEntitySet(_edmModel, navigationProperty); } var expandPath = new ODataExpandPath(new NavigationPropertySegment(navigationProperty, parentEntitySet)); FilterClause filterOption = null; if (fieldSelection.Arguments.Any()) { filterOption = BuildFilterClause(parentEntitySet, fieldSelection); } SelectExpandClause childSelectExpand = BuildSelectExpandClause(parentEntitySet, fieldSelection.SelectionSet); var expandedSelectItem = new ExpandedNavigationSelectItem(expandPath, parentEntitySet, childSelectExpand, filterOption, null, null, null, null, null, null); selectItems.Add(expandedSelectItem); } } else { throw new NotSupportedException("selection " + astNode.GetType().Name + " not supported"); } } return(new SelectExpandClause(selectItems, false)); }
private dynamic ComposeResultForType(GraphQLObjectType type, GraphQLSelectionSet selectionSet) { var variableResolver = new VariableResolver(this.variables, this.graphQLSchema.TypeTranslator, this.operation.VariableDefinitions); var valueResolver = new ValueResolver(variableResolver, this.graphQLSchema.TypeTranslator); var fieldCollector = new FieldCollector(this.fragments, valueResolver); var scope = new FieldScope( this.graphQLSchema.TypeTranslator, valueResolver, fieldCollector, type, null); return(scope.GetObject(fieldCollector.CollectFields(type, selectionSet))); }
/// <summary> /// Converts a selection set node and its children. /// </summary> private static SelectionSet SelectionSet(GraphQLSelectionSet source) { var set = new SelectionSet(); if (source != null) { set.SourceLocation = Convert(source.Location); foreach (var s in source.Selections) { set.Add(Selection(s)); } } return(set); }
public override GraphQLSelectionSet BeginVisitSelectionSet( GraphQLSelectionSet selectionSet) { { Tracker.EnterSelectionSet?.Invoke(selectionSet); } var _ = base.BeginVisitSelectionSet(selectionSet); { Tracker.LeaveSelectionSet?.Invoke(selectionSet); } return(_); }
private SelectExpandClause BuildSelectExpandClause(IEdmEntitySet entitySet, GraphQLSelectionSet selectionSet) { var selectItems = new List <SelectItem>(); foreach (ASTNode astNode in selectionSet.Selections) { if (astNode is GraphQLFieldSelection fieldSelection) { IEdmProperty edmProperty = FindEdmProperty(entitySet.EntityType(), fieldSelection.Name.Value); if (fieldSelection.SelectionSet == null) { var structuralProperty = (IEdmStructuralProperty)edmProperty; selectItems.Add(new PathSelectItem(new ODataSelectPath(new PropertySegment(structuralProperty)))); } else { IEdmType edmType = edmProperty.Type.Definition; if (edmType is IEdmCollectionType collectionType) { edmType = collectionType.ElementType.Definition; } IEdmEntitySet parentEntitySet = OeEdmClrHelper.GetEntitySet(_edmModel, edmType); SelectExpandClause childSelectExpand = BuildSelectExpandClause(parentEntitySet, fieldSelection.SelectionSet); var navigationProperty = (IEdmNavigationProperty)edmProperty; IEdmEntitySet navigationSource = OeEdmClrHelper.GetEntitySet(_edmModel, navigationProperty.Type.Definition); var expandPath = new ODataExpandPath(new NavigationPropertySegment(navigationProperty, navigationSource)); FilterClause filterOption = null; if (fieldSelection.Arguments.Any()) { filterOption = BuildFilterClause(parentEntitySet, fieldSelection); } var expandedSelectItem = new ExpandedNavigationSelectItem(expandPath, navigationSource, childSelectExpand, filterOption, null, null, null, null, null, null); selectItems.Add(expandedSelectItem); } } else { throw new NotSupportedException("selection " + astNode.GetType().Name + " not supported"); } } return(new SelectExpandClause(selectItems, false)); }
private T GetWithDocument <T>(GraphQLSelectionSet selectionSet, Id id) where T : class { var type = typeof(T); var hashMap = GetHashMap(selectionSet, type); try { var result = GetFromDb <T>(id, hashMap); var ret = Utils.DeserializeObject(typeof(T), result); return(ret as T); } catch (Exception) { return(null); } }
public void Validate(GraphQLSelectionSet selectionSet) { var comparedFragmentPairs = new PairSet(); var cachedFieldsAndFragmentNames = new Dictionary <GraphQLSelectionSet, CachedField>(); var conflicts = FindConflictsWithinGraphQLSelectionSet( cachedFieldsAndFragmentNames, comparedFragmentPairs, _context.Tracker.GetParentType(), selectionSet); foreach (var conflict in conflicts) { _context.Error( ValidationErrorCodes.R532FieldSelectionMerging, FieldsConflictMessage(conflict.Reason.Name, conflict.Reason), conflict.FieldsLeft.Concat(conflict.FieldsRight) ); } }
public RepeatedSubfieldsTests() { FirstInnerField = new GraphQLField { Name = new GraphQLName("first") }; FirstFieldSelection = new GraphQLSelectionSet { Selections = new List <ASTNode> { FirstInnerField } }; SecondInnerField = new GraphQLField { Name = new GraphQLName("second") }; SecondFieldSelection = new GraphQLSelectionSet { Selections = new List <ASTNode> { SecondInnerField } }; FirstTestField = new GraphQLField { Name = new GraphQLName("test") }; SecondTestField = new GraphQLField { Name = new GraphQLName("test") }; AliasedTestField = new GraphQLField { Alias = new GraphQLAlias { Name = new GraphQLName("alias") }, Name = new GraphQLName("test") }; FirstTestField.SelectionSet = FirstFieldSelection; SecondTestField.SelectionSet = SecondFieldSelection; AliasedTestField.SelectionSet = SecondFieldSelection; }
public static async Task <IDictionary <string, object> > ExecuteSelectionSetAsync( IExecutorContext executorContext, GraphQLSelectionSet selectionSet, ObjectType objectType, object objectValue, NodePath path) { var groupedFieldSet = CollectFields( executorContext.Schema, executorContext.Document, objectType, selectionSet, executorContext.CoercedVariableValues); var resultMap = await executorContext.Strategy.ExecuteGroupedFieldSetAsync( executorContext, groupedFieldSet, objectType, objectValue, path).ConfigureAwait(false); return(resultMap); }