예제 #1
0
        /// <summary>Tries to create a key segment for the given filter if it is non empty.</summary>
        /// <param name="previous">Segment on which to compose.</param>
        /// <param name="previousKeySegment">The parent node's key segment.</param>
        /// <param name="parenthesisExpression">Parenthesis expression of segment.</param>
        /// <param name="keySegment">The key segment that was created if the key was non-empty.</param>
        /// <param name="enableUriTemplateParsing">Whether Uri template parsing is enabled.</param>
        /// <param name="resolver">The resolver to use.</param>
        /// <returns>Whether the key was non-empty.</returns>
        internal static bool TryCreateKeySegmentFromParentheses(ODataPathSegment previous, KeySegment previousKeySegment, string parenthesisExpression, out ODataPathSegment keySegment, bool enableUriTemplateParsing = false, ODataUriResolver resolver = null)
        {
            Debug.Assert(parenthesisExpression != null, "parenthesisExpression != null");
            Debug.Assert(previous != null, "segment!= null");

            if (resolver == null)
            {
                resolver = ODataUriResolver.Default;
            }

            if (previous.SingleResult)
            {
                throw ExceptionUtil.CreateSyntaxError();
            }

            SegmentArgumentParser key;

            if (!SegmentArgumentParser.TryParseKeysFromUri(parenthesisExpression, out key, enableUriTemplateParsing))
            {
                throw ExceptionUtil.CreateSyntaxError();
            }

            // People/NS.Employees() is OK, just like People() is OK
            if (key.IsEmpty)
            {
                keySegment = null;
                return(false);
            }

            keySegment = CreateKeySegment(previous, previousKeySegment, key, resolver);
            return(true);
        }
예제 #2
0
        public void SyntaxErrorHelperShouldSetMessageCorrectly()
        {
            var exception = ExceptionUtil.CreateSyntaxError();

            Assert.Equal(Strings.RequestUriProcessor_SyntaxError, exception.Message);

            string a = Strings.General_InternalError(Microsoft.OData.UriParser.InternalErrorCodes.UriQueryExpressionParser_ParseComparison);
        }
예제 #3
0
        /// <summary>
        /// Parses the key properties based on the segment's target type, then creates a new segment for the key.
        /// </summary>
        /// <param name="segment">The segment to apply the key to.</param>
        /// <param name="previousKeySegment">The parent node's key segment.</param>
        /// <param name="key">The key to apply.</param>
        /// <param name="resolver">The resolver to use.</param>
        /// <returns>The newly created key segment.</returns>
        private static KeySegment CreateKeySegment(ODataPathSegment segment, KeySegment previousKeySegment, SegmentArgumentParser key, ODataUriResolver resolver)
        {
            Debug.Assert(segment != null, "segment != null");
            Debug.Assert(key != null && !key.IsEmpty, "key != null && !key.IsEmpty");
            Debug.Assert(segment.SingleResult == false, "segment.SingleResult == false");

            IEdmEntityType targetEntityType = null;

            if (!(segment.TargetEdmType != null && segment.TargetEdmType.IsEntityOrEntityCollectionType(out targetEntityType)))
            {
                throw ExceptionUtil.CreateSyntaxError();
            }

            Debug.Assert(targetEntityType != null, "targetEntityType != null");

            // Make sure the keys specified in the uri matches with the number of keys in the metadata
            var keyProperties = targetEntityType.Key().ToList();

            if (keyProperties.Count != key.ValueCount)
            {
                NavigationPropertySegment currentNavPropSegment = segment as NavigationPropertySegment;
                if (currentNavPropSegment != null)
                {
                    key = KeyFinder.FindAndUseKeysFromRelatedSegment(key, keyProperties, currentNavPropSegment.NavigationProperty, previousKeySegment);
                }

                // if we still didn't find any keys, then throw an error.
                if (keyProperties.Count != key.ValueCount && resolver.GetType() == typeof(ODataUriResolver))
                {
                    throw ExceptionUtil.CreateBadRequestError(ErrorStrings.BadRequest_KeyCountMismatch(targetEntityType.FullName()));
                }
            }

            if (!key.AreValuesNamed && key.ValueCount > 1 && resolver.GetType() == typeof(ODataUriResolver))
            {
                throw ExceptionUtil.CreateBadRequestError(ErrorStrings.RequestUriProcessor_KeysMustBeNamed);
            }

            IEnumerable <KeyValuePair <string, object> > keyPairs;

            if (!key.TryConvertValues(targetEntityType, out keyPairs, resolver))
            {
                throw ExceptionUtil.CreateSyntaxError();
            }

            IEdmEntityType entityType;
            bool           isEntity = segment.TargetEdmType.IsEntityOrEntityCollectionType(out entityType);

            Debug.Assert(isEntity, "Key target type should be an entity type.");

            var keySegment = new KeySegment(keyPairs, entityType, segment.TargetEdmNavigationSource);

            keySegment.CopyValuesFrom(segment);
            keySegment.SingleResult = true;

            return(keySegment);
        }
