/// <summary> /// Initializes a new instance of the <see cref="BatchResultProcessor" /> class. /// </summary> /// <param name="field">The field.</param> /// <param name="sourceItems">The source items.</param> /// <param name="origin">The origin.</param> public BatchResultProcessor(IGraphField field, IEnumerable <GraphDataItem> sourceItems, SourceOrigin origin) { _origin = origin; _field = Validation.ThrowIfNullOrReturn(field, nameof(field)); _sourceItems = Validation.ThrowIfNullOrReturn(sourceItems, nameof(sourceItems)); this.Messages = new GraphMessageCollection(); }
/// <summary> /// Initializes a new instance of the <see cref="IntrospectedInputValueType"/> class. /// </summary> /// <param name="inputField">The field of an input object used to populate this value.</param> /// <param name="introspectedGraphType">The meta data representing the type of this argument.</param> public IntrospectedInputValueType(IGraphField inputField, IntrospectedType introspectedGraphType) { Validation.ThrowIfNull(inputField, nameof(inputField)); this.IntrospectedGraphType = Validation.ThrowIfNullOrReturn(introspectedGraphType, nameof(introspectedGraphType)); this.Name = inputField.Name; this.Description = inputField.Description; }
/// <summary> /// Initializes a new instance of the <see cref="FieldContextBuilder" /> class. /// </summary> /// <param name="serviceProvider">The service provider.</param> /// <param name="user">The user.</param> /// <param name="graphField">The graph field.</param> /// <param name="schema">The schema.</param> /// <param name="graphMethod">The metadata describing the method/functon to be invoked by a resolver.</param> public FieldContextBuilder( IServiceProvider serviceProvider, ClaimsPrincipal user, IGraphField graphField, ISchema schema, IGraphMethod graphMethod) { _schema = Validation.ThrowIfNullOrReturn(schema, nameof(schema)); _graphField = Validation.ThrowIfNullOrReturn(graphField, nameof(graphField)); _user = Validation.ThrowIfNullOrReturn(user, nameof(user)); _messageCollection = new GraphMessageCollection(); this.ServiceProvider = Validation.ThrowIfNullOrReturn(serviceProvider, nameof(serviceProvider)); Type expectedInputType = null; if (!Validation.IsCastable <GraphDirective>(graphMethod.Parent.ObjectType) && !Validation.IsCastable <GraphController>(graphMethod.Parent.ObjectType)) { expectedInputType = graphMethod.Parent.ObjectType; } var metaData = new MetaDataCollection(); _mockRequest = new Mock <IGraphFieldRequest>(); _mockInvocationContext = new Mock <IGraphFieldInvocationContext>(); // fake the request for the field data (normally generated by the primary query exeuction context) var id = Guid.NewGuid().ToString("N"); _mockRequest.Setup(x => x.Id).Returns(id); _mockRequest.Setup(x => x.Origin).Returns(SourceOrigin.None); _mockRequest.Setup(x => x.Items).Returns(metaData); _mockRequest.Setup(x => x.Field).Returns(_graphField); _mockRequest.Setup(x => x.InvocationContext).Returns(_mockInvocationContext.Object); _mockInvocationContext.Setup(x => x.ExpectedSourceType).Returns(expectedInputType); _mockInvocationContext.Setup(x => x.Field).Returns(_graphField); _mockInvocationContext.Setup(x => x.Arguments).Returns(_arguments); _mockInvocationContext.Setup(x => x.Name).Returns(_graphField.Name); _mockInvocationContext.Setup(x => x.Directives).Returns(new List <IDirectiveInvocationContext>()); _mockInvocationContext.Setup(x => x.ChildContexts).Returns(new FieldInvocationContextCollection()); _mockInvocationContext.Setup(x => x.Origin).Returns(SourceOrigin.None); this.GraphMethod = new Mock <IGraphMethod>(); this.GraphMethod.Setup(x => x.Parent).Returns(graphMethod.Parent); this.GraphMethod.Setup(x => x.ObjectType).Returns(graphMethod.ObjectType); this.GraphMethod.Setup(x => x.ExpectedReturnType).Returns(graphMethod.ExpectedReturnType); this.GraphMethod.Setup(x => x.Method).Returns(graphMethod.Method); this.GraphMethod.Setup(x => x.IsAsyncField).Returns(graphMethod.IsAsyncField); this.GraphMethod.Setup(x => x.Name).Returns(graphMethod.Name); this.GraphMethod.Setup(x => x.InternalFullName).Returns(graphMethod.InternalFullName); this.GraphMethod.Setup(x => x.InternalName).Returns(graphMethod.InternalName); this.GraphMethod.Setup(x => x.Route).Returns(graphMethod.Route); this.GraphMethod.Setup(x => x.Arguments).Returns(graphMethod.Arguments); }
/// <summary> /// Adds the new field to the interface and to any object types associated with the interface. /// </summary> /// <param name="interfaceType">Type of the interface.</param> /// <param name="newField">The new field.</param> private void AddInterfaceField(IInterfaceGraphType interfaceType, IGraphField newField) { this.EnsureInterfaceIsTracked(interfaceType); interfaceType.Extend(newField); foreach (var objectType in _graphTypesByInterface[interfaceType]) { objectType.Extend(newField); } }
/// <summary> /// Attempts to retrieve a default source object for the given field. /// </summary> /// <param name="field">The expected data type of the field .</param> /// <param name="result">The result object populated with the result.</param> /// <returns><c>true</c> a source entry is found, <c>false</c> otherwise.</returns> public bool TryRetrieveSource(IGraphField field, out object result) { result = null; if (field == null || !_actionSources.ContainsKey(field.Route)) { return(false); } result = _actionSources[field.Route]; return(true); }
/// <summary> /// Adds the field extension to the associated graph type if possible. If the type is an interface the field is also /// added to any graph types that implement the interface. The field is also added to the tracker such that if any /// future graph types are added to this instance, that also implement the interface, the field is automatically added to them as well. /// If the graph type cannot accept new fields the addition is ignored and no exception is thrown. /// </summary> /// <param name="graphType">The graph type that will accept the new field.</param> /// <param name="newField">The new field to add.</param> public void AddFieldExtension(IGraphType graphType, IGraphField newField) { if (graphType is IInterfaceGraphType interfaceType) { this.AddInterfaceField(interfaceType, newField); } else if (graphType is IExtendableGraphType extendableType) { extendableType.Extend(newField); } }
/// <summary> /// Initializes a new instance of the <see cref="BatchBuilder{TSource, TResult, TKey}"/> class. /// </summary> /// <param name="field">The field for witch this batch is being produced.</param> /// <param name="sourceData">The source data.</param> /// <param name="resultData">The result data.</param> /// <param name="sourceKeySelector">The source key selector.</param> /// <param name="resultKeySelector">The result key selector.</param> public BatchBuilder( IGraphField field, IEnumerable <TSource> sourceData, IEnumerable <TResult> resultData, Func <TSource, TKey> sourceKeySelector, Func <TResult, IEnumerable <TKey> > resultKeySelector) { this.Field = field; this.SourceData = sourceData; this.ResultData = resultData; this.SourceKeySelector = sourceKeySelector; this.ResultKeySelector = resultKeySelector; }
/// <summary> /// Adds the field extension to the queue such that if a graph type associated with the supplied master type is added to the schema, /// then the new graph field is automatically added to the new graph type. /// </summary> /// <param name="masterType">The master type that, if added to the schema, will trigger the addition of this field to its associated <see cref="IGraphType"/>.</param> /// <param name="field">The field.</param> public void EnQueueField(Type masterType, IGraphField field) { if (!_unregisteredFieldExtensions.TryGetValue(masterType, out var fieldSet)) { fieldSet = new HashSet <UnregisteredGraphField>(UnregisteredGraphField.Comparer); _unregisteredFieldExtensions.TryAdd(masterType, fieldSet); } var unregisteredField = new UnregisteredGraphField(field, masterType); fieldSet.Add(unregisteredField); this.FieldCount += 1; }
/// <summary> /// Adds a default source for a controller action that can be used as an input when no other source is available. /// </summary> /// <param name="field">The field representing the controller action.</param> /// <param name="sourceData">The source data to store with this context.</param> public void AddSource(IGraphField field, object sourceData) { if (field != null && _sourceTemplateTypes.HasFlag(field.FieldSource)) { lock (_actionSources) { if (_actionSources.ContainsKey(field.Route)) { _actionSources[field.Route] = sourceData; } else { _actionSources.Add(field.Route, sourceData); } } } }
/// <summary> /// Validates the specified node to ensure it is "correct" in the context of the rule doing the valdiation. /// </summary> /// <param name="context">The validation context encapsulating a <see cref="SyntaxNode" /> that needs to be validated.</param> /// <returns><c>true</c> if the node is valid, <c>false</c> otherwise.</returns> public override bool Execute(DocumentConstructionContext context) { var node = (FieldNode)context.ActiveNode; // the '__typename' field is a known static quantity that requires no special rule processing or validation // it just exists or it doesn't and would be valid on any graph type returning it. // Group the appropriate logic for this metafield here to account for the allowed exception in spec rule 5.3.1 // where unions can contain a field reference for '__typename' var allTypes = context.DocumentContext.Schema.KnownTypes.ExpandAbstractType(context.GraphType); foreach (var graphType in allTypes) { if (graphType == null) { continue; } IGraphField field = null; if (graphType is IGraphFieldContainer fieldContainer) { field = fieldContainer.Fields.FindField(node.FieldName.ToString()); } if (field == null) { // if the graph type doesnt contain fields (scalar or enum?) this its an error. // this shouldnt happen because of schema building and validation but just in case... this.ValidationError( context, $"The graph type '{graphType.Name}' does not contain a field named '{node.FieldName.ToString()}'."); continue; } var fieldSelection = new FieldSelection(node, field, graphType); context.AddDocumentPart(fieldSelection); } return(true); }
/// <summary> /// Registers the extension field to the <see cref="IObjectGraphType" /> corrisponding to the supplied /// concrete type. If a matching graph type cannot be found for the concrete type supplied, the field /// is queued for when it is registered. /// </summary> /// <param name="masterType">The master type that, once added to the schema, will trigger that addition of this field.</param> /// <param name="field">The field that will be added to the graph type associated with the master type.</param> public void EnsureGraphFieldExtension(Type masterType, IGraphField field) { Validation.ThrowIfNull(masterType, nameof(masterType)); Validation.ThrowIfNullOrReturn(field, nameof(field)); var graphType = _concreteTypes.FindGraphType(masterType); if (graphType != null) { if (!(graphType is IExtendableGraphType)) { throw new GraphTypeDeclarationException( $"Fatal error. The graph type '{graphType.Name}' of type '{graphType.Kind.ToString()}' does not implement '{typeof(IExtendableGraphType).FriendlyName()}' " + $"and cannot be extended with the new field '{field.Name}'."); } _extendableGraphTypeTracker.AddFieldExtension(graphType, field); return; } _typeQueue.EnQueueField(masterType, field); }
/// <summary> /// Initializes a new instance of the <see cref="FieldInvocationContext" /> class. /// </summary> /// <param name="expectedSourceType">Expected type of the source.</param> /// <param name="name">The name to apply to this data set once resolution is complete.</param> /// <param name="field">The field.</param> /// <param name="origin">The origin, in the source text, that this context was generated from.</param> /// <param name="directives">The directives parsed from a query document that are to be executed as part of this context.</param> public FieldInvocationContext( Type expectedSourceType, string name, IGraphField field, SourceOrigin origin, IEnumerable <IDirectiveInvocationContext> directives = null) { this.Name = Validation.ThrowIfNullWhiteSpaceOrReturn(name, nameof(name)); this.Field = Validation.ThrowIfNullOrReturn(field, nameof(field)); this.ExpectedSourceType = expectedSourceType; this.Origin = origin; this.ChildContexts = new FieldInvocationContextCollection(); this.Arguments = new InputArgumentCollection(); var list = new List <IDirectiveInvocationContext>(); if (directives != null) { list.AddRange(directives); } this.Directives = list; }
/// <summary> /// Extends this graph type by adding a new field to its collection. An exception may be thrown if /// a field with the same name already exists. /// </summary> /// <param name="newField">The new field.</param> public void Extend(IGraphField newField) { this.GraphFieldCollection.AddField(newField); }
/// <summary> /// Adds the <see cref="IGraphField" /> to the collection. /// </summary> /// <param name="field">The field to add.</param> /// <returns>IGraphTypeField.</returns> public IGraphField AddField(IGraphField field) { Validation.ThrowIfNull(field, nameof(field)); _fields.Add(field.Name, field); return(field); }
/// <summary> /// Finds the graph type, if any, associated with the given field. /// </summary> /// <param name="field">The field.</param> /// <returns>IGraphType.</returns> public IGraphType FindGraphType(IGraphField field) { return(this.FindGraphType(field?.TypeExpression?.TypeName)); }
/// <summary> /// Initializes a new instance of the <see cref="BatchBuilder{TSource, TKey}" /> class. /// </summary> /// <param name="field">The field for witch this batch is being produced.</param> /// <param name="sourceData">The source data.</param> /// <param name="sourceKeySelector">A function to extract a single key value from each source item.</param> public BatchBuilder(IGraphField field, IEnumerable <TSource> sourceData, Func <TSource, TKey> sourceKeySelector) : base(field, sourceData, null, sourceKeySelector, null) { }
/// <summary> /// Initializes a new instance of the <see cref="BatchBuilder" /> class. /// </summary> /// <param name="field">The field for witch this batch is being produced.</param> public BatchBuilder(IGraphField field) : base(field, null, null, null, null) { }
/// <summary> /// Extends this graph type by adding a new field to its collection. An exception may be thrown if /// a field with the same name already exists. /// </summary> /// <param name="newField">The new field.</param> public void Extend(IGraphField newField) { throw new GraphTypeDeclarationException($"Introspection type '{this.Name}' cannot be extended"); }
/// <summary> /// Determines whether the specified field has an item defined in this collection. /// </summary> /// <param name="field">The field.</param> /// <returns><c>true</c> if the specified field has a defined value; otherwise, <c>false</c>.</returns> public bool ContainsKey(IGraphField field) { return(field?.Route != null && _actionSources.ContainsKey(field.Route)); }
/// <summary> /// Initializes a new instance of the <see cref="IntrospectedField" /> class. /// </summary> /// <param name="field">The field itself.</param> /// <param name="introspectedType">The introspected object representing the graph type returned /// by this field.</param> public IntrospectedField(IGraphField field, IntrospectedType introspectedType) { this.IntrospectedGraphType = Validation.ThrowIfNullOrReturn(introspectedType, nameof(introspectedType)); _field = Validation.ThrowIfNullOrReturn(field, nameof(field)); }
/// <summary> /// Initializes a new instance of the <see cref="UnregisteredGraphField" /> class. /// </summary> /// <param name="field">The field to register.</param> /// <param name="concreteType">The concrete type representing the graph type to which this field should /// be added.</param> public UnregisteredGraphField(IGraphField field, Type concreteType) { this.Field = Validation.ThrowIfNullOrReturn(field, nameof(field)); this.ConcreteType = Validation.ThrowIfNullOrReturn(concreteType, nameof(concreteType)); }
/// <summary> /// Extends the specified new field. /// </summary> /// <param name="newField">The new field.</param> public void Extend(IGraphField newField) { _fieldSet.AddField(newField); }