/// <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); }
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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
public void SyntaxErrorHelperShouldThrowNormalODataException() { Assert.IsType <ODataException>(ExceptionUtil.CreateSyntaxError()); }
public void SyntaxErrorHelperShouldSetMessageCorrectly() { ExceptionUtil.CreateSyntaxError().Message.Should().Be(Strings.RequestUriProcessor_SyntaxError); string a = Strings.General_InternalError(Microsoft.OData.Core.UriParser.InternalErrorCodes.UriQueryExpressionParser_ParseComparison); }
public void SyntaxErrorHelperShouldThrowNormalODataException() { ExceptionUtil.CreateSyntaxError().GetType().Should().Be(typeof(ODataException)); }