예제 #4
0
        /// <summary>
        /// Gets the target entity set for the given operation import.
        /// </summary>
        /// <param name="operationImport">The operation import.</param>
        /// <param name="sourceEntitySet">The source entity set.</param>
        /// <param name="model">The model.</param>
        /// <returns>The target entity set of the operation import or null if it could not be determined.</returns>
        internal static IEdmEntitySetBase GetTargetEntitySet(this IEdmOperationImport operationImport, IEdmEntitySetBase sourceEntitySet, IEdmModel model)
        {
            IEdmEntitySet targetEntitySet;

            if (operationImport.TryGetStaticEntitySet(out targetEntitySet))
            {
                return(targetEntitySet);
            }

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

            if (operationImport.Operation.IsBound && operationImport.Operation.Parameters.Any())
            {
                IEdmOperationParameter parameter;
                IEnumerable <IEdmNavigationProperty> path;
                IEnumerable <EdmError> errors;

                if (operationImport.TryGetRelativeEntitySetPath(model, out parameter, out path, out errors))
                {
                    IEdmEntitySetBase currentEntitySet = sourceEntitySet;
                    foreach (var navigation in path)
                    {
                        currentEntitySet = currentEntitySet.FindNavigationTarget(navigation) as IEdmEntitySetBase;
                        if (currentEntitySet == null || currentEntitySet is IEdmUnknownEntitySet)
                        {
                            return(currentEntitySet);
                        }
                    }

                    return(currentEntitySet);
                }
                else
                {
                    if (errors.Any(
                            e => e.ErrorCode == EdmErrorCode.InvalidPathFirstPathParameterNotMatchingFirstParameterName))
                    {
                        throw ExceptionUtil.CreateSyntaxError();
                    }
                }
            }

            return(null);
        }
예제 #5
0
        /// <summary>
        /// Resolve keys for certain entity set, this function would be called when key is specified as positional values. E.g. EntitySet('key')
        /// </summary>
        /// <param name="type">Type for current entityset.</param>
        /// <param name="positionalValues">The list of positional values.</param>
        /// <param name="convertFunc">The convert function to be used for value converting.</param>
        /// <returns>The resolved key list.</returns>
        public virtual IEnumerable <KeyValuePair <string, object> > ResolveKeys(IEdmEntityType type, IList <string> positionalValues, Func <IEdmTypeReference, string, object> convertFunc)
        {
            var keyProperties = type.Key().ToList();
            var keyPairList   = new List <KeyValuePair <string, object> >(positionalValues.Count);

            for (int i = 0; i < keyProperties.Count; i++)
            {
                string       valueText      = positionalValues[i];
                IEdmProperty keyProperty    = keyProperties[i];
                object       convertedValue = convertFunc(keyProperty.Type, valueText);
                if (convertedValue == null)
                {
                    throw ExceptionUtil.CreateSyntaxError();
                }

                keyPairList.Add(new KeyValuePair <string, object>(keyProperty.Name, convertedValue));
            }

            return(keyPairList);
        }
예제 #6
0
        /// <summary>
        /// Resolve keys for certain entity set, this function would be called when key is specified as name value pairs. E.g. EntitySet(ID='key')
        /// </summary>
        /// <param name="type">Type for current entityset.</param>
        /// <param name="namedValues">The dictionary of name value pairs.</param>
        /// <param name="convertFunc">The convert function to be used for value converting.</param>
        /// <returns>The resolved key list.</returns>
        public virtual IEnumerable <KeyValuePair <string, object> > ResolveKeys(IEdmEntityType type, IDictionary <string, string> namedValues, Func <IEdmTypeReference, string, object> convertFunc)
        {
            var convertedPairs = new Dictionary <string, object>(StringComparer.Ordinal);
            var keyProperties  = type.Key().ToList();

            foreach (IEdmStructuralProperty property in keyProperties)
            {
                string valueText;

                if (EnableCaseInsensitive)
                {
                    var list = namedValues.Keys.Where(key => string.Equals(property.Name, key, StringComparison.OrdinalIgnoreCase)).ToList();
                    if (list.Count > 1)
                    {
                        // TODO: fix loc strings.
                        throw new ODataException("More than one key match the name '" + property.Name + "' were found.");
                    }
                    else if (list.Count == 0)
                    {
                        throw ExceptionUtil.CreateSyntaxError();
                    }

                    valueText = namedValues[list.Single()];
                }
                else if (!namedValues.TryGetValue(property.Name, out valueText))
                {
                    throw ExceptionUtil.CreateSyntaxError();
                }

                //// Debug.Assert(property.Type.IsPrimitive() || property.Type.IsTypeDefinition(), "Keys can only be primitive or type definition");
                object convertedValue = convertFunc(property.Type, valueText);
                if (convertedValue == null)
                {
                    throw ExceptionUtil.CreateSyntaxError();
                }

                convertedPairs[property.Name] = convertedValue;
            }

            return(convertedPairs);
        }
