public IReadOnlyCollection <ResourceFieldAttribute> GetSparseFieldSetForSerializer(ResourceContext resourceContext)
        {
            if (!_visitedTable.ContainsKey(resourceContext))
            {
                var inputFields = _lazySourceTable.Value.ContainsKey(resourceContext)
                    ? _lazySourceTable.Value[resourceContext]
                    : GetResourceFields(resourceContext);

                var inputExpression  = new SparseFieldSetExpression(inputFields);
                var outputExpression = _resourceDefinitionAccessor.OnApplySparseFieldSet(resourceContext.ResourceType, inputExpression);

                HashSet <ResourceFieldAttribute> outputFields;
                if (outputExpression == null)
                {
                    outputFields = GetResourceFields(resourceContext);
                }
                else
                {
                    outputFields = new HashSet <ResourceFieldAttribute>(inputFields);
                    outputFields.IntersectWith(outputExpression.Fields);
                }

                _visitedTable[resourceContext] = outputFields;
            }

            return(_visitedTable[resourceContext]);
        }
Example #2
0
        /// <inheritdoc />
        public SparseFieldSetExpression OnApplySparseFieldSet(Type resourceType, SparseFieldSetExpression existingSparseFieldSet)
        {
            ArgumentGuard.NotNull(resourceType, nameof(resourceType));

            dynamic resourceDefinition = ResolveResourceDefinition(resourceType);

            return(resourceDefinition.OnApplySparseFieldSet(existingSparseFieldSet));
        }
        public override SparseFieldSetExpression OnApplySparseFieldSet(SparseFieldSetExpression existingSparseFieldSet)
        {
            _hitCounter.TrackInvocation <Lyric>(ResourceDefinitionHitCounter.ExtensibilityPoint.OnApplySparseFieldSet);

            return(_lyricPermissionProvider.CanViewText
                ? base.OnApplySparseFieldSet(existingSparseFieldSet)
                : existingSparseFieldSet.Excluding <Lyric>(lyric => lyric.Text, ResourceGraph));
        }
Example #4
0
        public override SparseFieldSetExpression OnApplySparseFieldSet(SparseFieldSetExpression existingSparseFieldSet)
        {
            _lyricPermissionProvider.HitCount++;

            return(_lyricPermissionProvider.CanViewText
                ? base.OnApplySparseFieldSet(existingSparseFieldSet)
                : existingSparseFieldSet.Excluding <Lyric>(lyric => lyric.Text, ResourceGraph));
        }
        public IDictionary <ResourceFieldAttribute, QueryLayer> GetSecondaryProjectionForRelationshipEndpoint(ResourceContext secondaryResourceContext)
        {
            var secondaryIdAttribute = secondaryResourceContext.Attributes.Single(a => a.Property.Name == nameof(Identifiable.Id));
            var sparseFieldSet       = new SparseFieldSetExpression(new[] { secondaryIdAttribute });

            var secondaryProjection = GetSparseFieldSetProjection(new[] { sparseFieldSet }, secondaryResourceContext) ?? new Dictionary <ResourceFieldAttribute, QueryLayer>();

            secondaryProjection[secondaryIdAttribute] = null;

            return(secondaryProjection);
        }
        /// <inheritdoc />
        public SparseFieldSetExpression OnApplySparseFieldSet(Type resourceType, SparseFieldSetExpression existingSparseFieldSet)
        {
            if (resourceType == null)
            {
                throw new ArgumentNullException(nameof(resourceType));
            }

            dynamic resourceDefinition = ResolveResourceDefinition(resourceType);

            return(resourceDefinition.OnApplySparseFieldSet(existingSparseFieldSet));
        }
Example #7
0
        private IDictionary <ResourceFieldAttribute, QueryLayer> GetProjectionForRelationship(ResourceContext secondaryResourceContext)
        {
            var secondaryIdAttribute = GetIdAttribute(secondaryResourceContext);
            var sparseFieldSet       = new SparseFieldSetExpression(new[] { secondaryIdAttribute });

            var secondaryProjection = GetSparseFieldSetProjection(new[] { sparseFieldSet }, secondaryResourceContext) ?? new Dictionary <ResourceFieldAttribute, QueryLayer>();

            secondaryProjection[secondaryIdAttribute] = null;

            return(secondaryProjection);
        }
