public void CsdlUnnamedTypeDefinitionToStringTest() { const string csdl = @"<?xml version=""1.0"" encoding=""utf-16""?> <Schema Namespace=""Namespace"" Alias=""Alias"" xmlns=""http://docs.oasis-open.org/odata/ns/edm""> <EntityType Name=""AstonishingEntity""> <Key> <PropertyRef Name=""Id"" /> </Key> <Property Name=""Id"" Type=""Int32"" Nullable=""false"" /> </EntityType> <Function Name=""Function1""><ReturnType Type=""Edm.Int32""/> <Parameter Name=""P1"" Type=""Collection(Edm.Int32)"" /> <Parameter Name=""P2"" Type=""Ref(Namespace.AstonishingEntity)"" /> </Function> </Schema>"; IEdmModel model; IEnumerable <EdmError> errors; bool parsed = CsdlReader.TryParse(new XmlReader[] { XmlReader.Create(new StringReader(csdl)) }, out model, out errors); Assert.IsTrue(parsed, "parsed"); Assert.IsTrue(errors.Count() == 0, "No errors"); IEdmOperation operation = (IEdmOperation)(model.FindOperations("Namespace.Function1")).First(); IEdmCollectionType collection = (IEdmCollectionType)operation.FindParameter("P1").Type.Definition; IEdmEntityReferenceType entityRef = (IEdmEntityReferenceType)operation.FindParameter("P2").Type.Definition; Assert.AreEqual("Collection([Edm.Int32 Nullable=True])", collection.ToString(), "To string correct"); Assert.AreEqual("EntityReference(Namespace.AstonishingEntity)", entityRef.ToString(), "To string correct"); }
public void CanCreateEdmModel_WithDateAndTimeOfDay_AsFunctionParameter(Type paramType, string expect) { // Arrange ODataModelBuilder builder = ODataModelBuilderMocks.GetModelBuilderMock <ODataModelBuilder>(); EntityTypeConfiguration <Movie> movie = builder.EntitySet <Movie>("Movies").EntityType; var functionBuilder = movie.Function("FunctionName").Returns <int>(); functionBuilder.Parameter(paramType, "p1"); MethodInfo method = typeof(OperationConfiguration).GetMethod("CollectionParameter", BindingFlags.Instance | BindingFlags.Public); method.MakeGenericMethod(paramType).Invoke(functionBuilder, new[] { "p2" }); // Act IEdmModel model = builder.GetEdmModel(); //Assert IEdmOperation function = Assert.Single(model.SchemaElements.OfType <IEdmFunction>()); Assert.Equal("FunctionName", function.Name); IEdmOperationParameter parameter = function.FindParameter("p1"); Assert.Equal(expect, parameter.Type.FullName()); Assert.Equal(TypeHelper.IsNullable(paramType), parameter.Type.IsNullable); parameter = function.FindParameter("p2"); Assert.Equal("Collection(" + expect + ")", parameter.Type.FullName()); Assert.Equal(TypeHelper.IsNullable(paramType), parameter.Type.IsNullable); }
/// <summary> /// Resolve operation's parameters. /// </summary> /// <param name="operation">Current operation for parameters.</param> /// <param name="input">A dictionary the parameter list.</param> /// <returns>A dictionary containing resolved parameters.</returns> public virtual IDictionary <IEdmOperationParameter, SingleValueNode> ResolveOperationParameters(IEdmOperation operation, IDictionary <string, SingleValueNode> input) { Dictionary <IEdmOperationParameter, SingleValueNode> result = new Dictionary <IEdmOperationParameter, SingleValueNode>(EqualityComparer <IEdmOperationParameter> .Default); foreach (var item in input) { IEdmOperationParameter functionParameter = null; if (EnableCaseInsensitive) { functionParameter = ResolveOpearationParameterNameCaseInsensitive(operation, item.Key); } else { functionParameter = operation.FindParameter(item.Key); } // ensure parameter name existis if (functionParameter == null) { throw new ODataException(Strings.ODataParameterWriterCore_ParameterNameNotFoundInOperation(item.Key, operation.Name)); } result.Add(functionParameter, item.Value); } return(result); }
private static ICollection <FunctionParameterToken> HandleComplexOrCollectionParameterValueIfExists(IEdmModel model, IEdmOperation operation, ICollection <FunctionParameterToken> parameterTokens, bool enableCaseInsensitive, bool enableUriTemplateParsing = false) { ICollection <FunctionParameterToken> partiallyParsedParametersWithComplexOrCollection = new Collection <FunctionParameterToken>(); foreach (FunctionParameterToken paraToken in parameterTokens) { FunctionParameterToken funcParaToken; IEdmOperationParameter functionParameter = operation.FindParameter(paraToken.ParameterName); if (enableCaseInsensitive && functionParameter == null) { functionParameter = ODataUriResolver.ResolveOpearationParameterNameCaseInsensitive(operation, paraToken.ParameterName); // The functionParameter can not be null here, else this method won't be called. funcParaToken = new FunctionParameterToken(functionParameter.Name, paraToken.ValueToken); } else { funcParaToken = paraToken; } FunctionParameterAliasToken aliasToken = funcParaToken.ValueToken as FunctionParameterAliasToken; if (aliasToken != null) { aliasToken.ExpectedParameterType = functionParameter.Type; } LiteralToken valueToken = funcParaToken.ValueToken as LiteralToken; string valueStr = null; if (valueToken != null && (valueStr = valueToken.Value as string) != null && !string.IsNullOrEmpty(valueToken.OriginalText)) { var lexer = new ExpressionLexer(valueToken.OriginalText, true /*moveToFirstToken*/, false /*useSemicolonDelimiter*/, true /*parsingFunctionParameters*/); if (lexer.CurrentToken.Kind == ExpressionTokenKind.BracketedExpression) { object result; UriTemplateExpression expression; if (enableUriTemplateParsing && UriTemplateParser.TryParseLiteral(lexer.CurrentToken.Text, functionParameter.Type, out expression)) { result = expression; } else { // ExpressionTokenKind.BracketedExpression means text like [{\"Street\":\"NE 24th St.\",\"City\":\"Redmond\"},{\"Street\":\"Pine St.\",\"City\":\"Seattle\"}] // so now try convert it into complex or collection type value: result = ODataUriUtils.ConvertFromUriLiteral(valueStr, ODataVersion.V4, model, functionParameter.Type); } LiteralToken newValueToken = new LiteralToken(result, valueToken.OriginalText); FunctionParameterToken newFuncParaToken = new FunctionParameterToken(funcParaToken.ParameterName, newValueToken); partiallyParsedParametersWithComplexOrCollection.Add(newFuncParaToken); continue; } } partiallyParsedParametersWithComplexOrCollection.Add(funcParaToken); } return(partiallyParsedParametersWithComplexOrCollection); }
public void GetEdmModel_SetsDateTimeAsParameterType_WorksForDefaultConverter() { // Arrange ODataModelBuilder builder = ODataModelBuilderMocks.GetModelBuilderMock <ODataModelBuilder>(); EntityTypeConfiguration <Movie> movie = builder.EntitySet <Movie>("Movies").EntityType; var functionBuilder = movie.Function("DateTimeFunction"); functionBuilder.Parameter <DateTime>("dateTime"); functionBuilder.Parameter <DateTime?>("nullableDateTime"); functionBuilder.CollectionParameter <DateTime>("collectionDateTime"); functionBuilder.CollectionParameter <DateTime?>("nullableCollectionDateTime"); functionBuilder.Returns <DateTime>(); // Act IEdmModel model = builder.GetEdmModel(); //Assert IEdmOperation function = Assert.Single(model.SchemaElements.OfType <IEdmFunction>()); Assert.Equal("DateTimeFunction", function.Name); Assert.Equal("Edm.DateTimeOffset", function.ReturnType.FullName()); Assert.False(function.ReturnType.IsNullable); IEdmOperationParameter parameter = function.FindParameter("dateTime"); Assert.Equal("Edm.DateTimeOffset", parameter.Type.FullName()); Assert.False(parameter.Type.IsNullable); parameter = function.FindParameter("nullableDateTime"); Assert.Equal("Edm.DateTimeOffset", parameter.Type.FullName()); Assert.True(parameter.Type.IsNullable); parameter = function.FindParameter("collectionDateTime"); Assert.Equal("Collection(Edm.DateTimeOffset)", parameter.Type.FullName()); Assert.False(parameter.Type.IsNullable); parameter = function.FindParameter("nullableCollectionDateTime"); Assert.Equal("Collection(Edm.DateTimeOffset)", parameter.Type.FullName()); Assert.True(parameter.Type.IsNullable); }
public void GetEdmModel_SetsNullableIffParameterTypeIsNullable() { // Arrange ODataModelBuilder builder = ODataModelBuilderMocks.GetModelBuilderMock <ODataModelBuilder>(); EntityTypeConfiguration <Movie> movie = builder.EntitySet <Movie>("Movies").EntityType; var actionBuilder = movie.Action("Watch"); actionBuilder.Parameter <int>("int"); actionBuilder.Parameter <Nullable <int> >("nullableOfInt"); actionBuilder.Parameter <string>("string"); // Act IEdmModel model = builder.GetEdmModel(); //Assert IEdmOperation action = Assert.Single(model.SchemaElements.OfType <IEdmAction>()); Assert.False(action.FindParameter("int").Type.IsNullable); Assert.True(action.FindParameter("nullableOfInt").Type.IsNullable); Assert.True(action.FindParameter("string").Type.IsNullable); }
public void GetEdmModel_SetsNullableIfParameterTypeIsReferenceType() { // Arrange ODataModelBuilder builder = ODataModelBuilderMocks.GetModelBuilderMock <ODataModelBuilder>(); EntityTypeConfiguration <Movie> movie = builder.EntitySet <Movie>("Movies").EntityType; var functionBuilder = movie.Function("Watch"); functionBuilder.Parameter <string>("string").Nullable = false; functionBuilder.Parameter <string>("nullaleString"); functionBuilder.Parameter <Address>("address").Nullable = false; functionBuilder.Parameter <Address>("nullableAddress"); functionBuilder.CollectionParameter <Address>("addresses").Nullable = false; functionBuilder.CollectionParameter <Address>("nullableAddresses"); functionBuilder.Returns <int>(); // Act IEdmModel model = builder.GetEdmModel(); //Assert IEdmOperation function = Assert.Single(model.SchemaElements.OfType <IEdmFunction>()); Assert.False(function.FindParameter("string").Type.IsNullable); Assert.True(function.FindParameter("nullaleString").Type.IsNullable); Assert.False(function.FindParameter("address").Type.IsNullable); Assert.True(function.FindParameter("nullableAddress").Type.IsNullable); Assert.False(function.FindParameter("addresses").Type.IsNullable); Assert.True(function.FindParameter("nullableAddresses").Type.IsNullable); }
public void GetEdmModel_SetsNullableIfParameterTypeIsReferenceType() { // Arrange ODataModelBuilder builder = ODataModelBuilderMocks.GetModelBuilderMock <ODataModelBuilder>(); EntityTypeConfiguration <Movie> movie = builder.EntitySet <Movie>("Movies").EntityType; var actionBuilder = movie.Action("Watch"); actionBuilder.Parameter <string>("string").OptionalParameter = false; actionBuilder.Parameter <string>("nullaleString"); actionBuilder.Parameter <Address>("address").OptionalParameter = false; actionBuilder.Parameter <Address>("nullableAddress"); actionBuilder.EntityParameter <Customer>("customer").OptionalParameter = false; actionBuilder.EntityParameter <Customer>("nullableCustomer"); actionBuilder.CollectionParameter <Address>("addresses").OptionalParameter = false; actionBuilder.CollectionParameter <Address>("nullableAddresses"); actionBuilder.CollectionEntityParameter <Customer>("customers").OptionalParameter = false; actionBuilder.CollectionEntityParameter <Customer>("nullableCustomers"); // Act IEdmModel model = builder.GetEdmModel(); //Assert IEdmOperation action = Assert.Single(model.SchemaElements.OfType <IEdmAction>()); Assert.False(action.FindParameter("string").Type.IsNullable); Assert.True(action.FindParameter("nullaleString").Type.IsNullable); Assert.False(action.FindParameter("address").Type.IsNullable); Assert.True(action.FindParameter("nullableAddress").Type.IsNullable); Assert.False(action.FindParameter("customer").Type.IsNullable); Assert.True(action.FindParameter("nullableCustomer").Type.IsNullable); Assert.False(action.FindParameter("addresses").Type.IsNullable); Assert.True(action.FindParameter("nullableAddresses").Type.IsNullable); // Follow up: https://github.com/OData/odata.net/issues/98 // Assert.False(action.FindParameter("customers").Type.IsNullable); Assert.True(action.FindParameter("nullableCustomers").Type.IsNullable); }
public void AmbiguousOperationTest() { string csdl = @" <Schema Namespace=""DefaultNamespace"" xmlns=""http://docs.oasis-open.org/odata/ns/edm""> <Term Name=""Annotation"" Type=""Edm.Int32"" /> <EntityType Name=""Entity"" > <Key> <PropertyRef Name=""ID"" /> </Key> <Property Name=""ID"" Type=""Edm.Int32"" Nullable=""False"" /> </EntityType> <Function Name=""Function""> <Parameter Name=""Parameter"" Type=""Edm.String"" /> <Parameter Name=""Parameter2"" Type=""Ref(DefaultNamespace.Entity)"" /> <ReturnType Type=""Edm.Int32"" /> </Function> <Function Name=""Function""> <Parameter Name=""Parameter"" Type=""Edm.String"" /> <Parameter Name=""Parameter2"" Type=""Ref(DefaultNamespace.Entity)"" /> <ReturnType Type=""Edm.Int32"" /> </Function> <Function Name=""Function""> <Parameter Name=""Parameter"" Type=""Edm.String"" /> <Parameter Name=""Parameter2"" Type=""Ref(DefaultNamespace.Entity)"" /> <ReturnType Type=""Edm.Int32"" /> </Function> <Annotations Target=""DefaultNamespace.Function(Edm.String, Ref(DefaultNamespace.Entity))""> <Annotation Term=""AnnotationNamespace.Annotation""> <Int>42</Int> </Annotation> </Annotations> </Schema>"; IEdmModel model; IEnumerable <EdmError> errors; bool parsed = SchemaReader.TryParse(new XmlReader[] { XmlReader.Create(new StringReader(csdl)) }, out model, out errors); Assert.IsTrue(parsed, "parsed"); Assert.IsTrue(errors.Count() == 0, "No errors"); IEdmVocabularyAnnotation annotation = model.VocabularyAnnotations.First(); IEdmOperation firstOperation = model.FindOperations("DefaultNamespace.Function").First(); IEdmOperation ambiguousOperation = annotation.Target as IEdmOperation; Assert.IsNotNull(ambiguousOperation, "Function not null"); Assert.AreEqual(EdmSchemaElementKind.Function, ambiguousOperation.SchemaElementKind, "Correct schema element kind"); Assert.IsNull(ambiguousOperation.ReturnType, "Null return type"); Assert.AreEqual("DefaultNamespace", ambiguousOperation.Namespace, "Correct namespace"); Assert.AreEqual(firstOperation.Parameters.First(), ambiguousOperation.Parameters.First(), "Function gets parameters from first function"); Assert.AreEqual(firstOperation.FindParameter("Parameter"), ambiguousOperation.FindParameter("Parameter"), "Find parameter defers to first function"); }
public override IDictionary <IEdmOperationParameter, SingleValueNode> ResolveOperationParameters(IEdmOperation operation, IDictionary <string, SingleValueNode> input) { Dictionary <IEdmOperationParameter, SingleValueNode> result = new Dictionary <IEdmOperationParameter, SingleValueNode>(EqualityComparer <IEdmOperationParameter> .Default); foreach (var item in input) { IEdmOperationParameter functionParameter = null; if (EnableCaseInsensitive) { var list = operation.Parameters.Where(parameter => string.Equals(item.Key, parameter.Name, StringComparison.OrdinalIgnoreCase)).ToList(); if (list.Count == 1) { functionParameter = list.Single(); } else if (list.Count > 1) { // TODO: fix loc strings. throw new ODataException("More than one parameter match the name '" + item.Key + "' were found."); } } else { functionParameter = operation.FindParameter(item.Key); } // ensure parameter name existis if (functionParameter == null) { throw new ODataException(Strings.ODataParameterWriterCore_ParameterNameNotFoundInOperation(item.Key, operation.Name)); } SingleValueNode newVal = item.Value; if (functionParameter.Type.IsEnum() && (newVal.TypeReference.IsString()) && newVal is ConstantNode) { string text = ((ConstantNode)item.Value).Value as string; ODataEnumValue val; IEdmTypeReference typeRef = functionParameter.Type; if (TryParseEnum(typeRef.Definition as IEdmEnumType, text, out val)) { newVal = new ConstantNode(val, text, typeRef); } } result.Add(functionParameter, newVal); } return(result); }
private static ICollection <FunctionParameterToken> HandleComplexOrCollectionParameterValueIfExists(IEdmModel model, IEdmOperation functionOrOpertion, ICollection <FunctionParameterToken> parameterTokens, bool enableUriTemplateParsing = false) { ICollection <FunctionParameterToken> partiallyParsedParametersWithComplexOrCollection = new Collection <FunctionParameterToken>(); foreach (FunctionParameterToken funcParaToken in parameterTokens) { LiteralToken valueToken = funcParaToken.ValueToken as LiteralToken; string valueStr = null; if (valueToken != null && (valueStr = valueToken.Value as string) != null) { var lexer = new ExpressionLexer(valueStr, true /*moveToFirstToken*/, false /*useSemicolonDelimiter*/, true /*parsingFunctionParameters*/); if (lexer.CurrentToken.Kind == ExpressionTokenKind.BracketedExpression) { var functionParameter = functionOrOpertion.FindParameter(funcParaToken.ParameterName); if (functionParameter == null) { throw new ODataException(Strings.ODataParameterWriterCore_ParameterNameNotFoundInOperation(funcParaToken.ParameterName, functionOrOpertion.Name)); } object result; UriTemplateExpression expression; if (enableUriTemplateParsing && UriTemplateParser.TryParseLiteral(lexer.CurrentToken.Text, functionParameter.Type, out expression)) { result = expression; } else { // ExpressionTokenKind.BracketedExpression means text like [{\"Street\":\"NE 24th St.\",\"City\":\"Redmond\"},{\"Street\":\"Pine St.\",\"City\":\"Seattle\"}] // so now try convert it into complex or collection type value: result = ODataUriUtils.ConvertFromUriLiteral(valueStr, ODataVersion.V4, model, functionParameter.Type); } LiteralToken newValueToken = new LiteralToken(result, valueToken.OriginalText); FunctionParameterToken newFuncParaToken = new FunctionParameterToken(funcParaToken.ParameterName, newValueToken); partiallyParsedParametersWithComplexOrCollection.Add(newFuncParaToken); continue; } } partiallyParsedParametersWithComplexOrCollection.Add(funcParaToken); } return(partiallyParsedParametersWithComplexOrCollection); }
internal static List <OperationSegmentParameter> BindSegmentParameters(ODataUriParserConfiguration configuration, IEdmOperation functionOrOpertion, ICollection <FunctionParameterToken> segmentParameterTokens) { // TODO: HandleComplexOrCollectionParameterValueIfExists is temp work around for single copmlex or colleciton type, it can't handle nested complex or collection value. ICollection <FunctionParameterToken> parametersParsed = FunctionCallBinder.HandleComplexOrCollectionParameterValueIfExists(configuration.Model, functionOrOpertion, segmentParameterTokens, configuration.EnableUriTemplateParsing); // Bind it to metadata BindingState state = new BindingState(configuration); state.ImplicitRangeVariable = null; state.RangeVariables.Clear(); MetadataBinder binder = new MetadataBinder(state); List <OperationSegmentParameter> boundParameters = new List <OperationSegmentParameter>(); foreach (var paraToken in parametersParsed) { // TODO: considering another better exception if (paraToken.ValueToken is EndPathToken) { throw new ODataException(Strings.MetadataBinder_ParameterNotInScope( string.Format(CultureInfo.InvariantCulture, "{0}={1}", paraToken.ParameterName, (paraToken.ValueToken as EndPathToken).Identifier))); } SingleValueNode boundNode = (SingleValueNode)binder.Bind(paraToken.ValueToken); // ensure parameter name existis var functionParameter = functionOrOpertion.FindParameter(paraToken.ParameterName); if (functionParameter == null) { throw new ODataException(Strings.ODataParameterWriterCore_ParameterNameNotFoundInOperation(paraToken.ParameterName, functionOrOpertion.Name)); } // ensure node type is compatible with parameter type. var sourceTypeReference = boundNode.GetEdmTypeReference(); bool sourceIsNullOrOpenType = (sourceTypeReference == null); if (!sourceIsNullOrOpenType) { boundNode = MetadataBindingUtils.ConvertToTypeIfNeeded(boundNode, functionParameter.Type); } OperationSegmentParameter boundParamer = new OperationSegmentParameter(paraToken.ParameterName, boundNode); boundParameters.Add(boundParamer); } return(boundParameters); }
public override IDictionary <IEdmOperationParameter, SingleValueNode> ResolveOperationParameters(IEdmOperation operation, IDictionary <string, SingleValueNode> input) { Dictionary <IEdmOperationParameter, SingleValueNode> result = new Dictionary <IEdmOperationParameter, SingleValueNode>(EqualityComparer <IEdmOperationParameter> .Default); foreach (var item in input) { IEdmOperationParameter functionParameter = null; if (EnableCaseInsensitive) { functionParameter = ODataUriResolver.ResolveOpearationParameterNameCaseInsensitive(operation, item.Key); } else { functionParameter = operation.FindParameter(item.Key); } // ensure parameter name existis if (functionParameter == null) { throw new ODataException(Strings.ODataParameterWriterCore_ParameterNameNotFoundInOperation(item.Key, operation.Name)); } SingleValueNode newVal = item.Value; if (functionParameter.Type.IsEnum() && newVal is ConstantNode && newVal.TypeReference != null && newVal.TypeReference.IsString()) { string text = ((ConstantNode)item.Value).Value as string; ODataEnumValue val; IEdmTypeReference typeRef = functionParameter.Type; if (TryParseEnum(typeRef.Definition as IEdmEnumType, text, out val)) { newVal = new ConstantNode(val, text, typeRef); } } result.Add(functionParameter, newVal); } return(result); }
/// <summary> /// Resolve operation's parameters. /// </summary> /// <param name="operation">Current operation for parameters.</param> /// <param name="input">A dictionary the paramenter list.</param> /// <returns>A dictionary containing resolved parameters.</returns> public virtual IDictionary <IEdmOperationParameter, SingleValueNode> ResolveOperationParameters(IEdmOperation operation, IDictionary <string, SingleValueNode> input) { Dictionary <IEdmOperationParameter, SingleValueNode> result = new Dictionary <IEdmOperationParameter, SingleValueNode>(EqualityComparer <IEdmOperationParameter> .Default); foreach (var item in input) { IEdmOperationParameter functionParameter = null; if (EnableCaseInsensitive) { var list = operation.Parameters.Where(parameter => string.Equals(item.Key, parameter.Name, StringComparison.OrdinalIgnoreCase)).ToList(); if (list.Count == 1) { functionParameter = list.Single(); } else if (list.Count > 1) { // TODO: fix loc strings. throw new ODataException("More than one parameter match the name '" + item.Key + "' were found."); } } else { functionParameter = operation.FindParameter(item.Key); } // ensure parameter name existis if (functionParameter == null) { throw new ODataException(Strings.ODataParameterWriterCore_ParameterNameNotFoundInOperation(item.Key, operation.Name)); } result.Add(functionParameter, item.Value); } return(result); }
private IEdmVocabularyAnnotatable ComputeTarget() { if (this.targetContext != null) { return(this.targetContext); } else { Debug.Assert(this.annotationsContext != null, "Annotation must either have a target context or annotations context"); string target = this.annotationsContext.Annotations.Target; string[] targetSegments = target.Split('/'); int targetSegmentsCount = targetSegments.Length; IEdmEntityContainer container; if (targetSegmentsCount == 1) { string elementName = targetSegments[0]; IEdmSchemaType type = this.schema.FindType(elementName); if (type != null) { return(type); } IEdmTerm term = this.schema.FindTerm(elementName); if (term != null) { return(term); } IEdmOperation operation = this.FindParameterizedOperation(elementName, this.Schema.FindOperations, this.CreateAmbiguousOperation); if (operation != null) { return(operation); } container = this.schema.FindEntityContainer(elementName); if (container != null) { return(container); } return(new UnresolvedType(this.Schema.UnresolvedName(targetSegments[0]), this.Location)); } if (targetSegmentsCount == 2) { container = this.schema.FindEntityContainer(targetSegments[0]); if (container != null) { // Using the methods here results in a much faster lookup as it uses a dictionary instead of using the list of container elements. IEdmEntityContainerElement containerElement = container.FindEntitySetExtended(targetSegments[1]) ?? container.FindSingletonExtended(targetSegments[1]) as IEdmEntityContainerElement; if (containerElement != null) { return(containerElement); } IEdmOperationImport operationImport = FindParameterizedOperationImport(targetSegments[1], container.FindOperationImportsExtended, this.CreateAmbiguousOperationImport); if (operationImport != null) { return(operationImport); } return(new UnresolvedEntitySet(targetSegments[1], container, this.Location)); } IEdmSchemaType type = this.schema.FindType(targetSegments[0]); if (type != null) { IEdmStructuredType structuredType; IEdmEnumType enumType; if ((structuredType = type as IEdmStructuredType) != null) { IEdmProperty property = structuredType.FindProperty(targetSegments[1]); if (property != null) { return(property); } return(new UnresolvedProperty(structuredType, targetSegments[1], this.Location)); } else if ((enumType = type as IEdmEnumType) != null) { foreach (IEdmEnumMember member in enumType.Members) { if (String.Equals(member.Name, targetSegments[1], StringComparison.OrdinalIgnoreCase)) { return(member); } } return(new UnresolvedEnumMember(targetSegments[1], enumType, this.Location)); } } IEdmOperation operation = this.FindParameterizedOperation(targetSegments[0], this.Schema.FindOperations, this.CreateAmbiguousOperation); if (operation != null) { // $ReturnType if (targetSegments[1] == CsdlConstants.OperationReturnExternalTarget) { if (operation.ReturnType != null) { return(operation.GetReturn()); } return(new UnresolvedReturn(operation, this.Location)); } IEdmOperationParameter parameter = operation.FindParameter(targetSegments[1]); if (parameter != null) { return(parameter); } return(new UnresolvedParameter(operation, targetSegments[1], this.Location)); } return(new UnresolvedProperty(new UnresolvedEntityType(this.Schema.UnresolvedName(targetSegments[0]), this.Location), targetSegments[1], this.Location)); } if (targetSegmentsCount == 3) { // The only valid target with three segments is a function parameter, or an operation return. string containerName = targetSegments[0]; string operationName = targetSegments[1]; string parameterName = targetSegments[2]; container = this.Model.FindEntityContainer(containerName); if (container != null) { IEdmOperationImport operationImport = FindParameterizedOperationImport(operationName, container.FindOperationImportsExtended, this.CreateAmbiguousOperationImport); if (operationImport != null) { // $ReturnType if (parameterName == CsdlConstants.OperationReturnExternalTarget) { if (operationImport.Operation.ReturnType != null) { return(operationImport.Operation.GetReturn()); } return(new UnresolvedReturn(operationImport.Operation, this.Location)); } IEdmOperationParameter parameter = operationImport.Operation.FindParameter(parameterName); if (parameter != null) { return(parameter); } return(new UnresolvedParameter(operationImport.Operation, parameterName, this.Location)); } } string qualifiedOperationName = containerName + "/" + operationName; UnresolvedOperation unresolvedOperation = new UnresolvedOperation(qualifiedOperationName, Edm.Strings.Bad_UnresolvedOperation(qualifiedOperationName), this.Location); if (parameterName == CsdlConstants.OperationReturnExternalTarget) { return(new UnresolvedReturn(unresolvedOperation, this.Location)); } else { return(new UnresolvedParameter(unresolvedOperation, parameterName, this.Location)); } } return(new BadElement(new EdmError[] { new EdmError(this.Location, EdmErrorCode.ImpossibleAnnotationsTarget, Edm.Strings.CsdlSemantics_ImpossibleAnnotationsTarget(target)) })); } }
private static ICollection<FunctionParameterToken> HandleComplexOrCollectionParameterValueIfExists(IEdmModel model, IEdmOperation operation, ICollection<FunctionParameterToken> parameterTokens, bool enableCaseInsensitive, bool enableUriTemplateParsing = false) { ICollection<FunctionParameterToken> partiallyParsedParametersWithComplexOrCollection = new Collection<FunctionParameterToken>(); foreach (FunctionParameterToken paraToken in parameterTokens) { FunctionParameterToken funcParaToken; IEdmOperationParameter functionParameter = operation.FindParameter(paraToken.ParameterName); if (enableCaseInsensitive && functionParameter == null) { functionParameter = ODataUriResolver.ResolveOpearationParameterNameCaseInsensitive(operation, paraToken.ParameterName); // The functionParameter can not be null here, else this method won't be called. funcParaToken = new FunctionParameterToken(functionParameter.Name, paraToken.ValueToken); } else { funcParaToken = paraToken; } FunctionParameterAliasToken aliasToken = funcParaToken.ValueToken as FunctionParameterAliasToken; if (aliasToken != null) { aliasToken.ExpectedParameterType = functionParameter.Type; } LiteralToken valueToken = funcParaToken.ValueToken as LiteralToken; string valueStr = null; if (valueToken != null && (valueStr = valueToken.Value as string) != null && !string.IsNullOrEmpty(valueToken.OriginalText)) { var lexer = new ExpressionLexer(valueToken.OriginalText, true /*moveToFirstToken*/, false /*useSemicolonDelimiter*/, true /*parsingFunctionParameters*/); if (lexer.CurrentToken.Kind == ExpressionTokenKind.BracketedExpression) { object result; UriTemplateExpression expression; if (enableUriTemplateParsing && UriTemplateParser.TryParseLiteral(lexer.CurrentToken.Text, functionParameter.Type, out expression)) { result = expression; } else { // ExpressionTokenKind.BracketedExpression means text like [{\"Street\":\"NE 24th St.\",\"City\":\"Redmond\"},{\"Street\":\"Pine St.\",\"City\":\"Seattle\"}] // so now try convert it into complex or collection type value: result = ODataUriUtils.ConvertFromUriLiteral(valueStr, ODataVersion.V4, model, functionParameter.Type); } LiteralToken newValueToken = new LiteralToken(result, valueToken.OriginalText); FunctionParameterToken newFuncParaToken = new FunctionParameterToken(funcParaToken.ParameterName, newValueToken); partiallyParsedParametersWithComplexOrCollection.Add(newFuncParaToken); continue; } } partiallyParsedParametersWithComplexOrCollection.Add(funcParaToken); } return partiallyParsedParametersWithComplexOrCollection; }
private IEdmVocabularyAnnotatable ComputeTarget() { if (this.targetContext != null) { return(this.targetContext); } else { Debug.Assert(this.annotationsContext != null, "Annotation must either have a target context or annotations context"); string target = this.annotationsContext.Annotations.Target; string[] targetSegments = target.Split('/'); int targetSegmentsCount = targetSegments.Count(); IEdmEntityContainer container; if (targetSegmentsCount == 1) { string elementName = targetSegments[0]; IEdmSchemaType type = this.schema.FindType(elementName); if (type != null) { return(type); } IEdmValueTerm term = this.schema.FindValueTerm(elementName); if (term != null) { return(term); } IEdmOperation operation = this.FindParameterizedOperation(elementName, this.Schema.FindOperations, this.CreateAmbiguousOperation); if (operation != null) { return(operation); } container = this.schema.FindEntityContainer(elementName); if (container != null) { return(container); } return(new UnresolvedType(this.Schema.UnresolvedName(targetSegments[0]), this.Location)); } if (targetSegmentsCount == 2) { container = this.schema.FindEntityContainer(targetSegments[0]); if (container != null) { IEdmEntityContainerElement containerElement = container.FindEntitySetExtended(targetSegments[1]); if (containerElement != null) { return(containerElement); } IEdmOperationImport operationImport = this.FindParameterizedOperationImport(targetSegments[1], container.FindOperationImportsExtended, this.CreateAmbiguousOperationImport); if (operationImport != null) { return(operationImport); } return(new UnresolvedEntitySet(targetSegments[1], container, this.Location)); } IEdmStructuredType type = this.schema.FindType(targetSegments[0]) as IEdmStructuredType; if (type != null) { IEdmProperty property = type.FindProperty(targetSegments[1]); if (property != null) { return(property); } return(new UnresolvedProperty(type, targetSegments[1], this.Location)); } IEdmOperation operation = this.FindParameterizedOperation(targetSegments[0], this.Schema.FindOperations, this.CreateAmbiguousOperation); if (operation != null) { IEdmOperationParameter parameter = operation.FindParameter(targetSegments[1]); if (parameter != null) { return(parameter); } return(new UnresolvedParameter(operation, targetSegments[1], this.Location)); } return(new UnresolvedProperty(new UnresolvedEntityType(this.Schema.UnresolvedName(targetSegments[0]), this.Location), targetSegments[1], this.Location)); } if (targetSegmentsCount == 3) { // The only valid target with three segments is a function parameter. string containerName = targetSegments[0]; string operationName = targetSegments[1]; string parameterName = targetSegments[2]; container = this.Model.FindEntityContainer(containerName); if (container != null) { IEdmOperationImport operationImport = this.FindParameterizedOperationImport(operationName, container.FindOperationImportsExtended, this.CreateAmbiguousOperationImport); if (operationImport != null) { IEdmOperationParameter parameter = operationImport.Operation.FindParameter(parameterName); if (parameter != null) { return(parameter); } return(new UnresolvedParameter(operationImport.Operation, parameterName, this.Location)); } } string qualifiedOperationName = containerName + "/" + operationName; UnresolvedOperation unresolvedOperation = new UnresolvedOperation(qualifiedOperationName, Edm.Strings.Bad_UnresolvedOperation(qualifiedOperationName), this.Location); return(new UnresolvedParameter(unresolvedOperation, parameterName, this.Location)); } return(new BadElement(new EdmError[] { new EdmError(this.Location, EdmErrorCode.ImpossibleAnnotationsTarget, Edm.Strings.CsdlSemantics_ImpossibleAnnotationsTarget(target)) })); } }
public override IDictionary<IEdmOperationParameter, SingleValueNode> ResolveOperationParameters(IEdmOperation operation, IDictionary<string, SingleValueNode> input) { Dictionary<IEdmOperationParameter, SingleValueNode> result = new Dictionary<IEdmOperationParameter, SingleValueNode>(EqualityComparer<IEdmOperationParameter>.Default); foreach (var item in input) { IEdmOperationParameter functionParameter = null; if (EnableCaseInsensitive) { functionParameter = ODataUriResolver.ResolveOpearationParameterNameCaseInsensitive(operation, item.Key); } else { functionParameter = operation.FindParameter(item.Key); } // ensure parameter name existis if (functionParameter == null) { throw new ODataException(Strings.ODataParameterWriterCore_ParameterNameNotFoundInOperation(item.Key, operation.Name)); } SingleValueNode newVal = item.Value; if (functionParameter.Type.IsEnum() && newVal is ConstantNode && newVal.TypeReference != null && newVal.TypeReference.IsString()) { string text = ((ConstantNode)item.Value).Value as string; ODataEnumValue val; IEdmTypeReference typeRef = functionParameter.Type; if (TryParseEnum(typeRef.Definition as IEdmEnumType, text, out val)) { newVal = new ConstantNode(val, text, typeRef); } } result.Add(functionParameter, newVal); } return result; }
/// <summary> /// Resolve operation's parameters. /// </summary> /// <param name="operation">Current operation for parameters.</param> /// <param name="input">A dictionary the parameter list.</param> /// <returns>A dictionary containing resolved parameters.</returns> public virtual IDictionary<IEdmOperationParameter, SingleValueNode> ResolveOperationParameters(IEdmOperation operation, IDictionary<string, SingleValueNode> input) { Dictionary<IEdmOperationParameter, SingleValueNode> result = new Dictionary<IEdmOperationParameter, SingleValueNode>(EqualityComparer<IEdmOperationParameter>.Default); foreach (var item in input) { IEdmOperationParameter functionParameter = null; if (EnableCaseInsensitive) { functionParameter = ResolveOpearationParameterNameCaseInsensitive(operation, item.Key); } else { functionParameter = operation.FindParameter(item.Key); } // ensure parameter name existis if (functionParameter == null) { throw new ODataException(Strings.ODataParameterWriterCore_ParameterNameNotFoundInOperation(item.Key, operation.Name)); } result.Add(functionParameter, item.Value); } return result; }
public void CsdlTypeReferenceToStringTest() { const string csdl = @"<?xml version=""1.0"" encoding=""utf-16""?> <Schema Namespace=""AwesomeNamespace"" Alias=""Alias"" xmlns=""http://docs.oasis-open.org/odata/ns/edm""> <EntityType Name=""AstonishingEntity""> <Key> <PropertyRef Name=""Id"" /> </Key> <Property Name=""Id"" Type=""Int32"" Nullable=""false"" /> </EntityType> <EntityType Name=""AweInspiringEntity""> <Key> <PropertyRef Name=""Id"" /> </Key> <Property Name=""Id"" Type=""Int32"" Nullable=""false"" /> <Property Name=""AstonishingID"" Type=""Int32"" /> </EntityType> <ComplexType Name=""BreathtakingComplex""> <Property Name=""Par1"" Type=""Int32"" Nullable=""false"" /> <Property Name=""Par2"" Type=""Int32"" Nullable=""false"" /> </ComplexType> <Function Name=""Function1""><ReturnType Type=""Edm.Int32""/> <Parameter Name=""P1"" Type=""AwesomeNamespace.AstonishingEntity"" /> <Parameter Name=""P2"" Type=""AwesomeNamespace.BreathtakingComplex"" /> <Parameter Name=""P3"" Type=""AwesomeNamespace.ExaltedAssociation"" /> <Parameter Name=""P4"" Type=""Edm.Int32"" /> <Parameter Name=""P5"" Type=""Edm.String"" MaxLength=""128"" Unicode=""false"" /> <Parameter Name=""P6"" Type=""Edm.Stream"" /> <Parameter Name=""P7"" Type=""Edm.Binary"" MaxLength=""max""/> <Parameter Name=""P8"" Type=""Edm.DateTimeOffset"" Precision=""1"" /> <Parameter Name=""P9"" Type=""Edm.Decimal"" Precision=""3"" Scale=""2""/> <Parameter Name=""P10"" Type=""Edm.Geography"" SRID=""1"" /> <Parameter Name=""P11"" Type=""Ref(AwesomeNamespace.AstonishingEntity)"" /> <Parameter Name=""P12"" Type=""Collection(Edm.Int32)"" /> <Parameter Name=""P14"" Type=""AwesomeNamespace.FabulousEnum"" /> </Function> <EnumType Name=""FabulousEnum""> <Member Name=""m1"" /> <Member Name=""m2"" /> </EnumType> </Schema>"; IEdmModel model; IEnumerable <EdmError> errors; bool parsed = CsdlReader.TryParse(new XmlReader[] { XmlReader.Create(new StringReader(csdl)) }, out model, out errors); Assert.IsTrue(parsed, "parsed"); Assert.IsTrue(errors.Count() == 0, "No errors"); IEdmOperation operation = (IEdmOperation)(model.FindOperations("AwesomeNamespace.Function1")).First(); IEdmEntityTypeReference entity = operation.FindParameter("P1").Type.AsEntity(); IEdmComplexTypeReference complex = operation.FindParameter("P2").Type.AsComplex(); IEdmTypeReference association = operation.FindParameter("P3").Type; IEdmPrimitiveTypeReference primitive = operation.FindParameter("P4").Type.AsPrimitive(); IEdmStringTypeReference stringType = operation.FindParameter("P5").Type.AsString(); IEdmPrimitiveTypeReference stream = operation.FindParameter("P6").Type.AsPrimitive(); IEdmBinaryTypeReference binary = operation.FindParameter("P7").Type.AsBinary(); IEdmTemporalTypeReference temporal = operation.FindParameter("P8").Type.AsTemporal(); IEdmDecimalTypeReference decimalType = operation.FindParameter("P9").Type.AsDecimal(); IEdmSpatialTypeReference spatial = operation.FindParameter("P10").Type.AsSpatial(); IEdmEntityReferenceTypeReference entityRef = operation.FindParameter("P11").Type.AsEntityReference(); IEdmCollectionTypeReference collection = operation.FindParameter("P12").Type.AsCollection(); IEdmEnumTypeReference enumTypeRef = operation.FindParameter("P14").Type.AsEnum(); IEdmTypeReference type = operation.FindParameter("P1").Type; Assert.IsFalse(association.IsBad(), "Associations cannot be types"); Assert.IsTrue(association.Definition.IsBad(), "Associations cannot be types"); Assert.AreEqual("[AwesomeNamespace.AstonishingEntity Nullable=True]", entity.ToString(), "To string correct"); Assert.AreEqual("[AwesomeNamespace.BreathtakingComplex Nullable=True]", complex.ToString(), "To string correct"); Assert.AreEqual("[Edm.Int32 Nullable=True]", primitive.ToString(), "To string correct"); Assert.AreEqual("[Edm.String Nullable=True MaxLength=128 Unicode=False]", stringType.ToString(), "To string correct"); Assert.AreEqual("[Edm.Stream Nullable=True]", stream.ToString(), "To string correct"); Assert.AreEqual("[Edm.Binary Nullable=True MaxLength=max]", binary.ToString(), "To string correct"); Assert.AreEqual("[Edm.DateTimeOffset Nullable=True Precision=1]", temporal.ToString(), "To string correct"); Assert.AreEqual("[Edm.Decimal Nullable=True Precision=3 Scale=2]", decimalType.ToString(), "To string correct"); Assert.AreEqual("[Edm.Geography Nullable=True SRID=1]", spatial.ToString(), "To string correct"); Assert.AreEqual("[Collection([Edm.Int32 Nullable=True]) Nullable=True]", collection.ToString(), "To string correct"); Assert.AreEqual("[EntityReference(AwesomeNamespace.AstonishingEntity) Nullable=True]", entityRef.ToString(), "To string correct"); Assert.AreEqual("[AwesomeNamespace.FabulousEnum Nullable=True]", enumTypeRef.ToString(), "To string correct"); Assert.AreEqual("[AwesomeNamespace.AstonishingEntity Nullable=True]", type.ToString(), "To string correct"); }