예제 #7
0
        /// <summary>
        /// Gets the target entity set for the given operation import.
        /// </summary>
        /// <param name="operation">The operation.</param>
        /// <param name="source">The source of operation.</param>
        /// <param name="model">The model.</param>
        /// <returns>The target entity set of the operation import or null if it could not be determined.</returns>
        internal static IEdmEntitySetBase GetTargetEntitySet(this IEdmOperation operation, IEdmNavigationSource source, IEdmModel model)
        {
            if (source == null)
            {
                return(null);
            }

            if (operation.IsBound && operation.Parameters.Any())
            {
                IEdmOperationParameter parameter;
                IEnumerable <IEdmNavigationProperty> path;
                IEdmEntityType         lastEntityType;
                IEnumerable <EdmError> errors;

                if (operation.TryGetRelativeEntitySetPath(model, out parameter, out path, out lastEntityType, out errors))
                {
                    IEdmNavigationSource target = source;
                    foreach (var navigation in path)
                    {
                        target = target.FindNavigationTarget(navigation);
                        if (target == null)
                        {
                            return(null);
                        }
                    }

                    return(target as IEdmEntitySetBase);
                }
                else
                {
                    if (errors.Any(
                            e => e.ErrorCode == EdmErrorCode.InvalidPathFirstPathParameterNotMatchingFirstParameterName))
                    {
                        throw ExceptionUtil.CreateSyntaxError();
                    }
                }
            }

            return(null);
        }
예제 #8
0
        /// <summary>
        /// Resolve keys for certain entity set, this function would be called when key is specified as name value pairs. E.g. EntitySet(ID='key')
        /// </summary>
        /// <param name="type">Type for current entityset.</param>
        /// <param name="namedValues">The dictionary of name value pairs.</param>
        /// <param name="convertFunc">The convert function to be used for value converting.</param>
        /// <returns>The resolved key list.</returns>
        public virtual IEnumerable <KeyValuePair <string, object> > ResolveKeys(IEdmEntityType type, IDictionary <string, string> namedValues, Func <IEdmTypeReference, string, object> convertFunc)
        {
            var convertedPairs = new Dictionary <string, object>(StringComparer.Ordinal);
            var keyProperties  = type.Key().ToList();

            foreach (IEdmStructuralProperty property in keyProperties)
            {
                string valueText;

                if (EnableCaseInsensitive)
                {
                    var list = namedValues.Keys.Where(key => string.Equals(property.Name, key, StringComparison.OrdinalIgnoreCase)).ToList();
                    if (list.Count > 1)
                    {
                        throw new ODataException(Strings.UriParserMetadata_MultipleMatchingKeysFound(property.Name));
                    }
                    else if (list.Count == 0)
                    {
                        throw ExceptionUtil.CreateSyntaxError();
                    }

                    valueText = namedValues[list.Single()];
                }
                else if (!namedValues.TryGetValue(property.Name, out valueText))
                {
                    throw ExceptionUtil.CreateSyntaxError();
                }

                object convertedValue = convertFunc(property.Type, valueText);
                if (convertedValue == null)
                {
                    throw ExceptionUtil.CreateSyntaxError();
                }

                convertedPairs[property.Name] = convertedValue;
            }

            return(convertedPairs);
        }
예제 #9
0
 public void SyntaxErrorHelperShouldThrowNormalODataException()
 {
     Assert.IsType <ODataException>(ExceptionUtil.CreateSyntaxError());
 }
예제 #10
0
        public void SyntaxErrorHelperShouldSetMessageCorrectly()
        {
            ExceptionUtil.CreateSyntaxError().Message.Should().Be(Strings.RequestUriProcessor_SyntaxError);

            string a = Strings.General_InternalError(Microsoft.OData.Core.UriParser.InternalErrorCodes.UriQueryExpressionParser_ParseComparison);
        }
예제 #11
0
 public void SyntaxErrorHelperShouldThrowNormalODataException()
 {
     ExceptionUtil.CreateSyntaxError().GetType().Should().Be(typeof(ODataException));
 }