/// <summary> /// Finds the signature that best matches the arguments /// </summary> /// <param name="functionName">The name of the function</param> /// <param name="argumentNodes">The nodes of the arguments, can be new {null,null}.</param> /// <param name="signatures">The signatures to match against</param> /// <returns>Returns the matching signature or throws</returns> internal static FunctionSignatureWithReturnType MatchSignatureToBuiltInFunction(string functionName, SingleValueNode[] argumentNodes, FunctionSignatureWithReturnType[] signatures) { FunctionSignatureWithReturnType signature; IEdmTypeReference[] argumentTypes = argumentNodes.Select(s => s.TypeReference).ToArray(); // Handle the cases where we don't have type information (null literal, open properties) for ANY of the arguments int argumentCount = argumentTypes.Length; if (argumentTypes.All(a => a == null) && argumentCount > 0) { // we specifically want to find just the first function that matches the number of arguments, we don't care about // ambiguity here because we're already in an ambiguous case where we don't know what kind of types // those arguments are. signature = signatures.FirstOrDefault(candidateFunction => candidateFunction.ArgumentTypes.Count() == argumentCount); if (signature == null) { throw new ODataException(ODataErrorStrings.FunctionCallBinder_CannotFindASuitableOverload(functionName, argumentTypes.Count())); } else { // in this case we can't assert the return type, we can only assert that a function exists... so // we need to set the return type to null. signature = new FunctionSignatureWithReturnType(null, signature.ArgumentTypes); } } else { signature = TypePromotionUtils.FindBestFunctionSignature(signatures, argumentNodes); if (signature == null) { throw new ODataException(ODataErrorStrings.MetadataBinder_NoApplicableFunctionFound( functionName, BuiltInFunctions.BuildFunctionSignatureListDescription(functionName, signatures))); } } return(signature); }
/// <summary> /// Ensure that the segments given to us are valid select segments. /// </summary> /// <exception cref="ODataException">Throws if the list of segments doesn't match the requirements for a path in $select</exception> private void ValidatePath() { int index = 0; foreach (ODataPathSegment segment in this) { if (segment is NavigationPropertySegment) { if (index != this.Count - 1) { throw new ODataException(ODataErrorStrings.ODataSelectPath_NavPropSegmentCanOnlyBeLastSegment); } } else if (segment is OperationSegment) { if (index != this.Count - 1) { throw new ODataException(ODataErrorStrings.ODataSelectPath_OperationSegmentCanOnlyBeLastSegment); } } else if (segment is TypeSegment) { if (index == this.Count - 1) { throw new ODataException(ODataErrorStrings.ODataSelectPath_CannotEndInTypeSegment); } } else if (segment is OpenPropertySegment || segment is PropertySegment) { continue; } else { throw new ODataException(ODataErrorStrings.ODataSelectPath_InvalidSelectPathSegmentType(segment.GetType().Name)); } index++; } }
/// <summary> /// Parses typed literals. /// </summary> /// <param name="lexer">The lexer to use.</param> /// <param name="targetTypeReference">Expected type to be parsed.</param> /// <param name="targetTypeName">The EDM type name of the expected type to be parsed.</param> /// <returns>The literal token produced by building the given literal.</returns> private static LiteralToken ParseTypedLiteral(ExpressionLexer lexer, IEdmTypeReference targetTypeReference, string targetTypeName) { Debug.Assert(lexer != null, "lexer != null"); UriLiteralParsingException typeParsingException; object targetValue = DefaultUriLiteralParser.Instance.ParseUriStringToType(lexer.CurrentToken.Text, targetTypeReference, out typeParsingException); if (targetValue == null) { string message; if (typeParsingException == null) { message = ODataErrorStrings.UriQueryExpressionParser_UnrecognizedLiteral( targetTypeName, lexer.CurrentToken.Text, lexer.CurrentToken.Position, lexer.ExpressionText); throw ParseError(message); } else { message = ODataErrorStrings.UriQueryExpressionParser_UnrecognizedLiteralWithReason( targetTypeName, lexer.CurrentToken.Text, lexer.CurrentToken.Position, lexer.ExpressionText, typeParsingException.Message); throw ParseError(message, typeParsingException); } } LiteralToken result = new LiteralToken(targetValue, lexer.CurrentToken.Text); lexer.NextToken(); return(result); }
// parses $apply aggregate tranformation (.e.g. aggregate(UnitPrice with sum as TotalUnitPrice) internal AggregateToken ParseAggregate() { Debug.Assert(TokenIdentifierIs(ExpressionConstants.KeywordAggregate), "token identifier is aggregate"); lexer.NextToken(); // '(' if (this.lexer.CurrentToken.Kind != ExpressionTokenKind.OpenParen) { throw ParseError(ODataErrorStrings.UriQueryExpressionParser_OpenParenExpected(this.lexer.CurrentToken.Position, this.lexer.ExpressionText)); } this.lexer.NextToken(); // series of statements separates by commas var statements = new List <AggregateExpressionToken>(); while (true) { statements.Add(this.ParseAggregateExpression()); if (this.lexer.CurrentToken.Kind != ExpressionTokenKind.Comma) { break; } this.lexer.NextToken(); } // ")" if (this.lexer.CurrentToken.Kind != ExpressionTokenKind.CloseParen) { throw ParseError(ODataErrorStrings.UriQueryExpressionParser_CloseParenOrCommaExpected(this.lexer.CurrentToken.Position, this.lexer.ExpressionText)); } this.lexer.NextToken(); return(new AggregateToken(statements)); }
/// <summary> /// Reads an annotation's value from the annotation value notation specified on the current element. /// </summary> /// <param name="expectedTypeReference">The expected type reference of the vocabulary term from the metadata.</param> /// <param name="attributeValueNotationTypeReference">The type reference indicated by the name of the attribute used in attribute value notation. /// For example, if the attribute was called "string", this will be a reference to the string type.</param> /// <param name="attributeValueNotationAttributeName">The name of the attribute used by attribute avalue notation.</param> /// <param name="attributeValueNotationAttributeValue">The value of the attribute used by attribute value notation.</param> /// <param name="typeAttributeValue">The value of the "m:type" attribute on the annotation element.</param> /// <param name="positionedOnEmptyElement">true if the annotation element is empty, false otherwise.</param> /// <param name="model">The edm model instance.</param> /// <param name="messageReaderSettings">The message reader settings instance.</param> /// <param name="version">The payload version to read.</param> /// <returns>The primitive value represented on this element via attribute value notation.</returns> private static ODataPrimitiveValue GetValueFromAttributeValueNotation( IEdmTypeReference expectedTypeReference, IEdmPrimitiveTypeReference attributeValueNotationTypeReference, string attributeValueNotationAttributeName, string attributeValueNotationAttributeValue, string typeAttributeValue, bool positionedOnEmptyElement, IEdmModel model, ODataMessageReaderSettings messageReaderSettings, ODataVersion version) { Debug.Assert(attributeValueNotationTypeReference != null, "attributeValueNotationTypeReference != null"); if (!positionedOnEmptyElement) { // If there is content in the body of the element, throw since it's ambiguous whether we should use the value from the attribute or the element content. throw new ODataException(ODataErrorStrings.AtomInstanceAnnotation_AttributeValueNotationUsedOnNonEmptyElement(attributeValueNotationAttributeName)); } // If both m:type is present and attribute value notation is being used, they must match. // For example, if m:type is "Edm.Int32", but the "string" attribute is also present, we should throw. if (typeAttributeValue != null && !string.Equals(attributeValueNotationTypeReference.Definition.ODataFullName(), typeAttributeValue, StringComparison.Ordinal)) { throw new ODataException(ODataErrorStrings.AtomInstanceAnnotation_AttributeValueNotationUsedWithIncompatibleType(typeAttributeValue, attributeValueNotationAttributeName)); } IEdmTypeReference targetTypeReference = ReaderValidationUtils.ResolveAndValidatePrimitiveTargetType( expectedTypeReference, EdmTypeKind.Primitive, attributeValueNotationTypeReference.Definition, attributeValueNotationTypeReference.ODataFullName(), attributeValueNotationTypeReference.Definition, model, messageReaderSettings, version); return(new ODataPrimitiveValue(AtomValueUtils.ConvertStringToPrimitive(attributeValueNotationAttributeValue, targetTypeReference.AsPrimitive()))); }
/// <summary> /// Handles the start of primary expressions. /// </summary> /// <returns>The lexical token representing the expression.</returns> private QueryToken ParsePrimaryStart() { switch (this.lexer.CurrentToken.Kind) { case ExpressionTokenKind.ParameterAlias: { return(ParseParameterAlias(this.lexer)); } case ExpressionTokenKind.Identifier: { IdentifierTokenizer identifierTokenizer = new IdentifierTokenizer(this.parameters, new FunctionCallParser(this.lexer, this)); return(identifierTokenizer.ParseIdentifier(null)); } case ExpressionTokenKind.OpenParen: { return(this.ParseParenExpression()); } case ExpressionTokenKind.Star: { IdentifierTokenizer identifierTokenizer = new IdentifierTokenizer(this.parameters, new FunctionCallParser(this.lexer, this)); return(identifierTokenizer.ParseStarMemberAccess(null)); } default: { QueryToken primitiveLiteralToken = TryParseLiteral(this.lexer); if (primitiveLiteralToken == null) { throw ParseError(ODataErrorStrings.UriQueryExpressionParser_ExpressionExpected(this.lexer.CurrentToken.Position, this.lexer.ExpressionText)); } return(primitiveLiteralToken); } } }
public void InvalidDateReaderTest() { var testCases = new[] { new { Payload = "\"\"", Show = "" }, new { Payload = "\"value\"", Show = "value" }, new { Payload = "42", Show = "42" }, new { Payload = "true", Show = "True" }, new { Payload = "\"\\/Date(-0001-01-01)\\/\"", Show = "/Date(-0001-01-01)/" }, new { Payload = "\"\\/Date(-9999-12-31)\\/\"", Show = "/Date(-9999-12-31)/" }, new { Payload = "\"\\/Date(2012-04-13T02:43:10.215Z)\\/\"", Show = "/Date(2012-04-13T02:43:10.215Z)/" }, new { Payload = "\"2/26/2011\"", Show = "2/26/2011" }, new { Payload = "\"\\/Date(1298678400000)\\/\"", Show = "/Date(1298678400000)/" }, new { Payload = "\"\\/Date(1286705410000+0060)\\/\"", Show = "/Date(1286705410000+0060)/" }, new { Payload = "\"7-dui:9M7UG{*'!pu:^8LaV8a9~Pt76Fn*sP*1Tdf\"", Show = "7-dui:9M7UG{*'!pu:^8LaV8a9~Pt76Fn*sP*1Tdf" }, }; foreach (var testCase in testCases) { Action action = () => this.VerifyDateValueReader(testCase.Payload, "Edm.Date", null); action.ShouldThrow <ODataException>().WithMessage(ErrorStrings.ReaderValidationUtils_CannotConvertPrimitiveValue(testCase.Show, "Edm.Date")); } }
/// <summary> /// Read a query option from the lexer. /// </summary> /// <returns>The query option as a string.</returns> private string ReadQueryOption() { if (this.lexer.CurrentToken.Kind != ExpressionTokenKind.Equal) { throw new ODataException(ODataErrorStrings.UriSelectParser_TermIsNotValid(this.lexer.ExpressionText)); } // get the full text from the current location onward // there could be literals like 'A string literal; tricky!' in there, so we need to be careful. // Also there could be more nested (...) expressions that we ignore until we recurse enough times to get there. string expressionText = this.lexer.AdvanceThroughExpandOption(); if (this.lexer.CurrentToken.Kind == ExpressionTokenKind.SemiColon) { // Move over the ';' seperator this.lexer.NextToken(); return(expressionText); } // If there wasn't a semicolon, it MUST be the last option. We must be at ')' in this case this.lexer.ValidateToken(ExpressionTokenKind.CloseParen); return(expressionText); }
public void AnnotationOnEntryTargetingSomethingOtherThanEntryShouldThrow() { const string payload = @" <entry xmlns=""http://www.w3.org/2005/Atom"" xmlns:d=""http://docs.oasis-open.org/odata/ns/data"" xmlns:m=""http://docs.oasis-open.org/odata/ns/metadata""> <id/> <title/> <m:annotation term=""my.namespace.term"" target=""PropertyName"" m:type=""Edm.Int32"">42</m:annotation> <updated>2013-01-22T01:09:20Z</updated> <author> <name/> </author> <content type=""application/xml""> <m:properties> <d:PropertyName>PropertyValue</d:PropertyName> </m:properties> </content> </entry> "; Action testSubject = () => this.ReadEntryPayload(payload, reader => { }); testSubject.ShouldThrow <ODataException>().WithMessage(ODataErrorStrings.ODataAtomEntryAndFeedDeserializer_AnnotationWithNonDotTarget("PropertyName", "my.namespace.term")); }
/// <summary> /// Resolves a type. /// </summary> /// <param name="typeName">The type name.</param> /// <param name="readerBehavior">Reader behavior if the caller is a reader, null if no reader behavior is available.</param> /// <returns>The resolved Edm type.</returns> private ODataPayloadKind ResolveType(string typeName, ODataReaderBehavior readerBehavior) { string typeNameToResolve = EdmLibraryExtensions.GetCollectionItemTypeName(typeName) ?? typeName; bool isCollection = typeNameToResolve != typeName; EdmTypeKind typeKind; IEdmType resolvedType = MetadataUtils.ResolveTypeNameForRead(this.model, /*expectedType*/ null, typeNameToResolve, readerBehavior, out typeKind); if (resolvedType == null || resolvedType.TypeKind != EdmTypeKind.Primitive && resolvedType.TypeKind != EdmTypeKind.Enum && resolvedType.TypeKind != EdmTypeKind.Complex && resolvedType.TypeKind != EdmTypeKind.Entity && resolvedType.TypeKind != EdmTypeKind.TypeDefinition) { throw new ODataException(ODataErrorStrings.ODataJsonLightContextUriParser_InvalidEntitySetNameOrTypeName(UriUtils.UriToString(this.parseResult.ContextUri), typeName)); } if (resolvedType.TypeKind == EdmTypeKind.Entity) { this.parseResult.EdmType = resolvedType; return(isCollection ? ODataPayloadKind.Feed : ODataPayloadKind.Entry); } resolvedType = isCollection ? EdmLibraryExtensions.GetCollectionType(resolvedType.ToTypeReference(true /*nullable*/)) : resolvedType; this.parseResult.EdmType = resolvedType; return(isCollection ? ODataPayloadKind.Collection : ODataPayloadKind.Property); }
/// <summary> /// Reads an item in the collection. /// </summary> /// <param name="expectedItemType">The expected type of the item to read.</param> /// <param name="collectionValidator">The collection validator instance if no expected item type has been specified; otherwise null.</param> /// <returns>The value of the collection item that was read; this can be an ODataComplexValue, a primitive value or 'null'.</returns> /// <remarks> /// Pre-Condition: XmlNodeType.Element - The start element node of the item in the collection. /// Post-Condition: Any - The next node after the end tag of the item. /// </remarks> internal object ReadCollectionItem(IEdmTypeReference expectedItemType, CollectionWithoutExpectedTypeValidator collectionValidator) { this.XmlReader.AssertNotBuffering(); this.AssertXmlCondition(XmlNodeType.Element); // the caller should guarantee that we are reading elements in the OData namespace or the custom namespace specified through the reader settings. Debug.Assert(this.XmlReader.NamespaceEquals(this.XmlReader.ODataMetadataNamespace), "The 'element' node should be in the OData Metadata Namespace or in the user specified Metadata Namespace"); // make sure that the item is named as 'element'. if (!this.XmlReader.LocalNameEquals(this.ODataCollectionItemElementName)) { throw new ODataException(ODataErrorStrings.ODataAtomCollectionDeserializer_WrongCollectionItemElementName(this.XmlReader.LocalName, this.XmlReader.ODataNamespace)); } object item = this.ReadNonEntityValue(expectedItemType, this.duplicatePropertyNamesChecker, collectionValidator, /*validateNullValue*/ true); // read over the end tag of the element or the start tag if the element was empty. this.XmlReader.Read(); this.XmlReader.AssertNotBuffering(); return(item); }
/// <summary> /// Parses typed literals. /// </summary> /// <param name="lexer">The lexer to use.</param> /// <param name="targetTypeReference">Expected type to be parsed.</param> /// <param name="targetTypeName">The EDM type name of the expected type to be parsed.</param> /// <returns>The literal token produced by building the given literal.</returns> private static LiteralToken ParseTypedLiteral(ExpressionLexer lexer, IEdmPrimitiveTypeReference targetTypeReference, string targetTypeName) { Debug.Assert(lexer != null, "lexer != null"); object targetValue; string reason; if (!UriPrimitiveTypeParser.TryUriStringToPrimitive(lexer.CurrentToken.Text, targetTypeReference, out targetValue, out reason)) { string message; if (reason == null) { message = ODataErrorStrings.UriQueryExpressionParser_UnrecognizedLiteral( targetTypeName, lexer.CurrentToken.Text, lexer.CurrentToken.Position, lexer.ExpressionText); } else { message = ODataErrorStrings.UriQueryExpressionParser_UnrecognizedLiteralWithReason( targetTypeName, lexer.CurrentToken.Text, lexer.CurrentToken.Position, lexer.ExpressionText, reason); } throw ParseError(message); } LiteralToken result = new LiteralToken(targetValue, lexer.CurrentToken.Text); lexer.NextToken(); return(result); }
/// <summary> /// Writes a primitive value. /// </summary> /// <param name="value">The value to write.</param> /// <param name="collectionValidator">The collection validator instance.</param> /// <param name="expectedTypeReference">The expected type of the primitive value.</param> /// <param name="typeNameAnnotation">The optional type name annotation provided by the user on the OM for this primitive value. The annotation value will override whatever type name is being written.</param> internal void WritePrimitiveValue( object value, CollectionWithoutExpectedTypeValidator collectionValidator, IEdmTypeReference expectedTypeReference, SerializationTypeNameAnnotation typeNameAnnotation) { Debug.Assert(value != null, "value != null"); IEdmPrimitiveTypeReference primitiveTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(value.GetType()); if (primitiveTypeReference == null) { throw new ODataException(ODataErrorStrings.ValidationUtils_UnsupportedPrimitiveType(value.GetType().FullName)); } if (collectionValidator != null) { collectionValidator.ValidateCollectionItem(primitiveTypeReference.FullName(), EdmTypeKind.Primitive); } if (expectedTypeReference != null) { ValidationUtils.ValidateIsExpectedPrimitiveType(value, primitiveTypeReference, expectedTypeReference); } string collectionItemTypeName; string typeName = this.AtomOutputContext.TypeNameOracle.GetValueTypeNameForWriting(value, primitiveTypeReference, typeNameAnnotation, collectionValidator, out collectionItemTypeName); Debug.Assert(collectionItemTypeName == null, "collectionItemTypeName == null"); if (typeName != null && typeName != EdmConstants.EdmStringTypeName) { this.WritePropertyTypeAttribute(typeName); } AtomValueUtils.WritePrimitiveValue(this.XmlWriter, value); }
/// <summary> /// Reads the start element of a collection. /// </summary> /// <param name="isCollectionElementEmpty">true, if the collection element is empty; false otherwise.</param> /// <returns>An <see cref="ODataCollectionStart"/> representing the collection-level information. Currently this only contains /// the name of the collection.</returns> /// <remarks> /// Pre-Condition: XmlNodeType.Element - The start element of the collection. /// Post-Condition: Any - The next node after the start element node of the collection or the /// empty collection element node. /// </remarks> internal ODataCollectionStart ReadCollectionStart(out bool isCollectionElementEmpty) { this.XmlReader.AssertNotBuffering(); this.AssertXmlCondition(XmlNodeType.Element); if (!this.XmlReader.NamespaceEquals(this.XmlReader.ODataMetadataNamespace)) { throw new ODataException(ODataErrorStrings.ODataAtomCollectionDeserializer_TopLevelCollectionElementWrongNamespace(this.XmlReader.NamespaceURI, this.XmlReader.ODataMetadataNamespace)); } while (this.XmlReader.MoveToNextAttribute()) { if (this.XmlReader.NamespaceEquals(this.XmlReader.ODataMetadataNamespace) && (this.XmlReader.LocalNameEquals(this.AtomTypeAttributeName) || (this.XmlReader.LocalNameEquals(this.ODataNullAttributeName)))) { // make sure that m:type or m:null attributes are not present in the root element of the collection. throw new ODataException(ODataErrorStrings.ODataAtomCollectionDeserializer_TypeOrNullAttributeNotAllowed); } } // ignore all other attributes. this.XmlReader.MoveToElement(); ODataCollectionStart collectionStart = new ODataCollectionStart(); isCollectionElementEmpty = this.XmlReader.IsEmptyElement; if (!isCollectionElementEmpty) { // if the collection start element is not an empty element than read over the // start element. this.XmlReader.Read(); } return(collectionStart); }
/// <summary> /// Build a segment from a token. /// </summary> /// <param name="tokenIn">the token to bind</param> /// <param name="model">The model.</param> /// <param name="edmType">the type of the current scope based on type segments.</param> /// <param name="resolver">Resolver for uri parser.</param> /// <returns>The segment created from the token.</returns> public static ODataPathSegment ConvertNonTypeTokenToSegment(PathSegmentToken tokenIn, IEdmModel model, IEdmStructuredType edmType, ODataUriResolver resolver = null) { if (resolver == null) { resolver = ODataUriResolver.Default; } ODataPathSegment nextSegment; if (TryBindAsDeclaredProperty(tokenIn, edmType, resolver, out nextSegment)) { return(nextSegment); } // Operations must be container-qualified, and because the token type indicates it was not a .-seperated identifier, we should not try to look up operations. if (tokenIn.IsNamespaceOrContainerQualified()) { if (TryBindAsOperation(tokenIn, model, edmType, out nextSegment)) { return(nextSegment); } // If an action or function is requested in a selectItem using a qualifiedActionName or a qualifiedFunctionName // and that operation cannot be bound to the entities requested, the service MUST ignore the selectItem. if (!edmType.IsOpen) { return(null); } } if (edmType.IsOpen) { return(new OpenPropertySegment(tokenIn.Identifier)); } throw new ODataException(ODataErrorStrings.MetadataBinder_PropertyNotDeclared(edmType.ODataFullName(), tokenIn.Identifier)); }
/// <summary> /// Binds key values to a key lookup on a collection. /// </summary> /// <param name="collectionNode">Already bound collection node.</param> /// <param name="namedValues">The named value tokens to bind.</param> /// <param name="model">The model to be used.</param> /// <returns>The bound key lookup.</returns> internal QueryNode BindKeyValues(EntityCollectionNode collectionNode, IEnumerable <NamedValue> namedValues, IEdmModel model) { Debug.Assert(namedValues != null, "namedValues != null"); Debug.Assert(collectionNode != null, "CollectionNode != null"); Debug.Assert(model != null, "model != null"); IEdmEntityTypeReference collectionItemType = collectionNode.EntityItemType; IEdmEntityType collectionItemEntityType = collectionItemType.EntityDefinition(); QueryNode keyLookupNode; if (TryBindToDeclaredKey(collectionNode, namedValues, model, collectionItemEntityType, out keyLookupNode)) { return(keyLookupNode); } else if (TryBindToDeclaredAlternateKey(collectionNode, namedValues, model, collectionItemEntityType, out keyLookupNode)) { return(keyLookupNode); } else { throw new ODataException(ODataErrorStrings.MetadataBinder_NotAllKeyPropertiesSpecifiedInKeyValues(collectionNode.ItemType.FullName())); } }
/// <summary> /// Parses the primary expressions. /// </summary> /// <returns>The lexical token representing the expression.</returns> private QueryToken ParsePrimary() { QueryToken expr = null; this.RecurseEnter(); switch (this.lexer.CurrentToken.Kind) { case ExpressionTokenKind.OpenParen: expr = this.ParseParenExpression(); break; case ExpressionTokenKind.StringLiteral: expr = new StringLiteralToken(this.lexer.CurrentToken.Text); this.lexer.NextToken(); break; default: throw new ODataException(ODataErrorStrings.UriQueryExpressionParser_ExpressionExpected(this.lexer.CurrentToken.Position, this.lexer.ExpressionText)); } this.RecurseLeave(); return(expr); }
/// <summary> /// Compute the result type of a binary operator based on the type of its operands and the operator kind. /// </summary> /// <param name="left">The type reference on the left hand.</param> /// <param name="right">The type reference on the right hand.</param> /// <param name="operatorKind">The kind of operator.</param> /// <returns>The result type reference of the binary operator.</returns> internal static IEdmPrimitiveTypeReference GetBinaryOperatorResultType(IEdmPrimitiveTypeReference left, IEdmPrimitiveTypeReference right, BinaryOperatorKind operatorKind) { Debug.Assert(left != null, "type != null"); Debug.Assert(right != null, "type != null"); EdmPrimitiveTypeKind kind; if (additionalMap.TryGetValue(new Tuple <BinaryOperatorKind, EdmPrimitiveTypeKind, EdmPrimitiveTypeKind>(operatorKind, left.PrimitiveKind(), right.PrimitiveKind()), out kind)) { return(EdmCoreModel.Instance.GetPrimitive(kind, left.IsNullable)); } switch (operatorKind) { case BinaryOperatorKind.Or: // fall through case BinaryOperatorKind.And: // fall through case BinaryOperatorKind.Equal: // fall through case BinaryOperatorKind.NotEqual: // fall through case BinaryOperatorKind.GreaterThan: // fall through case BinaryOperatorKind.GreaterThanOrEqual: // fall through case BinaryOperatorKind.LessThan: // fall through case BinaryOperatorKind.LessThanOrEqual: case BinaryOperatorKind.Has: return(EdmCoreModel.Instance.GetBoolean(left.IsNullable)); case BinaryOperatorKind.Add: // fall through case BinaryOperatorKind.Subtract: // fall through case BinaryOperatorKind.Multiply: // fall through case BinaryOperatorKind.Divide: // fall through case BinaryOperatorKind.Modulo: return(left); default: throw new ODataException(ODataErrorStrings.General_InternalError(InternalErrorCodes.QueryNodeUtils_BinaryOperatorResultType_UnreachableCodepath)); } }
private static bool TryBindAsDeclaredProperty(PathSegmentToken tokenIn, IEdmStructuredType edmType, ODataUriResolver resolver, out ODataPathSegment segment) { IEdmProperty prop = resolver.ResolveProperty(edmType, tokenIn.Identifier); if (prop == null) { segment = null; return(false); } if (prop.PropertyKind == EdmPropertyKind.Structural) { segment = new PropertySegment((IEdmStructuralProperty)prop); return(true); } if (prop.PropertyKind == EdmPropertyKind.Navigation) { segment = new NavigationPropertySegment((IEdmNavigationProperty)prop, null /*TODO set*/); return(true); } throw new ODataException(ODataErrorStrings.SelectExpandBinder_UnknownPropertyType(prop.Name)); }
/// <summary> /// Verifies that CreateEntryReader or CreateFeedReader or CreateDeltaReader can be called. /// </summary> /// <param name="navigationSource">The navigation source we are going to read entities for.</param> /// <param name="entityType">The expected entity type for the entry/entries to be read.</param> private void VerifyCanCreateODataReader(IEdmNavigationSource navigationSource, IEdmEntityType entityType) { Debug.Assert(navigationSource == null || entityType != null, "If an navigation source is specified, the entity type must be specified as well."); // We require metadata information for reading requests. if (!this.ReadingResponse) { this.VerifyUserModel(); if (navigationSource == null) { throw new ODataException(ODataErrorStrings.ODataJsonLightInputContext_NoEntitySetForRequest); } } // We only check that the base type of the entity set is assignable from the specified entity type. // If no entity set/entity type is specified in the API, we will read it from the context URI. IEdmEntityType entitySetElementType = this.EdmTypeResolver.GetElementType(navigationSource); if (navigationSource != null && entityType != null && !entityType.IsOrInheritsFrom(entitySetElementType)) { throw new ODataException(ODataErrorStrings.ODataJsonLightInputContext_EntityTypeMustBeCompatibleWithEntitySetBaseType(entityType.FullName(), entitySetElementType.FullName(), navigationSource.FullNavigationSourceName())); } }
public BatchReferenceSegment(string contentId, IEdmType edmType, IEdmEntitySetBase entitySet) { ExceptionUtils.CheckArgumentNotNull(edmType, "resultingType"); ExceptionUtils.CheckArgumentNotNull(contentId, "contentId"); if (!ODataPathParser.ContentIdRegex.IsMatch(contentId)) { throw new ODataException(ODataErrorStrings.BatchReferenceSegment_InvalidContentID(contentId)); } this.edmType = edmType; this.entitySet = entitySet; this.contentId = contentId; this.Identifier = this.ContentId; this.TargetEdmType = edmType; this.TargetEdmNavigationSource = this.EntitySet; this.SingleResult = true; this.TargetKind = RequestTargetKind.Resource; if (entitySet != null) { UriParserErrorHelper.ThrowIfTypesUnrelated(edmType, entitySet.EntityType(), "BatchReferenceSegments"); } }
/// <summary> /// Read an entity reference link. /// </summary> /// <param name="duplicatePropertyNamesChecker">The duplicate property names checker to check for duplicate properties and /// duplicate annotations; this is a separate instance per entity reference link.</param> /// <param name="topLevel">true if we are reading a singleton entity reference link at the top level; false if we are reading /// an entity reference link as part of a collection of entity reference links.</param> /// <returns>An instance of <see cref="ODataEntityReferenceLink"/> which was read.</returns> /// <remarks> /// Pre-Condition: StartObject when the entity reference link is part of a collection /// Property the first property in the entity reference link (for a top-level link) /// EndObject the end object node of an entity reference link (for a top-level link) /// Post-Condition: EndInput for a top-level object /// EndArray for the last link in a collection of links /// Any for the first node of the next link in a collection of links /// </remarks> private ODataEntityReferenceLink ReadSingleEntityReferenceLink(DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, bool topLevel) { this.JsonReader.AssertNotBuffering(); if (!topLevel) { if (this.JsonReader.NodeType != JsonNodeType.StartObject) { // entity reference link has to be an object throw new ODataException(ODataErrorStrings.ODataJsonLightEntityReferenceLinkDeserializer_EntityReferenceLinkMustBeObjectValue(this.JsonReader.NodeType)); } this.JsonReader.ReadStartObject(); } this.AssertJsonCondition(JsonNodeType.Property, JsonNodeType.EndObject); ODataEntityReferenceLink[] entityReferenceLink = { null }; // Entity reference links use instance annotations. Fail if we find a property annotation. Func <string, object> propertyAnnotationValueReader = annotationName => { throw new ODataException(ODataErrorStrings.ODataJsonLightEntityReferenceLinkDeserializer_PropertyAnnotationForEntityReferenceLink(annotationName)); }; while (this.JsonReader.NodeType == JsonNodeType.Property) { this.ProcessProperty( duplicatePropertyNamesChecker, propertyAnnotationValueReader, (propertyParsingResult, propertyName) => { switch (propertyParsingResult) { case PropertyParsingResult.ODataInstanceAnnotation: if (string.CompareOrdinal(ODataAnnotationNames.ODataId, propertyName) != 0) { throw new ODataException(ODataErrorStrings.ODataJsonLightEntityReferenceLinkDeserializer_InvalidPropertyInEntityReferenceLink(propertyName, ODataAnnotationNames.ODataId)); } else if (entityReferenceLink[0] != null) { throw new ODataException(ODataErrorStrings.ODataJsonLightEntityReferenceLinkDeserializer_MultipleUriPropertiesInEntityReferenceLink(ODataAnnotationNames.ODataId)); } // read the value of the 'odata.id' annotation string urlString = this.JsonReader.ReadStringValue(ODataAnnotationNames.ODataId); if (urlString == null) { throw new ODataException(ODataErrorStrings.ODataJsonLightEntityReferenceLinkDeserializer_EntityReferenceLinkUrlCannotBeNull(ODataAnnotationNames.ODataId)); } entityReferenceLink[0] = new ODataEntityReferenceLink { Url = this.ProcessUriFromPayload(urlString) }; ReaderValidationUtils.ValidateEntityReferenceLink(entityReferenceLink[0]); break; case PropertyParsingResult.CustomInstanceAnnotation: this.JsonReader.SkipValue(); break; case PropertyParsingResult.PropertyWithValue: case PropertyParsingResult.PropertyWithoutValue: // entity reference link is denoted by odata.id annotation throw new ODataException(ODataErrorStrings.ODataJsonLightEntityReferenceLinkDeserializer_InvalidAnnotationInEntityReferenceLink(propertyName)); case PropertyParsingResult.EndOfObject: break; case PropertyParsingResult.MetadataReferenceProperty: throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_UnexpectedMetadataReferenceProperty(propertyName)); default: throw new ODataException(ODataErrorStrings.General_InternalError(InternalErrorCodes.ODataJsonLightEntityReferenceLinkDeserializer_ReadSingleEntityReferenceLink)); } }); } if (entityReferenceLink[0] == null) { throw new ODataException(ODataErrorStrings.ODataJsonLightEntityReferenceLinkDeserializer_MissingEntityReferenceLinkProperty(ODataAnnotationNames.ODataId)); } // end of the entity reference link object this.JsonReader.ReadEndObject(); this.JsonReader.AssertNotBuffering(); return(entityReferenceLink[0]); }
// parses $apply groupby tranformation (.e.g. groupby(ProductID, CategoryId, aggregate(UnitPrice with sum as TotalUnitPrice)) internal GroupByToken ParseGroupBy() { Debug.Assert(TokenIdentifierIs(ExpressionConstants.KeywordGroupBy), "token identifier is groupby"); lexer.NextToken(); // '(' if (this.lexer.CurrentToken.Kind != ExpressionTokenKind.OpenParen) { throw ParseError(ODataErrorStrings.UriQueryExpressionParser_OpenParenExpected(this.lexer.CurrentToken.Position, this.lexer.ExpressionText)); } this.lexer.NextToken(); // '(' if (this.lexer.CurrentToken.Kind != ExpressionTokenKind.OpenParen) { throw ParseError(ODataErrorStrings.UriQueryExpressionParser_OpenParenExpected(this.lexer.CurrentToken.Position, this.lexer.ExpressionText)); } this.lexer.NextToken(); // properties var properties = new List <EndPathToken>(); while (true) { var expression = this.ParsePrimary() as EndPathToken; if (expression == null) { throw ParseError(ODataErrorStrings.UriQueryExpressionParser_ExpressionExpected(this.lexer.CurrentToken.Position, this.lexer.ExpressionText)); } properties.Add(expression); if (this.lexer.CurrentToken.Kind != ExpressionTokenKind.Comma) { break; } this.lexer.NextToken(); } // ")" if (this.lexer.CurrentToken.Kind != ExpressionTokenKind.CloseParen) { throw ParseError(ODataErrorStrings.UriQueryExpressionParser_CloseParenOrOperatorExpected(this.lexer.CurrentToken.Position, this.lexer.ExpressionText)); } this.lexer.NextToken(); // optional child transformation ApplyTransformationToken transformationToken = null; // "," (comma) if (this.lexer.CurrentToken.Kind == ExpressionTokenKind.Comma) { this.lexer.NextToken(); if (TokenIdentifierIs(ExpressionConstants.KeywordAggregate)) { transformationToken = this.ParseAggregate(); } else { throw ParseError(ODataErrorStrings.UriQueryExpressionParser_KeywordOrIdentifierExpected(ExpressionConstants.KeywordAggregate, this.lexer.CurrentToken.Position, this.lexer.ExpressionText)); } } // ")" if (this.lexer.CurrentToken.Kind != ExpressionTokenKind.CloseParen) { throw ParseError(ODataErrorStrings.UriQueryExpressionParser_CloseParenOrCommaExpected(this.lexer.CurrentToken.Position, this.lexer.ExpressionText)); } this.lexer.NextToken(); return(new GroupByToken(properties, transformationToken)); }
public void GetOrCreateReadOnlyEnumerableShouldThrowForListSource() { Action test = () => (new List <int>()).GetOrCreateReadOnlyEnumerable("Integers"); test.ShouldThrow <ODataException>().WithMessage(ErrorStrings.ReaderUtils_EnumerableModified("Integers")); }
public void ConcatToReadOnlyEnumerableShouldThrowForListSource() { Action test = () => new List <ODataProperty>().ConcatToReadOnlyEnumerable("Properties", new ODataProperty()); test.ShouldThrow <ODataException>().WithMessage(ErrorStrings.ReaderUtils_EnumerableModified("Properties")); }
/// <summary> /// Binds a <see cref="InnerPathToken"/>. /// This includes more than just navigations - it includes complex property access and primitive collections. /// </summary> /// <param name="segmentToken">The segment token to bind.</param> /// <returns>The bound node.</returns> internal QueryNode BindInnerPathSegment(InnerPathToken segmentToken) { FunctionCallBinder functionCallBinder = new FunctionCallBinder(this.bindMethod, state); // First we get the parent node QueryNode parent = this.DetermineParentNode(segmentToken, state); Debug.Assert(parent != null, "parent should never be null"); SingleValueNode singleValueParent = parent as SingleValueNode; if (singleValueParent == null) { QueryNode boundFunction; if (functionCallBinder.TryBindInnerPathAsFunctionCall(segmentToken, parent, out boundFunction)) { return(boundFunction); } throw new ODataException(ODataErrorStrings.MetadataBinder_PropertyAccessSourceNotSingleValue(segmentToken.Identifier)); } // Using the parent and name of this token, we try to get the IEdmProperty it represents IEdmProperty property = BindProperty(singleValueParent.TypeReference, segmentToken.Identifier, this.Resolver); if (property == null) { QueryNode boundFunction; if (functionCallBinder.TryBindInnerPathAsFunctionCall(segmentToken, parent, out boundFunction)) { return(boundFunction); } if (singleValueParent.TypeReference != null && !singleValueParent.TypeReference.Definition.IsOpenType()) { throw new ODataException( ODataErrorStrings.MetadataBinder_PropertyNotDeclared( parent.GetEdmTypeReference().FullName(), segmentToken.Identifier)); } return(new SingleValueOpenPropertyAccessNode(singleValueParent, segmentToken.Identifier)); } if (property.Type.IsODataComplexTypeKind()) { return(new SingleValuePropertyAccessNode(singleValueParent, property)); } // Note - this means nonentity collection (primitive or complex) if (property.Type.IsNonEntityCollectionType()) { return(new CollectionPropertyAccessNode(singleValueParent, property)); } IEdmNavigationProperty navigationProperty = property as IEdmNavigationProperty; if (navigationProperty == null) { throw new ODataException(ODataErrorStrings.MetadataBinder_IllegalSegmentType(property.Name)); } SingleEntityNode parentEntity = EnsureParentIsEntityForNavProp(singleValueParent); return(GetNavigationNode(navigationProperty, parentEntity, segmentToken.NamedValues, state, new KeyBinder(this.bindMethod))); }
internal static object ConvertValue( object value, IEdmPrimitiveTypeReference primitiveTypeReference, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, bool validateNullValue, string propertyName) { Debug.Assert(primitiveTypeReference != null, "primitiveTypeReference != null"); if (value == null) { // Only primitive type references are validated. Core model is sufficient. ReaderValidationUtils.ValidateNullValue( EdmCoreModel.Instance, primitiveTypeReference, messageReaderSettings, validateNullValue, version, propertyName); return(null); } try { Type targetType = EdmLibraryExtensions.GetPrimitiveClrType(primitiveTypeReference.PrimitiveDefinition(), false); string stringValue = value as string; if (stringValue != null) { return(ConvertStringValue(stringValue, targetType)); } else if (value is Int32) { return(ConvertInt32Value((int)value, targetType, primitiveTypeReference)); } else if (value is Decimal) { Decimal decimalValue = (Decimal)value; if (targetType == typeof(Int64)) { return(Convert.ToInt64(decimalValue)); } if (targetType == typeof(Double)) { return(Convert.ToDouble(decimalValue)); } if (targetType == typeof(Single)) { return(Convert.ToSingle(decimalValue)); } if (targetType != typeof(Decimal)) { throw new ODataException(ODataErrorStrings.ODataJsonReaderUtils_CannotConvertDecimal(primitiveTypeReference.ODataFullName())); } } else if (value is Double) { Double doubleValue = (Double)value; if (targetType == typeof(Single)) { return(Convert.ToSingle(doubleValue)); } if (targetType != typeof(Double)) { throw new ODataException(ODataErrorStrings.ODataJsonReaderUtils_CannotConvertDouble(primitiveTypeReference.ODataFullName())); } } else if (value is bool) { if (targetType != typeof(bool)) { throw new ODataException(ODataErrorStrings.ODataJsonReaderUtils_CannotConvertBoolean(primitiveTypeReference.ODataFullName())); } } else if (value is DateTime) { if (targetType != typeof(DateTime)) { throw new ODataException(ODataErrorStrings.ODataJsonReaderUtils_CannotConvertDateTime(primitiveTypeReference.ODataFullName())); } } else if (value is DateTimeOffset) { if (targetType != typeof(DateTimeOffset)) { throw new ODataException(ODataErrorStrings.ODataJsonReaderUtils_CannotConvertDateTimeOffset(primitiveTypeReference.ODataFullName())); } } } catch (Exception e) { if (!ExceptionUtils.IsCatchableExceptionType(e)) { throw; } throw ReaderValidationUtils.GetPrimitiveTypeConversionException(primitiveTypeReference, e, value.ToString()); } // otherwise just return the value without doing any conversion return(value); }
/// <summary> /// Generate an expand item (and a select item for the implicit nav prop if necessary) based on an ExpandTermToken /// </summary> /// <param name="tokenIn">the expandTerm token to visit</param> /// <returns>the expand item for this expand term token.</returns> private SelectItem GenerateExpandItem(ExpandTermToken tokenIn) { ExceptionUtils.CheckArgumentNotNull(tokenIn, "tokenIn"); // ensure that we're always dealing with proper V4 syntax if (tokenIn.PathToNavProp.NextToken != null && !tokenIn.PathToNavProp.IsNamespaceOrContainerQualified()) { if (tokenIn.PathToNavProp.NextToken.Identifier != UriQueryConstants.RefSegment || tokenIn.PathToNavProp.NextToken.NextToken != null) { throw new ODataException(ODataErrorStrings.ExpandItemBinder_TraversingMultipleNavPropsInTheSamePath); } } PathSegmentToken currentToken = tokenIn.PathToNavProp; IEdmStructuredType currentLevelEntityType = this.EdmType; List <ODataPathSegment> pathSoFar = new List <ODataPathSegment>(); PathSegmentToken firstNonTypeToken = currentToken; if (currentToken.IsNamespaceOrContainerQualified()) { pathSoFar.AddRange(SelectExpandPathBinder.FollowTypeSegments(currentToken, this.Model, this.Settings.SelectExpandLimit, this.configuration.Resolver, ref currentLevelEntityType, out firstNonTypeToken)); } IEdmProperty edmProperty = this.configuration.Resolver.ResolveProperty(currentLevelEntityType, firstNonTypeToken.Identifier); if (edmProperty == null) { throw new ODataException(ODataErrorStrings.MetadataBinder_PropertyNotDeclared(currentLevelEntityType.FullTypeName(), currentToken.Identifier)); } IEdmNavigationProperty currentNavProp = edmProperty as IEdmNavigationProperty; if (currentNavProp == null) { throw new ODataException(ODataErrorStrings.ExpandItemBinder_PropertyIsNotANavigationProperty(currentToken.Identifier, currentLevelEntityType.FullTypeName())); } bool isRef = false; if (firstNonTypeToken.NextToken != null) { // lastly... make sure that, since we're on a NavProp, that the next token isn't null. if (firstNonTypeToken.NextToken.Identifier == UriQueryConstants.RefSegment) { isRef = true; } else { throw new ODataException(ODataErrorStrings.ExpandItemBinder_TraversingMultipleNavPropsInTheSamePath); } } pathSoFar.Add(new NavigationPropertySegment(currentNavProp, /*entitySet*/ null)); ODataExpandPath pathToNavProp = new ODataExpandPath(pathSoFar); IEdmNavigationSource targetNavigationSource = null; if (this.NavigationSource != null) { targetNavigationSource = this.NavigationSource.FindNavigationTarget(currentNavProp); } // call MetadataBinder to build the filter clause FilterClause filterOption = null; if (tokenIn.FilterOption != null) { MetadataBinder binder = this.BuildNewMetadataBinder(targetNavigationSource); FilterBinder filterBinder = new FilterBinder(binder.Bind, binder.BindingState); filterOption = filterBinder.BindFilter(tokenIn.FilterOption); } // call MetadataBinder again to build the orderby clause OrderByClause orderbyOption = null; if (tokenIn.OrderByOptions != null) { MetadataBinder binder = this.BuildNewMetadataBinder(targetNavigationSource); OrderByBinder orderByBinder = new OrderByBinder(binder.Bind); orderbyOption = orderByBinder.BindOrderBy(binder.BindingState, tokenIn.OrderByOptions); } SearchClause searchOption = null; if (tokenIn.SearchOption != null) { MetadataBinder binder = this.BuildNewMetadataBinder(targetNavigationSource); SearchBinder searchBinder = new SearchBinder(binder.Bind); searchOption = searchBinder.BindSearch(tokenIn.SearchOption); } if (isRef) { return(new ExpandedReferenceSelectItem(pathToNavProp, targetNavigationSource, filterOption, orderbyOption, tokenIn.TopOption, tokenIn.SkipOption, tokenIn.CountQueryOption, searchOption)); } SelectExpandClause subSelectExpand; if (tokenIn.ExpandOption != null) { subSelectExpand = this.GenerateSubExpand(currentNavProp, tokenIn); } else { subSelectExpand = BuildDefaultSubExpand(); } subSelectExpand = this.DecorateExpandWithSelect(subSelectExpand, currentNavProp, tokenIn.SelectOption); LevelsClause levelsOption = this.ParseLevels(tokenIn.LevelsOption, currentLevelEntityType, currentNavProp); return(new ExpandedNavigationSelectItem(pathToNavProp, targetNavigationSource, subSelectExpand, filterOption, orderbyOption, tokenIn.TopOption, tokenIn.SkipOption, tokenIn.CountQueryOption, searchOption, levelsOption)); }
public void DeltaLinkComesAfterInnerFeedShouldThrow() { foreach (bool isResponse in new[] { true, false }) { const string entryText = @" ""NavProp"" : [], ""*****@*****.**"" : ""http://deltaLink"""; var entryReader = GetEntryReader(entryText, isResponse); entryReader.Read(); entryReader.State.Should().Be(ODataReaderState.EntryStart); entryReader.Read(); entryReader.State.Should().Be(ODataReaderState.NavigationLinkStart); entryReader.Read(); entryReader.State.Should().Be(ODataReaderState.FeedStart); entryReader.Item.As <ODataFeed>().NextPageLink.Should().Be(null); Action test = () => entryReader.Read(); string expectedErrorMsg = isResponse ? ErrorStrings.ODataJsonLightEntryAndFeedDeserializer_UnexpectedPropertyAnnotationAfterExpandedFeed("odata.deltaLink", "NavProp") : ErrorStrings.ODataJsonLightPropertyAndValueDeserializer_UnexpectedPropertyAnnotation("NavProp", "odata.deltaLink"); test.ShouldThrow <ODataException>().WithMessage(expectedErrorMsg); } }
internal static bool TryUriStringToPrimitive(string text, IEdmTypeReference targetType, out object targetValue, out string reason) { Debug.Assert(text != null, "text != null"); Debug.Assert(targetType != null, "targetType != null"); reason = null; if (targetType.IsNullable) { if (text == ExpressionConstants.KeywordNull) { targetValue = null; return(true); } } IEdmPrimitiveTypeReference primitiveTargetType = targetType.AsPrimitiveOrNull(); if (primitiveTargetType == null) { targetValue = null; return(false); } EdmPrimitiveTypeKind targetTypeKind = primitiveTargetType.PrimitiveKind(); byte[] byteArrayValue; bool binaryResult = TryUriStringToByteArray(text, out byteArrayValue); if (targetTypeKind == EdmPrimitiveTypeKind.Binary) { targetValue = (object)byteArrayValue; return(binaryResult); } else if (binaryResult) { string keyValue = Encoding.UTF8.GetString(byteArrayValue, 0, byteArrayValue.Length); return(TryUriStringToPrimitive(keyValue, targetType, out targetValue)); } else if (targetTypeKind == EdmPrimitiveTypeKind.Guid) { Guid guidValue; bool result = UriUtils.TryUriStringToGuid(text, out guidValue); targetValue = guidValue; return(result); } else if (targetTypeKind == EdmPrimitiveTypeKind.DateTimeOffset) { DateTimeOffset dateTimeOffsetValue; bool result = UriUtils.TryUriStringToDateTimeOffset(text, out dateTimeOffsetValue); targetValue = dateTimeOffsetValue; return(result); } else if (targetTypeKind == EdmPrimitiveTypeKind.Duration) { TimeSpan timespanValue; bool result = TryUriStringToDuration(text, out timespanValue); targetValue = timespanValue; return(result); } else if (targetTypeKind == EdmPrimitiveTypeKind.Geography) { Geography geographyValue; bool result = TryUriStringToGeography(text, out geographyValue, out reason); targetValue = geographyValue; return(result); } else if (targetTypeKind == EdmPrimitiveTypeKind.Geometry) { Geometry geometryValue; bool result = TryUriStringToGeometry(text, out geometryValue, out reason); targetValue = geometryValue; return(result); } bool quoted = targetTypeKind == EdmPrimitiveTypeKind.String; if (quoted != IsUriValueQuoted(text)) { targetValue = null; return(false); } if (quoted) { text = RemoveQuotes(text); } try { switch (targetTypeKind) { case EdmPrimitiveTypeKind.String: targetValue = text; break; case EdmPrimitiveTypeKind.Boolean: targetValue = XmlConvert.ToBoolean(text); break; case EdmPrimitiveTypeKind.Byte: targetValue = XmlConvert.ToByte(text); break; case EdmPrimitiveTypeKind.SByte: targetValue = XmlConvert.ToSByte(text); break; case EdmPrimitiveTypeKind.Int16: targetValue = XmlConvert.ToInt16(text); break; case EdmPrimitiveTypeKind.Int32: targetValue = XmlConvert.ToInt32(text); break; case EdmPrimitiveTypeKind.Int64: TryRemoveLiteralSuffix(ExpressionConstants.LiteralSuffixInt64, ref text); targetValue = XmlConvert.ToInt64(text); break; case EdmPrimitiveTypeKind.Single: TryRemoveLiteralSuffix(ExpressionConstants.LiteralSuffixSingle, ref text); targetValue = XmlConvert.ToSingle(text); break; case EdmPrimitiveTypeKind.Double: TryRemoveLiteralSuffix(ExpressionConstants.LiteralSuffixDouble, ref text); targetValue = XmlConvert.ToDouble(text); break; case EdmPrimitiveTypeKind.Decimal: TryRemoveLiteralSuffix(ExpressionConstants.LiteralSuffixDecimal, ref text); try { targetValue = XmlConvert.ToDecimal(text); } catch (FormatException) { // we need to support exponential format for decimals since we used to support them in V1 decimal result; if (Decimal.TryParse(text, NumberStyles.Float, NumberFormatInfo.InvariantInfo, out result)) { targetValue = result; } else { targetValue = default(Decimal); return(false); } } break; default: throw new ODataException(ODataErrorStrings.General_InternalError(InternalErrorCodes.UriPrimitiveTypeParser_TryUriStringToPrimitive)); } return(true); } catch (FormatException) { targetValue = null; return(false); } catch (OverflowException) { targetValue = null; return(false); } }