Example #8
0
        private SparseFieldSetExpression GetSparseFieldSet(string parameterValue, ResourceContext resourceContext)
        {
            SparseFieldSetExpression sparseFieldSet = _sparseFieldSetParser.Parse(parameterValue, resourceContext);

            if (sparseFieldSet == null)
            {
                // We add ID on an incoming empty fieldset, so that callers can distinguish between no fieldset and an empty one.
                AttrAttribute idAttribute = resourceContext.Attributes.Single(attribute => attribute.Property.Name == nameof(Identifiable.Id));
                return(new SparseFieldSetExpression(ArrayFactory.Create(idAttribute)));
            }

            return(sparseFieldSet);
        }
        public SparseFieldSetExpression Parse(string source, ResourceContext resourceContext)
        {
            ArgumentGuard.NotNull(resourceContext, nameof(resourceContext));

            _resourceContext = resourceContext;

            Tokenize(source);

            SparseFieldSetExpression expression = ParseSparseFieldSet();

            AssertTokenStackIsEmpty();

            return(expression);
        }
Example #10
0
        /// <inheritdoc />
        public virtual void Read(string parameterName, StringValues parameterValue)
        {
            _lastParameterName = parameterName;

            try
            {
                ResourceContext          targetResource = GetSparseFieldType(parameterName);
                SparseFieldSetExpression sparseFieldSet = GetSparseFieldSet(parameterValue, targetResource);

                _sparseFieldTable[targetResource] = sparseFieldSet;
            }
            catch (QueryParseException exception)
            {
                throw new InvalidQueryStringParameterException(parameterName, "The specified fieldset is invalid.", exception.Message, exception);
            }
        }
Example #11
0
        public IReadOnlyCollection <AttrAttribute> GetIdAttributeSetForRelationshipQuery(ResourceContext resourceContext)
        {
            ArgumentGuard.NotNull(resourceContext, nameof(resourceContext));

            AttrAttribute idAttribute     = resourceContext.Attributes.Single(attr => attr.Property.Name == nameof(Identifiable.Id));
            var           inputExpression = new SparseFieldSetExpression(idAttribute.AsArray());

            // Intentionally not cached, as we are fetching ID only (ignoring any sparse fieldset that came from query string).
            SparseFieldSetExpression outputExpression = _resourceDefinitionAccessor.OnApplySparseFieldSet(resourceContext.ResourceType, inputExpression);

            HashSet <AttrAttribute> outputAttributes = outputExpression == null
                ? new HashSet <AttrAttribute>()
                : outputExpression.Fields.OfType <AttrAttribute>().ToHashSet();

            outputAttributes.Add(idAttribute);
            return(outputAttributes);
        }
        /// <inheritdoc/>
        public void Read(string parameterName, StringValues parameterValue)
        {
            _lastParameterName = parameterName;

            try
            {
                ResourceFieldChainExpression scope          = GetScope(parameterName);
                SparseFieldSetExpression     sparseFieldSet = GetSparseFieldSet(parameterValue, scope);

                var expressionInScope = new ExpressionInScope(scope, sparseFieldSet);
                _constraints.Add(expressionInScope);
            }
            catch (QueryParseException exception)
            {
                throw new InvalidQueryStringParameterException(parameterName, "The specified fieldset is invalid.",
                                                               exception.Message, exception);
            }
        }
        /// <inheritdoc />
        public QueryLayer WrapLayerForSecondaryEndpoint <TId>(QueryLayer secondaryLayer, ResourceContext primaryResourceContext, TId primaryId, RelationshipAttribute secondaryRelationship)
        {
            var innerInclude = secondaryLayer.Include;

            secondaryLayer.Include = null;

            var primaryIdAttribute = primaryResourceContext.Attributes.Single(x => x.Property.Name == nameof(Identifiable.Id));
            var sparseFieldSet     = new SparseFieldSetExpression(new[] { primaryIdAttribute });

            var primaryProjection = GetSparseFieldSetProjection(new[] { sparseFieldSet }, primaryResourceContext) ?? new Dictionary <ResourceFieldAttribute, QueryLayer>();

            primaryProjection[secondaryRelationship] = secondaryLayer;
            primaryProjection[primaryIdAttribute]    = null;

            return(new QueryLayer(primaryResourceContext)
            {
                Include = RewriteIncludeForSecondaryEndpoint(innerInclude, secondaryRelationship),
                Filter = CreateFilterById(primaryId, primaryResourceContext),
                Projection = primaryProjection
            });
        }
Example #14
0
        public IReadOnlyCollection <ResourceFieldAttribute> GetSparseFieldSetForQuery(ResourceContext resourceContext)
        {
            ArgumentGuard.NotNull(resourceContext, nameof(resourceContext));

            if (!_visitedTable.ContainsKey(resourceContext))
            {
                SparseFieldSetExpression inputExpression = _lazySourceTable.Value.ContainsKey(resourceContext)
                    ? new SparseFieldSetExpression(_lazySourceTable.Value[resourceContext])
                    : null;

                SparseFieldSetExpression outputExpression = _resourceDefinitionAccessor.OnApplySparseFieldSet(resourceContext.ResourceType, inputExpression);

                HashSet <ResourceFieldAttribute> outputFields = outputExpression == null
                    ? new HashSet <ResourceFieldAttribute>()
                    : outputExpression.Fields.ToHashSet();

                _visitedTable[resourceContext] = outputFields;
            }

            return(_visitedTable[resourceContext]);
        }
Example #15
0
        /// <inheritdoc />
        public QueryLayer WrapLayerForSecondaryEndpoint <TId>(QueryLayer secondaryLayer, ResourceContext primaryResourceContext, TId primaryId, RelationshipAttribute secondaryRelationship)
        {
            if (secondaryLayer == null)
            {
                throw new ArgumentNullException(nameof(secondaryLayer));
            }
            if (primaryResourceContext == null)
            {
                throw new ArgumentNullException(nameof(primaryResourceContext));
            }
            if (secondaryRelationship == null)
            {
                throw new ArgumentNullException(nameof(secondaryRelationship));
            }

            var innerInclude = secondaryLayer.Include;

            secondaryLayer.Include = null;

            var primaryIdAttribute = GetIdAttribute(primaryResourceContext);
            var sparseFieldSet     = new SparseFieldSetExpression(new[] { primaryIdAttribute });

            var primaryProjection = GetSparseFieldSetProjection(new[] { sparseFieldSet }, primaryResourceContext) ?? new Dictionary <ResourceFieldAttribute, QueryLayer>();

            primaryProjection[secondaryRelationship] = secondaryLayer;
            primaryProjection[primaryIdAttribute]    = null;

            var primaryFilter = GetFilter(Array.Empty <QueryExpression>(), primaryResourceContext);

            return(new QueryLayer(primaryResourceContext)
            {
                Include = RewriteIncludeForSecondaryEndpoint(innerInclude, secondaryRelationship),
                Filter = CreateFilterByIds(new[] { primaryId }, primaryIdAttribute, primaryFilter),
                Projection = primaryProjection
            });
        }
Example #16
0
 /// <summary>
 /// Enables to extend, replace or remove a sparse fieldset that is being applied on a set of this resource type.
 /// Tip: Use <see cref="SparseFieldSetExpressionExtensions.Including{TResource}"/> and <see cref="SparseFieldSetExpressionExtensions.Excluding{TResource}"/>
 /// to safely change the fieldset without worrying about nulls.
 /// </summary>
 /// <remarks>
 /// This method executes twice for a single request: first to select which fields to retrieve from the data store and then to
 /// select which fields to serialize. Including extra fields from this method will retrieve them, but not include them in the json output.
 /// This enables you to expose calculated properties whose value depends on a field that is not in the sparse fieldset.
 /// </remarks>
 /// <param name="existingSparseFieldSet">The incoming sparse fieldset from query string.
 /// At query execution time, this is <c>null</c> if the query string contains no sparse fieldset.
 /// At serialization time, this contains all viewable fields if the query string contains no sparse fieldset.
 /// </param>
 /// <returns>
 /// The new sparse fieldset, or <c>null</c> to discard the existing sparse fieldset and select all viewable fields.
 /// </returns>
 public virtual SparseFieldSetExpression OnApplySparseFieldSet(SparseFieldSetExpression existingSparseFieldSet)
 {
     return(existingSparseFieldSet);
 }
Example #17
0
 public SparseFieldSetExpression OnApplySparseFieldSet(Type resourceType, SparseFieldSetExpression existingSparseFieldSet)
 {
     return(existingSparseFieldSet);
 }
Example #18
0
 public SparseFieldSetExpression OnApplySparseFieldSet(SparseFieldSetExpression existingSparseFieldSet)
 {
     throw new NotImplementedException();
 }