internal string GetDatePartString(ODataFunction datePartFunction) { switch (datePartFunction) { case ODataFunction.Second: return("SECOND"); case ODataFunction.Minute: return("MINUTE"); case ODataFunction.Hour: return("HOUR"); case ODataFunction.Day: return("DAY"); case ODataFunction.Month: return("MONTH"); case ODataFunction.Year: return("YEAR"); default: throw new ArgumentException("Function " + datePartFunction + " is not a date part function"); } }
public void PropertyGettersAndSettersTest() { Uri metadata = new Uri("http://odata.org/operationMetadata"); string title = "OperationTitle"; Uri target = new Uri("http://odata.org/operationtarget"); ODataAction action = new ODataAction() { Metadata = metadata, Title = title, Target = target, }; this.Assert.AreSame(metadata, action.Metadata, "Expected reference equal values for property 'Metadata'."); this.Assert.AreEqual(title, action.Title, "Expected equal Title values."); this.Assert.AreSame(target, action.Target, "Expected reference equal values for property 'Target'."); ODataFunction function = new ODataFunction() { Metadata = metadata, Title = title, Target = target, }; this.Assert.AreSame(metadata, function.Metadata, "Expected reference equal values for property 'Metadata'."); this.Assert.AreEqual(title, function.Title, "Expected equal Title values."); this.Assert.AreSame(target, function.Target, "Expected reference equal values for property 'Target'."); }
public void OmitOperations() { var resource = new ODataResource(); ODataMessageWriterSettings settings = new ODataMessageWriterSettings(); settings.MetadataSelector = new TestMetadataSelector(); ODataResourceMetadataBuilder resourceMetadataBuilder = fullMetadataLevel.CreateResourceMetadataBuilder( resource, personTypeContext, null, HardCodedTestModel.GetPersonType(), new SelectedPropertiesNode(SelectedPropertiesNode.SelectionType.EntireSubtree), /*isResponse*/ true, /*keyAsSegment*/ false, /*requestUri*/ null, /*settings*/ settings); fullMetadataLevel.InjectMetadataBuilder(resource, resourceMetadataBuilder); var function = new ODataFunction { Metadata = new Uri(MetadataDocumentUri, "#function1"), }; var action = new ODataAction { Metadata = new Uri(MetadataDocumentUri, "#action2") }; resource.AddFunction(function); resource.AddAction(action); resource.MetadataBuilder.Should().BeSameAs(resourceMetadataBuilder); //metadataselector only allows for two HasHat functions to be written as metadata Assert.True(resource.Functions.Count() == 3); Assert.True(resource.Actions.Count() == 1); }
/// <summary> /// Uses the DATEPART function /// </summary> protected internal override void RenderDatePartFunctionCall(ODataFunction datePartFunction, Action <string> writer, Action renderArgument) { writer("DATEPART("); writer(this.GetDatePartString(datePartFunction)); writer(", "); renderArgument(); writer(")"); }
/// <summary> /// Add function to feed. /// </summary> /// <param name="function">The function to add.</param> public void AddFunction(ODataFunction function) { ExceptionUtils.CheckArgumentNotNull(function, "function"); if (!this.functions.Contains(function)) { this.functions.Add(function); } }
/// <summary> /// Adds an ODataFunction to an entry. /// </summary> /// <param name="entry">The entry to add the function.</param> /// <param name="function">The function to add.</param> internal static void AddFunction(this ODataEntry entry, ODataFunction function) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(entry != null, "entry != null"); Debug.Assert(function != null, "function != null"); entry.Functions = entry.Functions.ConcatToReadOnlyEnumerable("Functions", function); }
internal static void AddFunctionToEntry(ODataEntry entry, ODataFunction function) { if (object.ReferenceEquals(entry.Functions, EmptyFunctionsList)) { entry.Functions = new ReadOnlyEnumerable <ODataFunction>(); } GetSourceListOfEnumerable <ODataFunction>(entry.Functions, "Functions").Add(function); }
/// <summary> /// Add function to resource set. /// </summary> /// <param name="function">The function to add.</param> public void AddFunction(ODataFunction function) { ExceptionUtils.CheckArgumentNotNull(function, "function"); if (!this.functions.Contains(function)) { this.functions.Add(function); } }
/// <summary> /// Helper function to render a "datepart" function. Defaults to the ANSI EXTRACT([date part] FROM [expression]). /// See http://users.atw.hu/sqlnut/sqlnut2-chp-4-sect-4.html for more information /// </summary> /// <param name="datePartFunction">An <see cref="ODataFunction"/> such as <see cref="ODataFunction.Day"/></param> /// <param name="writer">A function that can be called to write SQL output</param> /// <param name="renderArgument">A function that can be called to render the expression being operated on</param> protected internal virtual void RenderDatePartFunctionCall(ODataFunction datePartFunction, Action <string> writer, Action renderArgument) { writer("EXTRACT("); writer(this.GetDatePartString(datePartFunction)); writer(" FROM "); renderArgument(); writer(")"); }
public void DefaultValuesTest() { ODataAction action = new ODataAction(); this.Assert.IsNull(action.Metadata, "Expected null default value for property 'Metadata'."); this.Assert.IsNull(action.Title, "Expected null default value for property 'Title'."); this.Assert.IsNull(action.Target, "Expected null default value for property 'Target'."); ODataFunction function = new ODataFunction(); this.Assert.IsNull(function.Metadata, "Expected null default value for property 'Metadata'."); this.Assert.IsNull(function.Title, "Expected null default value for property 'Title'."); this.Assert.IsNull(function.Target, "Expected null default value for property 'Target'."); }
public void AddDuplicateFunction() { var function = new ODataFunction() { Metadata = new Uri("http://odata.org/metadata"), Target = new Uri("http://odata.org/target"), Title = "TestFunction", }; this.odataEntry.AddFunction(function); this.odataEntry.AddFunction(function); this.odataEntry.Functions.Count().Should().Be(1); this.odataEntry.Functions.First().Should().Be(function); }
/// <summary> /// Récupèrer la fonction adéquate selon l'opérateur et le type de champ /// </summary> /// <param name="oDataLogicalOperators"></param> /// <param name="oDataBaseFieldType"></param> /// <returns></returns> public ODataFunction GetFunction(ODataLogicalOperators oDataLogicalOperators, string propertyName, string value = null) { ODataFunction oDataFunction = null; switch (oDataLogicalOperators) { case ODataLogicalOperators.Eq: oDataFunction = new ODataEqual(propertyName, this.GetParsedValue(value)); break; case ODataLogicalOperators.Ne: oDataFunction = new ODataNotEqual(propertyName, this.GetParsedValue(value)); break; case ODataLogicalOperators.Gt: oDataFunction = new ODataGreaterThan(propertyName, this.GetParsedValue(value)); break; case ODataLogicalOperators.Ge: oDataFunction = new ODataGreaterThanOrEqual(propertyName, this.GetParsedValue(value)); break; case ODataLogicalOperators.Lt: oDataFunction = new ODataLessThan(propertyName, this.GetParsedValue(value)); break; case ODataLogicalOperators.Le: oDataFunction = new ODataLessThanOrEqual(propertyName, this.GetParsedValue(value)); break; case ODataLogicalOperators.StartsWith: oDataFunction = new ODataStartsWith(propertyName, value); break; case ODataLogicalOperators.And: oDataFunction = new ODataAndFunction(); break; case ODataLogicalOperators.Or: oDataFunction = new ODataOrFunction(); break; case ODataLogicalOperators.Not: oDataFunction = new ODataNotFunction(); break; default: break; } return(oDataFunction); }
/// <summary> /// Adds an ODataFunction to an entry. /// </summary> /// <param name="entry">The entry to add the function.</param> /// <param name="function">The function to add.</param> internal static void AddFunctionToEntry(ODataEntry entry, ODataFunction function) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(entry != null, "entry != null"); Debug.Assert(function != null, "function != null"); if (object.ReferenceEquals(entry.Functions, EmptyFunctionsList)) { entry.Functions = new ReadOnlyEnumerable <ODataFunction>(); } ReaderUtils.GetSourceListOfEnumerable(entry.Functions, "Functions").Add(function); }
public void AddFunctionShouldWork() { var function = new ODataFunction() { Metadata = new Uri("http://odata.org/metadata"), Target = new Uri("http://odata.org/target"), Title = "TestFunction", }; this.odataEntry.AddFunction(function); var odataFunction = Assert.Single(this.odataEntry.Functions); Assert.Same(function, odataFunction); }
public void CreateODataOperations_CreateOperations(bool followConventions) { // Arrange string expectedTarget = "aa://Target"; Mock <ODataSerializerProvider> serializerProvider = new Mock <ODataSerializerProvider>(); ODataResourceSetSerializer serializer = new ODataResourceSetSerializer(serializerProvider.Object); var builder = new ODataConventionModelBuilder(); builder.EntitySet <FeedCustomer>("Customers"); var function = builder.EntityType <FeedCustomer>().Collection.Function("MyFunction").Returns <int>(); IEdmModel model = builder.GetEdmModel(); IEdmEntitySet customers = model.EntityContainer.FindEntitySet("Customers"); IEdmFunction edmFunction = model.SchemaElements.OfType <IEdmFunction>().First(f => f.Name == "MyFunction"); Func <ResourceSetContext, Uri> functionLinkFactory = a => new Uri(expectedTarget); var operationLinkBuilder = new OperationLinkBuilder(functionLinkFactory, followConventions); model.SetOperationLinkBuilder(edmFunction, operationLinkBuilder); var request = RequestFactory.Create(method: "get", uri: "http://any", opt => opt.AddModel(model)); ResourceSetContext resourceSetContext = new ResourceSetContext { EntitySetBase = customers, Request = request, }; ODataSerializerContext serializerContext = new ODataSerializerContext { NavigationSource = customers, Request = request, Model = model, MetadataLevel = ODataMetadataLevel.Full, }; string expectedMetadataPrefix = "http://any/$metadata"; // Act ODataOperation actualOperation = serializer.CreateODataOperation(edmFunction, resourceSetContext, serializerContext); // Assert Assert.NotNull(actualOperation); string expectedMetadata = expectedMetadataPrefix + "#Default.MyFunction"; ODataOperation expectedFunction = new ODataFunction { Metadata = new Uri(expectedMetadata), Target = new Uri(expectedTarget), Title = "MyFunction" }; AssertEqual(expectedFunction, actualOperation); }
public void CreateODataOperations_CreateOperations(bool followConventions) { // Arrange // Arrange string expectedTarget = "aa://Target"; ODataFeedSerializer serializer = new ODataFeedSerializer(new DefaultODataSerializerProvider()); var builder = new ODataConventionModelBuilder(); builder.EntitySet <FeedCustomer>("Customers"); var function = builder.EntityType <FeedCustomer>().Collection.Function("MyFunction").Returns <int>(); function.HasFeedFunctionLink(a => new Uri(expectedTarget), followConventions); IEdmModel model = builder.GetEdmModel(); IEdmEntitySet customers = model.EntityContainer.FindEntitySet("Customers"); IEdmFunction edmFunction = model.SchemaElements.OfType <IEdmFunction>().First(f => f.Name == "MyFunction"); string expectedMetadataPrefix = "http://Metadata"; UrlHelper url = CreateMetadataLinkFactory(expectedMetadataPrefix); HttpRequestMessage request = new HttpRequestMessage(); FeedContext feedContext = new FeedContext { EntitySetBase = customers, Request = request, Url = url }; ODataSerializerContext serializerContext = new ODataSerializerContext { NavigationSource = customers, Request = request, Model = model, MetadataLevel = ODataMetadataLevel.FullMetadata, Url = url }; // Act ODataOperation actualOperation = serializer.CreateODataOperation(edmFunction, feedContext, serializerContext); // Assert Assert.NotNull(actualOperation); string expectedMetadata = expectedMetadataPrefix + "#Default.MyFunction"; ODataOperation expectedFunction = new ODataFunction { Metadata = new Uri(expectedMetadata), Target = new Uri(expectedTarget), Title = "MyFunction" }; AssertEqual(expectedFunction, actualOperation); }
private static ODataOperation CreateODataOperation(IEdmOperation operation, OperationLinkBuilder builder, ResourceContext resourceContext) { Contract.Assert(operation != null); Contract.Assert(builder != null); Contract.Assert(resourceContext != null); ODataMetadataLevel metadataLevel = resourceContext.SerializerContext.MetadataLevel; IEdmModel model = resourceContext.EdmModel; if (ShouldOmitOperation(operation, builder, metadataLevel)) { return(null); } Uri target = builder.BuildLink(resourceContext); if (target == null) { return(null); } Uri baseUri = new Uri(resourceContext.Url.CreateODataLink(MetadataSegment.Instance)); Uri metadata = new Uri(baseUri, "#" + CreateMetadataFragment(operation)); ODataOperation odataOperation; if (operation is IEdmAction) { odataOperation = new ODataAction(); } else { odataOperation = new ODataFunction(); } odataOperation.Metadata = metadata; // Always omit the title in minimal/no metadata modes. if (metadataLevel == ODataMetadataLevel.FullMetadata) { EmitTitle(model, operation, odataOperation); } // Omit the target in minimal/no metadata modes unless it doesn't follow conventions. if (!builder.FollowsConventions || metadataLevel == ODataMetadataLevel.FullMetadata) { odataOperation.Target = target; } return(odataOperation); }
private IEnumerable <ODataFunction> CreateODataFunctions( IEnumerable <IEdmFunction> functions, EntityInstanceContext entityInstanceContext) { Contract.Assert(functions != null); Contract.Assert(entityInstanceContext != null); foreach (IEdmFunction function in functions) { ODataFunction oDataFunction = CreateODataFunction(function, entityInstanceContext); if (oDataFunction != null) { yield return(oDataFunction); } } }
public MissingOperationGeneratorTests() { this.model = new EdmModel(); this.container = new EdmEntityContainer("Fake", "Container"); this.functionEdmMetadata = new EdmFunction("Fake", "FakeFunction", EdmCoreModel.Instance.GetInt32(false), true /*isBound*/, null, true /*isComposable*/); this.actionEdmMetadata = new EdmAction("Fake", "FakeAction", EdmCoreModel.Instance.GetInt32(false), true/*isBound*/, null /*entitySetPath*/); this.model.AddElement(this.container); this.model.AddElement(this.actionEdmMetadata); this.model.AddElement(this.functionEdmMetadata); this.allOperations = new EdmOperation[] { this.actionEdmMetadata, this.functionEdmMetadata }; this.odataAction = new ODataAction {Metadata = new Uri("http://temp.org/$metadata#Fake.FakeAction")}; this.odataFunction = new ODataFunction {Metadata = new Uri("http://temp.org/$metadata#Fake.FakeFunction")}; }
private IEnumerable <ODataFunction> CreateODataFunctions( IEnumerable <IEdmFunction> functions, ResourceContext resourceContext) { Contract.Assert(functions != null); Contract.Assert(resourceContext != null); foreach (IEdmFunction function in functions) { ODataFunction oDataFunction = CreateODataFunction(function, resourceContext); if (oDataFunction != null) { yield return(oDataFunction); } } }
public void InjectMetadataBuilderShouldSetBuilderOnEntryFunctions() { var entry = new ODataResource(); var builder = new TestEntityMetadataBuilder(entry); var function1 = new ODataFunction { Metadata = new Uri(MetadataDocumentUri, "#function1") }; var function2 = new ODataFunction { Metadata = new Uri(MetadataDocumentUri, "#function2") }; entry.AddFunction(function1); entry.AddFunction(function2); testSubject.InjectMetadataBuilder(entry, builder); function1.GetMetadataBuilder().Should().BeSameAs(builder); function2.GetMetadataBuilder().Should().BeSameAs(builder); }
public void InjectMetadataBuilderShouldNotSetBuilderOnEntryFunctions() { var entry = new ODataEntry(); var builder = new TestEntityMetadataBuilder(entry); var function1 = new ODataFunction { Metadata = new Uri("http://service/$metadata#function1", UriKind.Absolute) }; var function2 = new ODataFunction { Metadata = new Uri("http://service/$metadata#function2", UriKind.Absolute) }; entry.AddFunction(function1); entry.AddFunction(function2); testSubject.InjectMetadataBuilder(entry, builder); function1.GetMetadataBuilder().Should().BeNull(); function2.GetMetadataBuilder().Should().BeNull(); }
public MissingOperationGeneratorTests() { this.model = new EdmModel(); this.container = new EdmEntityContainer("Fake", "Container"); this.functionEdmMetadata = new EdmFunction("Fake", "FakeFunction", EdmCoreModel.Instance.GetInt32(false), true /*isBound*/, null, true /*isComposable*/); this.actionEdmMetadata = new EdmAction("Fake", "FakeAction", EdmCoreModel.Instance.GetInt32(false), true /*isBound*/, null /*entitySetPath*/); this.model.AddElement(this.container); this.model.AddElement(this.actionEdmMetadata); this.model.AddElement(this.functionEdmMetadata); this.allOperations = new EdmOperation[] { this.actionEdmMetadata, this.functionEdmMetadata }; this.odataAction = new ODataAction { Metadata = new Uri("http://temp.org/$metadata#Fake.FakeAction") }; this.odataFunction = new ODataFunction { Metadata = new Uri("http://temp.org/$metadata#Fake.FakeFunction") }; }
public void NoOpMetadataBuilderShouldReturnFunctionsSetByUser() { ODataFunction function = new ODataFunction() { Metadata = new Uri("http://example.com/$metadata#Function"), Target = new Uri("http://example.com/Function"), Title = "FunctionTitle" }; ODataResource entry = new ODataResource(); entry.AddFunction(function); Assert.Single(new NoOpResourceMetadataBuilder(entry).GetFunctions().Where(f => f == function)); // Verify that the Function information wasn't removed or changed. Assert.Equal(new Uri("http://example.com/$metadata#Function"), function.Metadata); Assert.Equal(new Uri("http://example.com/Function"), function.Target); Assert.Equal("FunctionTitle", function.Title); }
public void NoOpMetadataBuilderShouldReturnFunctionsSetByUser() { ODataFunction function = new ODataFunction() { Metadata = new Uri("http://example.com/$metadata#Function"), Target = new Uri("http://example.com/Function"), Title = "FunctionTitle" }; ODataEntry entry = new ODataEntry(); entry.AddFunction(function); new NoOpEntityMetadataBuilder(entry).GetFunctions() .Should().ContainSingle(f => f == function); // Verify that the Function information wasn't removed or changed. function.Metadata.Should().Be(new Uri("http://example.com/$metadata#Function")); function.Target.Should().Be(new Uri("http://example.com/Function")); function.Title.Should().Be("FunctionTitle"); }
internal static ODataCallExpression Call(ODataFunction function, IEnumerable <ODataExpression> arguments) { var argumentsList = (arguments as IReadOnlyList <ODataExpression>) ?? arguments.ToArray(); var signatures = FunctionSignatures[function]; var matches = (from s in signatures let args = s.Arguments.Select((v, i) => new { Value = v, Index = i }) let score = s.Arguments.Count != argumentsList.Count ? default(int?) : args.All(iv => !iv.Value.HasValue || iv.Value.Value == argumentsList[iv.Index].Type || argumentsList[iv.Index].Type == ODataExpressionType.Unknown) ? 0 : args.All(iv => !iv.Value.HasValue || argumentsList[iv.Index].Type.IsImplicityCastableTo(iv.Value.Value) || argumentsList[iv.Index].Type == ODataExpressionType.Unknown) ? 1 : default(int?) where score.HasValue orderby score select new { sig = s, score }) .ToArray(); Throw <ArgumentException> .If(matches.Length == 0, () => string.Format("No version of {0} matched the argument types [{1}]", function, arguments.Select(a => a.Type).ToDelimitedString(", "))); Throw <ArgumentException> .If( matches.Length > 1 && matches[0].score == matches[1].score && argumentsList.All(e => e.Type != ODataExpressionType.Unknown), () => string.Format("Ambiguous match for argument types [{0}] between {1} and {2}", arguments.Select(a => a.Type).ToDelimitedString(", "), matches[0].sig, matches[1].sig) ); var match = matches[0].sig; var castArguments = argumentsList.Select((a, i) => !match.Arguments[i].HasValue || a.Type == match.Arguments[i] ? a : a.Type == ODataExpressionType.Unknown ? ConvertFromUnknownType(a, match.Arguments[i].Value.ToClrType()) : Convert(a, match.Arguments[i].Value.ToClrType())) .ToList() .AsReadOnly(); return(new ODataCallExpression( function, castArguments, match.ReturnType.HasValue ? match.ReturnType.Value.ToClrType() // this case handles cast, whose return type is dynamic depending on its arguments : (Type)((ODataConstantExpression)castArguments[1]).Value )); }
public void PropertySettersNullTest() { Uri metadata = new Uri("http://odata.org/operationMetadata"); string title = "OperationTitle"; Uri target = new Uri("http://odata.org/operationtarget"); ODataAction action = new ODataAction() { Metadata = metadata, Title = title, Target = target, }; action.Metadata = null; action.Title = null; action.Target = null; this.Assert.IsNull(action.Metadata, "Expected null value for property 'Metadata'."); this.Assert.IsNull(action.Title, "Expected null value for property 'Title'."); this.Assert.IsNull(action.Target, "Expected null value for property 'Target'."); ODataFunction function = new ODataFunction() { Metadata = metadata, Title = title, Target = target, }; function.Metadata = null; function.Title = null; function.Target = null; this.Assert.IsNull(function.Metadata, "Expected null value for property 'Metadata'."); this.Assert.IsNull(function.Title, "Expected null value for property 'Title'."); this.Assert.IsNull(function.Target, "Expected null value for property 'Target'."); }
public void ActionAndFunctionTest() { // <m:action Metadata=URI title?="title" target=URI /> Uri actionMetadata = new Uri("http://odata.org/test/$metadata#defaultAction"); Uri actionMetadata2 = new Uri("#action escaped relative metadata", UriKind.Relative); Uri actionMetadata3 = new Uri("../#action escaped relative metadata", UriKind.Relative); string actionTitle = "Default Action"; Uri actionTarget = new Uri("http://odata.org/defaultActionTarget"); Uri actionTarget2 = new Uri("http://odata.org/defaultActionTarget2"); ODataAction action_r1_t1 = new ODataAction() { Metadata = actionMetadata, Title = actionTitle, Target = actionTarget }; ODataAction action_r1_t2 = new ODataAction() { Metadata = actionMetadata, Title = actionTitle, Target = actionTarget2 }; ODataAction action_r2_t1 = new ODataAction() { Metadata = actionMetadata2, Title = actionTitle, Target = actionTarget }; ODataAction action_r3_t1 = new ODataAction() { Metadata = actionMetadata3, Title = actionTitle, Target = actionTarget }; Uri functionMetadata = new Uri("http://odata.org/test/$metadata#defaultFunction"); Uri functionMetadata2 = new Uri("#function escaped relative metadata", UriKind.Relative); Uri functionMetadata3 = new Uri("\\#function escaped relative metadata", UriKind.Relative); string functionTitle = "Default Function"; Uri functionTarget = new Uri("http://odata.org/defaultFunctionTarget"); Uri functionTarget2 = new Uri("http://odata.org/defaultFunctionTarget2"); ODataFunction function_r1_t1 = new ODataFunction() { Metadata = functionMetadata, Title = functionTitle, Target = functionTarget }; ODataFunction function_r1_t2 = new ODataFunction() { Metadata = functionMetadata, Title = functionTitle, Target = functionTarget2 }; ODataFunction function_r2_t1 = new ODataFunction() { Metadata = functionMetadata2, Title = functionTitle, Target = functionTarget }; ODataFunction function_r3_t1 = new ODataFunction() { Metadata = functionMetadata3, Title = functionTitle, Target = functionTarget }; var actionCases = new[] { new { ODataActions = new ODataAction[] { action_r1_t1 }, Atom = GetAtom(action_r1_t1), JsonLight = GetJsonLightForRelGroup(action_r1_t1), }, new { ODataActions = new ODataAction[] { action_r1_t1, action_r1_t2 }, Atom = GetAtom(action_r1_t1) + GetAtom(action_r1_t2), JsonLight = GetJsonLightForRelGroup(action_r1_t1, action_r1_t2), }, new { ODataActions = new ODataAction[] { action_r1_t1, action_r2_t1 }, Atom = GetAtom(action_r1_t1) + GetAtom(action_r2_t1), JsonLight = GetJsonLightForRelGroup(action_r1_t1) + "," + GetJsonLightForRelGroup(action_r2_t1), }, new { ODataActions = new ODataAction[] { action_r1_t1, action_r2_t1, action_r1_t2 }, Atom = GetAtom(action_r1_t1) + GetAtom(action_r2_t1) + GetAtom(action_r1_t2), JsonLight = GetJsonLightForRelGroup(action_r1_t1, action_r1_t2) + "," + GetJsonLightForRelGroup(action_r2_t1), }, new { ODataActions = new ODataAction[] { action_r3_t1 }, Atom = GetAtom(action_r3_t1), JsonLight = GetJsonLightForRelGroup(action_r3_t1), }, }; var functionCases = new[] { new { ODataFunctions = new ODataFunction[] { function_r1_t1 }, Atom = GetAtom(function_r1_t1), JsonLight = GetJsonLightForRelGroup(function_r1_t1), }, new { ODataFunctions = new ODataFunction[] { function_r1_t1, function_r1_t2 }, Atom = GetAtom(function_r1_t1) + GetAtom(function_r1_t2), JsonLight = GetJsonLightForRelGroup(function_r1_t1, function_r1_t2), }, new { ODataFunctions = new ODataFunction[] { function_r1_t1, function_r2_t1 }, Atom = GetAtom(function_r1_t1) + GetAtom(function_r2_t1), JsonLight = GetJsonLightForRelGroup(function_r1_t1) + "," + GetJsonLightForRelGroup(function_r2_t1), }, new { ODataFunctions = new ODataFunction[] { function_r1_t1, function_r2_t1, function_r1_t2 }, Atom = GetAtom(function_r1_t1) + GetAtom(function_r2_t1) + GetAtom(function_r1_t2), JsonLight = GetJsonLightForRelGroup(function_r1_t1, function_r1_t2) + "," + GetJsonLightForRelGroup(function_r2_t1), }, new { ODataFunctions = new ODataFunction[] { function_r3_t1 }, Atom = GetAtom(function_r3_t1), JsonLight = GetJsonLightForRelGroup(function_r3_t1), }, }; var queryResults = from actionCase in actionCases from functionCase in functionCases select new { actionCase.ODataActions, functionCase.ODataFunctions, Atom = string.Concat(actionCase.Atom, functionCase.Atom), JsonLight = string.Join(",", new[] { actionCase.JsonLight, functionCase.JsonLight }.Where(x => x != null)) }; EdmModel model = new EdmModel(); EdmEntityType edmEntityTypeCustomer = model.EntityType("Customer", "TestModel"); EdmEntityContainer edmEntityContainer = model.EntityContainer("DefaultContainer","TestModel" ); EdmEntitySet edmEntitySetCustermors = model.EntitySet("Customers", edmEntityTypeCustomer); var testDescriptors = queryResults.Select(testCase => { ODataEntry entry = ObjectModelUtils.CreateDefaultEntry("TestModel.Customer"); if (testCase.ODataActions != null) { foreach (var action in testCase.ODataActions) { entry.AddAction(action); } } if (testCase.ODataFunctions != null) { foreach (var function in testCase.ODataFunctions) { entry.AddFunction(function); } } return new PayloadWriterTestDescriptor<ODataItem>( this.Settings, entry, (testConfiguration) => { if (testConfiguration.Format == ODataFormat.Atom) { return new AtomWriterTestExpectedResults(this.Settings.ExpectedResultSettings) { Xml = "<ODataOperations>" + testCase.Atom + "</ODataOperations>", ExpectedException2 = entry.Actions != null && entry.Actions.Contains(null) ? ODataExpectedExceptions.ODataException("ValidationUtils_EnumerableContainsANullItem", "ODataEntry.Actions") : testConfiguration.IsRequest && entry.Actions != null && entry.Actions.Any() ? ODataExpectedExceptions.ODataException("WriterValidationUtils_OperationInRequest", GetFirstOperationMetadata(entry)) : entry.Functions != null && entry.Functions.Contains(null) ? ODataExpectedExceptions.ODataException("ValidationUtils_EnumerableContainsANullItem", "ODataEntry.Functions") : testConfiguration.IsRequest && entry.Functions != null && entry.Functions.Any() ? ODataExpectedExceptions.ODataException("WriterValidationUtils_OperationInRequest", GetFirstOperationMetadata(entry)) : null, FragmentExtractor = (result) => { var actions = result.Elements(TestAtomConstants.ODataMetadataXNamespace + "action"); var functions = result.Elements(TestAtomConstants.ODataMetadataXNamespace + "function"); result = new XElement("ODataOperations", actions, functions); if (result.FirstNode == null) { result.Add(string.Empty); } return result; } }; } else if (testConfiguration.Format == ODataFormat.Json) { return new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings) { Json = string.Join( "$(NL)", "{", testCase.JsonLight, "}"), ExpectedException2 = entry.Actions != null && entry.Actions.Contains(null) ? ODataExpectedExceptions.ODataException("ValidationUtils_EnumerableContainsANullItem", "ODataEntry.Actions") : testConfiguration.IsRequest && entry.Actions != null && entry.Actions.Any() ? ODataExpectedExceptions.ODataException("WriterValidationUtils_OperationInRequest", GetFirstOperationMetadata(entry)) : entry.Actions != null && entry.Actions.Any(a => !a.Metadata.IsAbsoluteUri && !a.Metadata.OriginalString.StartsWith("#")) ? ODataExpectedExceptions.ODataException("ValidationUtils_InvalidMetadataReferenceProperty", entry.Actions.First(a => a.Metadata.OriginalString.Contains(" ")).Metadata.OriginalString) : entry.Functions != null && entry.Functions.Contains(null) ? ODataExpectedExceptions.ODataException("ValidationUtils_EnumerableContainsANullItem", "ODataEntry.Functions") : testConfiguration.IsRequest && entry.Functions != null && entry.Functions.Any() ? ODataExpectedExceptions.ODataException("WriterValidationUtils_OperationInRequest", GetFirstOperationMetadata(entry)) : entry.Functions != null && entry.Functions.Any(f => !f.Metadata.IsAbsoluteUri && !f.Metadata.OriginalString.StartsWith("#")) ? ODataExpectedExceptions.ODataException("ValidationUtils_InvalidMetadataReferenceProperty", entry.Functions.First(f => f.Metadata.OriginalString.Contains(" ")).Metadata.OriginalString) : null, FragmentExtractor = (result) => { var actionsAndFunctions = result.Object().Properties.Where(p => p.Name.Contains("#")).ToList(); var jsonResult = new JsonObject(); actionsAndFunctions.ForEach(p => { // NOTE we remove all annotations here and in particular the text annotations to be able to easily compare // against the expected results. This however means that we do not distinguish between the indented and non-indented case here. p.RemoveAllAnnotations(true); jsonResult.Add(p); }); return jsonResult; } }; } else { string formatName = testConfiguration.Format == null ? "null" : testConfiguration.Format.GetType().Name; throw new NotSupportedException("Invalid format detected: " + formatName); } }); }); this.CombinatorialEngineProvider.RunCombinations( testDescriptors.PayloadCases(WriterPayloads.EntryPayloads), this.WriterTestConfigurationProvider.ExplicitFormatConfigurationsWithIndent, (testDescriptor, testConfiguration) => { testConfiguration = testConfiguration.Clone(); testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri); if (testConfiguration.Format == ODataFormat.Json) { if (testDescriptor.IsGeneratedPayload) { return; } // We need a model, entity set and entity type for JSON Light testDescriptor = new PayloadWriterTestDescriptor<ODataItem>(testDescriptor) { Model = model, PayloadEdmElementContainer = edmEntitySetCustermors, PayloadEdmElementType = edmEntityTypeCustomer, }; } TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor, testConfiguration, this.Assert, this.Logger); }); }
public void CreateODataOperations_CreateOperations(bool followConventions) { // Arrange // Arrange string expectedTarget = "aa://Target"; ODataFeedSerializer serializer = new ODataFeedSerializer(new DefaultODataSerializerProvider()); var builder = new ODataConventionModelBuilder(); builder.EntitySet<FeedCustomer>("Customers"); var function = builder.EntityType<FeedCustomer>().Collection.Function("MyFunction").Returns<int>(); function.HasFeedFunctionLink(a => new Uri(expectedTarget), followConventions); IEdmModel model = builder.GetEdmModel(); IEdmEntitySet customers = model.EntityContainer.FindEntitySet("Customers"); IEdmFunction edmFunction = model.SchemaElements.OfType<IEdmFunction>().First(f => f.Name == "MyFunction"); string expectedMetadataPrefix = "http://Metadata"; UrlHelper url = CreateMetadataLinkFactory(expectedMetadataPrefix); HttpRequestMessage request = new HttpRequestMessage(); FeedContext feedContext = new FeedContext { EntitySetBase = customers, Request = request, Url = url }; ODataSerializerContext serializerContext = new ODataSerializerContext { NavigationSource = customers, Request = request, Model = model, MetadataLevel = ODataMetadataLevel.FullMetadata, Url = url }; // Act ODataOperation actualOperation = serializer.CreateODataOperation(edmFunction, feedContext, serializerContext); // Assert Assert.NotNull(actualOperation); string expectedMetadata = expectedMetadataPrefix + "#Default.MyFunction"; ODataOperation expectedFunction = new ODataFunction { Metadata = new Uri(expectedMetadata), Target = new Uri(expectedTarget), Title = "MyFunction" }; AssertEqual(expectedFunction, actualOperation); }
private static ODataOperation CreateODataOperation(IEdmOperation operation, ProcedureLinkBuilder builder, EntityInstanceContext entityInstanceContext) { Contract.Assert(operation != null); Contract.Assert(builder != null); Contract.Assert(entityInstanceContext != null); ODataMetadataLevel metadataLevel = entityInstanceContext.SerializerContext.MetadataLevel; IEdmModel model = entityInstanceContext.EdmModel; if (ShouldOmitOperation(operation, builder, metadataLevel)) { return null; } Uri target = builder.BuildLink(entityInstanceContext); if (target == null) { return null; } Uri baseUri = new Uri(entityInstanceContext.Url.CreateODataLink(new MetadataPathSegment())); Uri metadata = new Uri(baseUri, "#" + CreateMetadataFragment(operation)); ODataOperation odataOperation; if (operation is IEdmAction) { odataOperation = new ODataAction(); } else { odataOperation = new ODataFunction(); } odataOperation.Metadata = metadata; // Always omit the title in minimal/no metadata modes. if (metadataLevel == ODataMetadataLevel.FullMetadata) { EmitTitle(model, operation, odataOperation); } // Omit the target in minimal/no metadata modes unless it doesn't follow conventions. if (!builder.FollowsConventions || metadataLevel == ODataMetadataLevel.FullMetadata) { odataOperation.Target = target; } return odataOperation; }
private void ReadOperationsMetadata(ODataEntry entry, bool isActions) { string str = isActions ? "actions" : "functions"; if (base.JsonReader.NodeType != JsonNodeType.StartObject) { throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonEntryAndFeedDeserializer_PropertyInEntryMustHaveObjectValue(str, base.JsonReader.NodeType)); } base.JsonReader.ReadStartObject(); HashSet<string> set = new HashSet<string>(StringComparer.Ordinal); while (base.JsonReader.NodeType == JsonNodeType.Property) { ODataOperation operation; string item = base.JsonReader.ReadPropertyName(); if (set.Contains(item)) { throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonEntryAndFeedDeserializer_RepeatMetadataValue(str, item)); } set.Add(item); if (base.JsonReader.NodeType != JsonNodeType.StartArray) { throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonEntryAndFeedDeserializer_MetadataMustHaveArrayValue(str, base.JsonReader.NodeType)); } base.JsonReader.ReadStartArray(); if (base.JsonReader.NodeType == JsonNodeType.StartObject) { goto Label_0227; } throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonEntryAndFeedDeserializer_OperationMetadataArrayExpectedAnObject(str, base.JsonReader.NodeType)); Label_00E1: base.JsonReader.ReadStartObject(); if (isActions) { operation = new ODataAction(); ReaderUtils.AddActionToEntry(entry, (ODataAction) operation); } else { operation = new ODataFunction(); ReaderUtils.AddFunctionToEntry(entry, (ODataFunction) operation); } operation.Metadata = base.ResolveUri(item); while (base.JsonReader.NodeType == JsonNodeType.Property) { string str3 = base.JsonReader.ReadPropertyName(); string str6 = str3; if (str6 == null) { goto Label_01E5; } if (!(str6 == "title")) { if (str6 == "target") { goto Label_019D; } goto Label_01E5; } if (operation.Title != null) { throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonEntryAndFeedDeserializer_MultipleOptionalPropertiesInOperation(str3, item, str)); } string propertyValue = base.JsonReader.ReadStringValue("title"); ODataJsonReaderUtils.ValidateOperationJsonProperty(propertyValue, str3, item, str); operation.Title = propertyValue; continue; Label_019D: if (operation.Target != null) { throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonEntryAndFeedDeserializer_MultipleTargetPropertiesInOperation(item, str)); } string str5 = base.JsonReader.ReadStringValue("target"); ODataJsonReaderUtils.ValidateOperationJsonProperty(str5, str3, item, str); operation.Target = base.ProcessUriFromPayload(str5); continue; Label_01E5: base.JsonReader.SkipValue(); } if (operation.Target == null) { throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonEntryAndFeedDeserializer_OperationMissingTargetProperty(item, str)); } base.JsonReader.ReadEndObject(); Label_0227: if (base.JsonReader.NodeType == JsonNodeType.StartObject) { goto Label_00E1; } base.JsonReader.ReadEndArray(); } base.JsonReader.ReadEndObject(); }
/// <summary> /// Reads a an m:action or m:function in atom:entry. /// </summary> /// <param name="entryState">The reader entry state for the entry being read.</param> /// <returns>true, if the m:action or m:function was read succesfully, false otherwise.</returns> /// <remarks> /// Pre-Condition: XmlNodeType.Element m:action|m:function - The m:action or m:function element to read. /// Post-Condition: Any - The node after the m:action or m:function element if it was read by this method. /// XmlNodeType.Element m:action|m:function - The m:action or m:function element to read if it was not read by this method. /// </remarks> private bool TryReadOperation(IODataAtomReaderEntryState entryState) { Debug.Assert(entryState != null, "entryState != null"); this.XmlReader.AssertNotBuffering(); this.AssertXmlCondition(XmlNodeType.Element); Debug.Assert( this.XmlReader.NamespaceURI == AtomConstants.ODataMetadataNamespace, "The XML reader must be on a metadata (m:*) element for this method to work."); bool isAction = false; if (this.XmlReader.LocalNameEquals(this.ODataActionElementName)) { // m:action isAction = true; } else if (!this.XmlReader.LocalNameEquals(this.ODataFunctionElementName)) { // not an m:function either return false; } ODataOperation operation; if (isAction) { operation = new ODataAction(); entryState.Entry.AddAction((ODataAction)operation); } else { operation = new ODataFunction(); entryState.Entry.AddFunction((ODataFunction)operation); } string operationName = this.XmlReader.LocalName; // for error reporting while (this.XmlReader.MoveToNextAttribute()) { if (this.XmlReader.NamespaceEquals(this.EmptyNamespace)) { string attributeValue = this.XmlReader.Value; if (this.XmlReader.LocalNameEquals(this.ODataOperationMetadataAttribute)) { // For metadata, if the URI is relative we don't attempt to make it absolute using the service // base URI, because the ODataOperation metadata URI is relative to $metadata. operation.Metadata = this.ProcessUriFromPayload(attributeValue, this.XmlReader.XmlBaseUri, /*makeAbsolute*/ false); } else if (this.XmlReader.LocalNameEquals(this.ODataOperationTargetAttribute)) { operation.Target = this.ProcessUriFromPayload(attributeValue, this.XmlReader.XmlBaseUri); } else if (this.XmlReader.LocalNameEquals(this.ODataOperationTitleAttribute)) { operation.Title = this.XmlReader.Value; } // skip unknown attributes } } if (operation.Metadata == null) { throw new ODataException(ODataErrorStrings.ODataAtomEntryAndFeedDeserializer_OperationMissingMetadataAttribute(operationName)); } if (operation.Target == null) { throw new ODataException(ODataErrorStrings.ODataAtomEntryAndFeedDeserializer_OperationMissingTargetAttribute(operationName)); } // skip the content of m:action/m:function this.XmlReader.Skip(); return true; }
/// <summary> /// Adds an ODataFunction to the end of the payload order items. /// </summary> /// <param name="function">The function.</param> public void AddFunction(ODataFunction function) { this.AddItem("Function_" + function.Metadata.OriginalString); }
/// <summary> /// Visits an item in the object model. /// </summary> /// <param name="objectModelItem">The item to visit.</param> public virtual T Visit(object objectModelItem) { ODataResourceSet feed = objectModelItem as ODataResourceSet; if (feed != null) { return(this.VisitFeed(feed)); } ODataResource entry = objectModelItem as ODataResource; if (entry != null) { return(this.VisitEntry(entry)); } ODataProperty property = objectModelItem as ODataProperty; if (property != null) { return(this.VisitProperty(property)); } ODataNestedResourceInfo navigationLink = objectModelItem as ODataNestedResourceInfo; if (navigationLink != null) { return(this.VisitNavigationLink(navigationLink)); } ODataResourceValue resourceValue = objectModelItem as ODataResourceValue; if (resourceValue != null) { return(this.VisitResourceValue(resourceValue)); } ODataCollectionValue collection = objectModelItem as ODataCollectionValue; if (collection != null) { return(this.VisitCollectionValue(collection)); } ODataStreamReferenceValue streamReferenceValue = objectModelItem as ODataStreamReferenceValue; if (streamReferenceValue != null) { return(this.VisitStreamReferenceValue(streamReferenceValue)); } ODataCollectionStart collectionStart = objectModelItem as ODataCollectionStart; if (collectionStart != null) { return(this.VisitCollectionStart(collectionStart)); } ODataServiceDocument serviceDocument = objectModelItem as ODataServiceDocument; if (serviceDocument != null) { return(this.VisitWorkspace(serviceDocument)); } ODataEntitySetInfo entitySetInfo = objectModelItem as ODataEntitySetInfo; if (entitySetInfo != null) { return(this.VisitResourceCollection(entitySetInfo)); } ODataError error = objectModelItem as ODataError; if (error != null) { return(this.VisitError(error)); } ODataInnerError innerError = objectModelItem as ODataInnerError; if (innerError != null) { return(this.VisitInnerError(innerError)); } ODataEntityReferenceLinks entityReferenceLinks = objectModelItem as ODataEntityReferenceLinks; if (entityReferenceLinks != null) { return(this.VisitEntityReferenceLinks(entityReferenceLinks)); } ODataEntityReferenceLink entityReferenceLink = objectModelItem as ODataEntityReferenceLink; if (entityReferenceLink != null) { return(this.VisitEntityReferenceLink(entityReferenceLink)); } ODataAction action = objectModelItem as ODataAction; if (action != null) { return(this.VisitODataOperation(action)); } ODataFunction function = objectModelItem as ODataFunction; if (function != null) { return(this.VisitODataOperation(function)); } ODataParameters parameters = objectModelItem as ODataParameters; if (parameters != null) { return(this.VisitParameters(parameters)); } ODataBatch batch = objectModelItem as ODataBatch; if (batch != null) { return(this.VisitBatch(batch)); } if (objectModelItem == null || objectModelItem is ODataPrimitiveValue || objectModelItem.GetType().IsValueType || objectModelItem is string || objectModelItem is byte[] || objectModelItem is ISpatial) { return(this.VisitPrimitiveValue(objectModelItem)); } if (objectModelItem is ODataUntypedValue) { object val = ODataObjectModelVisitor.ParseJsonToPrimitiveValue( (objectModelItem as ODataUntypedValue).RawValue); return(this.VisitPrimitiveValue(val)); } return(this.VisitUnsupportedValue(objectModelItem)); }
public virtual ODataOperation CreateODataOperation(IEdmOperation operation, FeedContext feedContext, ODataSerializerContext writeContext) { if (operation == null) { throw Error.ArgumentNull("operation"); } if (feedContext == null) { throw Error.ArgumentNull("feedContext"); } if (writeContext == null) { throw Error.ArgumentNull("writeContext"); } ODataMetadataLevel metadataLevel = writeContext.MetadataLevel; IEdmModel model = writeContext.Model; if (metadataLevel != ODataMetadataLevel.FullMetadata) { return null; } ProcedureLinkBuilder builder; IEdmAction action = operation as IEdmAction; if (action != null) { builder = model.GetActionLinkBuilder(action); } else { builder = model.GetFunctionLinkBuilder((IEdmFunction)operation); } if (builder == null) { return null; } Uri target = builder.BuildLink(feedContext); if (target == null) { return null; } Uri baseUri = new Uri(writeContext.Url.CreateODataLink(new MetadataPathSegment())); Uri metadata = new Uri(baseUri, "#" + operation.FullName()); ODataOperation odataOperation; if (action != null) { odataOperation = new ODataAction(); } else { odataOperation = new ODataFunction(); } odataOperation.Metadata = metadata; // Always omit the title in minimal/no metadata modes. ODataEntityTypeSerializer.EmitTitle(model, operation, odataOperation); // Omit the target in minimal/no metadata modes unless it doesn't follow conventions. if (metadataLevel == ODataMetadataLevel.FullMetadata || !builder.FollowsConventions) { odataOperation.Target = target; } return odataOperation; }
public void ActionAndFunctionPayloadOrderTest() { EdmModel model = new EdmModel(); var container = new EdmEntityContainer("TestModel", "TestContainer"); model.AddElement(container); var otherType = new EdmEntityType("TestModel", "OtherType"); otherType.AddKeys(otherType.AddStructuralProperty("ID", EdmCoreModel.Instance.GetInt32(false))); model.AddElement(otherType); container.AddEntitySet("OtherType", otherType); var nonMLEBaseType = new EdmEntityType("TestModel", "NonMLEBaseType"); nonMLEBaseType.AddKeys(nonMLEBaseType.AddStructuralProperty("ID", EdmCoreModel.Instance.GetInt32(false))); model.AddElement(nonMLEBaseType); var nonMLESet = container.AddEntitySet("NonMLESet", nonMLEBaseType); var nonMLEType = new EdmEntityType("TestModel", "NonMLEType", nonMLEBaseType); nonMLEType.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(true)); nonMLEType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo { Name = "NavProp", Target = otherType, TargetMultiplicity = EdmMultiplicity.Many }); model.AddElement(nonMLEType); container.AddEntitySet("NonMLEType", nonMLEType); ODataAction action = new ODataAction { Metadata = new Uri("http://odata.org/test/$metadata#defaultAction"), Title = "Default Action", Target = new Uri("http://www.odata.org/defaultAction"), }; ODataFunction function = new ODataFunction { Metadata = new Uri("http://odata.org/test/$metadata#defaultFunction()"), Title = "Default Function", Target = new Uri("defaultFunctionTarget", UriKind.Relative) }; string defaultJson = string.Join("$(NL)", "{{", "{1}" + "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"#TestModel.NonMLEType\"{0},\"#defaultAction\":{{", "\"title\":\"Default Action\",\"target\":\"http://www.odata.org/defaultAction\"", "}},\"#defaultFunction()\":{{", "\"title\":\"Default Function\",\"target\":\"defaultFunctionTarget\"", "}}", "}}"); var entryWithActionAndFunction = new ODataEntry() { TypeName = "TestModel.NonMLEType", }; entryWithActionAndFunction.AddAction(action); entryWithActionAndFunction.AddFunction(function); IEnumerable<EntryPayloadTestCase> testCases = new[] { new EntryPayloadTestCase { DebugDescription = "Functions and actions available at the beginning.", Entry = entryWithActionAndFunction, Model = model, EntitySet = nonMLESet, Json = defaultJson }, }; IEnumerable<PayloadWriterTestDescriptor<ODataItem>> testDescriptors = testCases.Select(testCase => new PayloadWriterTestDescriptor<ODataItem>( this.Settings, new ODataItem[] { testCase.Entry }, tc => new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings) { Json = string.Format(CultureInfo.InvariantCulture, testCase.Json, string.Empty, tc.IsRequest ? string.Empty : (JsonLightWriterUtils.GetMetadataUrlPropertyForEntry(testCase.EntitySet.Name) + ",")), FragmentExtractor = (result) => result.RemoveAllAnnotations(true) }) { DebugDescription = testCase.DebugDescription, Model = testCase.Model, PayloadEdmElementContainer = testCase.EntitySet, PayloadEdmElementType = testCase.EntityType, SkipTestConfiguration = testCase.SkipTestConfiguration }); testDescriptors = testDescriptors.Concat(testCases.Select(testCase => new PayloadWriterTestDescriptor<ODataItem>( this.Settings, new ODataItem[] { testCase.Entry, new ODataNavigationLink { Name = "NavProp", IsCollection = true, Url = new Uri("http://odata.org/navprop/uri") }}, tc => new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings) { Json = string.Format(CultureInfo.InvariantCulture, testCase.Json, tc.IsRequest ? ",\"NavProp\":[$(NL){$(NL)\"__metadata\":{$(NL)\"uri\":\"http://odata.org/navprop/uri\"$(NL)}$(NL)}$(NL)]" : ",\"" + JsonLightUtils.GetPropertyAnnotationName("NavProp", JsonLightConstants.ODataNavigationLinkUrlAnnotationName) + "\":\"http://odata.org/navprop/uri\"", tc.IsRequest ? string.Empty : (JsonLightWriterUtils.GetMetadataUrlPropertyForEntry(testCase.EntitySet.Name) + ",")), FragmentExtractor = (result) => result.RemoveAllAnnotations(true) }) { DebugDescription = testCase.DebugDescription + "- with navigation property", Model = testCase.Model, PayloadEdmElementContainer = testCase.EntitySet, PayloadEdmElementType = testCase.EntityType, SkipTestConfiguration = testCase.SkipTestConfiguration })); this.CombinatorialEngineProvider.RunCombinations( testDescriptors, // Actions/functions are only supported in responses. this.WriterTestConfigurationProvider.JsonLightFormatConfigurationsWithIndent.Where(tc => !tc.IsRequest), (testDescriptor, testConfiguration) => { TestWriterUtils.WriteAndVerifyODataEdmPayload(testDescriptor.DeferredLinksToEntityReferenceLinksInRequest(testConfiguration), testConfiguration, this.Assert, this.Logger); }); }
public void CreateODataFunction_IncludesEverything_ForFullMetadata() { // Arrange string expectedTarget = "aa://Target"; string expectedMetadataPrefix = "http://Metadata"; IEdmTypeReference returnType = EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Boolean, isNullable: false); IEdmFunction function = new EdmFunction("NS", "Function", returnType, isBound: true, entitySetPathExpression: null, isComposable: false); FunctionLinkBuilder linkBuilder = new FunctionLinkBuilder((EntityInstanceContext a) => new Uri(expectedTarget), followsConventions: false); IEdmDirectValueAnnotationsManager annotationsManager = CreateFakeAnnotationsManager(); annotationsManager.SetFunctionLinkBuilder(function, linkBuilder); annotationsManager.SetIsAlwaysBindable(function); IEdmModel model = CreateFakeModel(annotationsManager); UrlHelper url = CreateMetadataLinkFactory(expectedMetadataPrefix); EntityInstanceContext context = CreateContext(model, url); context.SerializerContext.MetadataLevel = ODataMetadataLevel.FullMetadata; // Act ODataFunction actualFunction = _serializer.CreateODataFunction(function, context); // Assert string expectedMetadata = expectedMetadataPrefix + "#NS.Function"; ODataFunction expectedFunction = new ODataFunction { Metadata = new Uri(expectedMetadata), Target = new Uri(expectedTarget), Title = "Function" }; AssertEqual(actualFunction, actualFunction); }
public void InjectMetadataBuilderShouldSetBuilderOnEntryFunctions() { var entry = new ODataEntry(); var builder = new TestEntityMetadataBuilder(entry); var function1 = new ODataFunction { Metadata = new Uri(MetadataDocumentUri, "#function1") }; var function2 = new ODataFunction { Metadata = new Uri(MetadataDocumentUri, "#function2") }; entry.AddFunction(function1); entry.AddFunction(function2); testSubject.InjectMetadataBuilder(entry, builder); function1.GetMetadataBuilder().Should().BeSameAs(builder); function2.GetMetadataBuilder().Should().BeSameAs(builder); }
public static string ToODataString(this ODataFunction @this) { return(@this.ToString().ToLowerInvariant()); }
public void ActionAndFunctionTest() { // <m:action Metadata=URI title?="title" target=URI /> Uri actionMetadata = new Uri("http://odata.org/test/$metadata#defaultAction"); Uri actionMetadata2 = new Uri("#action escaped relative metadata", UriKind.Relative); Uri actionMetadata3 = new Uri("../#action escaped relative metadata", UriKind.Relative); string actionTitle = "Default Action"; Uri actionTarget = new Uri("http://odata.org/defaultActionTarget"); Uri actionTarget2 = new Uri("http://odata.org/defaultActionTarget2"); ODataAction action_r1_t1 = new ODataAction() { Metadata = actionMetadata, Title = actionTitle, Target = actionTarget }; ODataAction action_r1_t2 = new ODataAction() { Metadata = actionMetadata, Title = actionTitle, Target = actionTarget2 }; ODataAction action_r2_t1 = new ODataAction() { Metadata = actionMetadata2, Title = actionTitle, Target = actionTarget }; ODataAction action_r3_t1 = new ODataAction() { Metadata = actionMetadata3, Title = actionTitle, Target = actionTarget }; Uri functionMetadata = new Uri("http://odata.org/test/$metadata#defaultFunction"); Uri functionMetadata2 = new Uri("#function escaped relative metadata", UriKind.Relative); Uri functionMetadata3 = new Uri("\\#function escaped relative metadata", UriKind.Relative); string functionTitle = "Default Function"; Uri functionTarget = new Uri("http://odata.org/defaultFunctionTarget"); Uri functionTarget2 = new Uri("http://odata.org/defaultFunctionTarget2"); ODataFunction function_r1_t1 = new ODataFunction() { Metadata = functionMetadata, Title = functionTitle, Target = functionTarget }; ODataFunction function_r1_t2 = new ODataFunction() { Metadata = functionMetadata, Title = functionTitle, Target = functionTarget2 }; ODataFunction function_r2_t1 = new ODataFunction() { Metadata = functionMetadata2, Title = functionTitle, Target = functionTarget }; ODataFunction function_r3_t1 = new ODataFunction() { Metadata = functionMetadata3, Title = functionTitle, Target = functionTarget }; var actionCases = new[] { new { ODataActions = new ODataAction[] { action_r1_t1 }, Atom = GetAtom(action_r1_t1), JsonLight = GetJsonLightForRelGroup(action_r1_t1), }, new { ODataActions = new ODataAction[] { action_r1_t1, action_r1_t2 }, Atom = GetAtom(action_r1_t1) + GetAtom(action_r1_t2), JsonLight = GetJsonLightForRelGroup(action_r1_t1, action_r1_t2), }, new { ODataActions = new ODataAction[] { action_r1_t1, action_r2_t1 }, Atom = GetAtom(action_r1_t1) + GetAtom(action_r2_t1), JsonLight = GetJsonLightForRelGroup(action_r1_t1) + "," + GetJsonLightForRelGroup(action_r2_t1), }, new { ODataActions = new ODataAction[] { action_r1_t1, action_r2_t1, action_r1_t2 }, Atom = GetAtom(action_r1_t1) + GetAtom(action_r2_t1) + GetAtom(action_r1_t2), JsonLight = GetJsonLightForRelGroup(action_r1_t1, action_r1_t2) + "," + GetJsonLightForRelGroup(action_r2_t1), }, new { ODataActions = new ODataAction[] { action_r3_t1 }, Atom = GetAtom(action_r3_t1), JsonLight = GetJsonLightForRelGroup(action_r3_t1), }, }; var functionCases = new[] { new { ODataFunctions = new ODataFunction[] { function_r1_t1 }, Atom = GetAtom(function_r1_t1), JsonLight = GetJsonLightForRelGroup(function_r1_t1), }, new { ODataFunctions = new ODataFunction[] { function_r1_t1, function_r1_t2 }, Atom = GetAtom(function_r1_t1) + GetAtom(function_r1_t2), JsonLight = GetJsonLightForRelGroup(function_r1_t1, function_r1_t2), }, new { ODataFunctions = new ODataFunction[] { function_r1_t1, function_r2_t1 }, Atom = GetAtom(function_r1_t1) + GetAtom(function_r2_t1), JsonLight = GetJsonLightForRelGroup(function_r1_t1) + "," + GetJsonLightForRelGroup(function_r2_t1), }, new { ODataFunctions = new ODataFunction[] { function_r1_t1, function_r2_t1, function_r1_t2 }, Atom = GetAtom(function_r1_t1) + GetAtom(function_r2_t1) + GetAtom(function_r1_t2), JsonLight = GetJsonLightForRelGroup(function_r1_t1, function_r1_t2) + "," + GetJsonLightForRelGroup(function_r2_t1), }, new { ODataFunctions = new ODataFunction[] { function_r3_t1 }, Atom = GetAtom(function_r3_t1), JsonLight = GetJsonLightForRelGroup(function_r3_t1), }, }; var queryResults = from actionCase in actionCases from functionCase in functionCases select new { actionCase.ODataActions, functionCase.ODataFunctions, Atom = string.Concat(actionCase.Atom, functionCase.Atom), JsonLight = string.Join(",", new[] { actionCase.JsonLight, functionCase.JsonLight }.Where(x => x != null)) }; EdmModel model = new EdmModel(); EdmEntityType edmEntityTypeCustomer = model.EntityType("Customer", "TestModel"); EdmEntityContainer edmEntityContainer = model.EntityContainer("DefaultContainer", "TestModel"); EdmEntitySet edmEntitySetCustermors = model.EntitySet("Customers", edmEntityTypeCustomer); var testDescriptors = queryResults.Select(testCase => { ODataResource entry = ObjectModelUtils.CreateDefaultEntry("TestModel.Customer"); if (testCase.ODataActions != null) { foreach (var action in testCase.ODataActions) { entry.AddAction(action); } } if (testCase.ODataFunctions != null) { foreach (var function in testCase.ODataFunctions) { entry.AddFunction(function); } } return(new PayloadWriterTestDescriptor <ODataItem>( this.Settings, entry, (testConfiguration) => { if (testConfiguration.Format == ODataFormat.Json) { return new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings) { Json = string.Join( "$(NL)", "{", testCase.JsonLight, "}"), ExpectedException2 = entry.Actions != null && entry.Actions.Contains(null) ? ODataExpectedExceptions.ODataException("ValidationUtils_EnumerableContainsANullItem", "ODataResource.Actions") : testConfiguration.IsRequest && entry.Actions != null && entry.Actions.Any() ? ODataExpectedExceptions.ODataException("WriterValidationUtils_OperationInRequest", GetFirstOperationMetadata(entry)) : entry.Actions != null && entry.Actions.Any(a => !a.Metadata.IsAbsoluteUri && !a.Metadata.OriginalString.StartsWith("#")) ? ODataExpectedExceptions.ODataException("ValidationUtils_InvalidMetadataReferenceProperty", entry.Actions.First(a => a.Metadata.OriginalString.Contains(" ")).Metadata.OriginalString) : entry.Functions != null && entry.Functions.Contains(null) ? ODataExpectedExceptions.ODataException("ValidationUtils_EnumerableContainsANullItem", "ODataResource.Functions") : testConfiguration.IsRequest && entry.Functions != null && entry.Functions.Any() ? ODataExpectedExceptions.ODataException("WriterValidationUtils_OperationInRequest", GetFirstOperationMetadata(entry)) : entry.Functions != null && entry.Functions.Any(f => !f.Metadata.IsAbsoluteUri && !f.Metadata.OriginalString.StartsWith("#")) ? ODataExpectedExceptions.ODataException("ValidationUtils_InvalidMetadataReferenceProperty", entry.Functions.First(f => f.Metadata.OriginalString.Contains(" ")).Metadata.OriginalString) : null, FragmentExtractor = (result) => { var actionsAndFunctions = result.Object().Properties.Where(p => p.Name.Contains("#")).ToList(); var jsonResult = new JsonObject(); actionsAndFunctions.ForEach(p => { // NOTE we remove all annotations here and in particular the text annotations to be able to easily compare // against the expected results. This however means that we do not distinguish between the indented and non-indented case here. p.RemoveAllAnnotations(true); jsonResult.Add(p); }); return jsonResult; } }; } else { string formatName = testConfiguration.Format == null ? "null" : testConfiguration.Format.GetType().Name; throw new NotSupportedException("Invalid format detected: " + formatName); } })); }); this.CombinatorialEngineProvider.RunCombinations( testDescriptors.PayloadCases(WriterPayloads.EntryPayloads), this.WriterTestConfigurationProvider.ExplicitFormatConfigurationsWithIndent, (testDescriptor, testConfiguration) => { testConfiguration = testConfiguration.Clone(); testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri); if (testConfiguration.Format == ODataFormat.Json) { if (testDescriptor.IsGeneratedPayload) { return; } // We need a model, entity set and entity type for JSON Light testDescriptor = new PayloadWriterTestDescriptor <ODataItem>(testDescriptor) { Model = model, PayloadEdmElementContainer = edmEntitySetCustermors, PayloadEdmElementType = edmEntityTypeCustomer, }; } TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor, testConfiguration, this.Assert, this.Logger); }); }
internal ODataCallExpression(ODataFunction function, IReadOnlyList<ODataExpression> arguments, Type returnClrType) : base(ODataExpressionKind.Call, returnClrType.ToODataExpressionType(), returnClrType) { this.Function = function; this.Arguments = arguments; }
/// <summary> /// Read the 'actions' or 'functions' metadata for the entry being read. /// </summary> /// <param name="entry">The <see cref="ODataEntry"/> the 'actions' or 'functions' metadata is read for.</param> /// <param name="isActions">When True the 'actions' metadata is being read, otherwise 'functions' metadata is being read.</param> /// <remarks> /// Pre-Condition: first node of the 'actions' or 'functions' property's value (we will throw if this is not a start object node) /// Post-Condition: JsonNodeType.Property: the next metadata property /// JsonNodeType.EndObject: the end-object node of the metadata object /// /// This method will not validate anything against the model because it will read the type name and thus it can't rely /// on knowing the actual type of the entry being read. /// </remarks> private void ReadOperationsMetadata(ODataEntry entry, bool isActions) { Debug.Assert(entry != null, "entry != null"); this.JsonReader.AssertBuffering(); string operationsHeaderName = isActions ? JsonConstants.ODataActionsMetadataName : JsonConstants.ODataFunctionsMetadataName; // make sure the 'actions' or 'functions' property value is an object if (this.JsonReader.NodeType != JsonNodeType.StartObject) { throw new ODataException(o.Strings.ODataJsonEntryAndFeedDeserializer_PropertyInEntryMustHaveObjectValue(operationsHeaderName, this.JsonReader.NodeType)); } // read over the start-object node of the metadata object for 'actions' or 'functions' this.JsonReader.ReadStartObject(); // iterate through each metadata object HashSet<string> metadataValues = new HashSet<string>(StringComparer.Ordinal); while (this.JsonReader.NodeType == JsonNodeType.Property) { string metadataValue = this.JsonReader.ReadPropertyName(); // JSON reader should have already validated that the property name is a string and is not empty or null. Debug.Assert(!string.IsNullOrEmpty(metadataValue), "!string.IsNullOrEmpty(metadataValue)"); if (metadataValues.Contains(metadataValue)) { throw new ODataException(o.Strings.ODataJsonEntryAndFeedDeserializer_RepeatMetadataValue(operationsHeaderName, metadataValue)); } metadataValues.Add(metadataValue); if (this.JsonReader.NodeType != JsonNodeType.StartArray) { throw new ODataException(o.Strings.ODataJsonEntryAndFeedDeserializer_MetadataMustHaveArrayValue(operationsHeaderName, this.JsonReader.NodeType)); } // read the start-array node of the current metadata this.JsonReader.ReadStartArray(); if (this.JsonReader.NodeType != JsonNodeType.StartObject) { throw new ODataException(o.Strings.ODataJsonEntryAndFeedDeserializer_OperationMetadataArrayExpectedAnObject(operationsHeaderName, this.JsonReader.NodeType)); } while (this.JsonReader.NodeType == JsonNodeType.StartObject) { this.JsonReader.ReadStartObject(); ODataOperation operation; if (isActions) { operation = new ODataAction(); ReaderUtils.AddActionToEntry(entry, (ODataAction)operation); } else { operation = new ODataFunction(); ReaderUtils.AddFunctionToEntry(entry, (ODataFunction)operation); } operation.Metadata = this.ResolveUri(metadataValue); while (this.JsonReader.NodeType == JsonNodeType.Property) { string operationPropertyName = this.JsonReader.ReadPropertyName(); switch (operationPropertyName) { case JsonConstants.ODataOperationTitleName: if (operation.Title != null) { throw new ODataException(o.Strings.ODataJsonEntryAndFeedDeserializer_MultipleOptionalPropertiesInOperation( operationPropertyName, metadataValue, operationsHeaderName)); } string titleString = this.JsonReader.ReadStringValue(JsonConstants.ODataOperationTitleName); ODataJsonReaderUtils.ValidateOperationJsonProperty(titleString, operationPropertyName, metadataValue, operationsHeaderName); operation.Title = titleString; break; case JsonConstants.ODataOperationTargetName: if (operation.Target != null) { throw new ODataException(o.Strings.ODataJsonEntryAndFeedDeserializer_MultipleTargetPropertiesInOperation( metadataValue, operationsHeaderName)); } string targetString = this.JsonReader.ReadStringValue(JsonConstants.ODataOperationTargetName); ODataJsonReaderUtils.ValidateOperationJsonProperty(targetString, operationPropertyName, metadataValue, operationsHeaderName); operation.Target = this.ProcessUriFromPayload(targetString); break; default: // skip over all unknown properties and read the next property or // the end of the metadata for the current propertyName this.JsonReader.SkipValue(); break; } } if (operation.Target == null) { throw new ODataException(o.Strings.ODataJsonEntryAndFeedDeserializer_OperationMissingTargetProperty(metadataValue, operationsHeaderName)); } // read the end-object node of the target / title pair this.JsonReader.ReadEndObject(); } // read the end-array node of the metadata array this.JsonReader.ReadEndArray(); } // read over the end-object node of the metadata object for 'actions' or 'functions'. this.JsonReader.ReadEndObject(); this.JsonReader.AssertBuffering(); Debug.Assert( this.JsonReader.NodeType == JsonNodeType.Property || this.JsonReader.NodeType == JsonNodeType.EndObject, "Post-Condition: expected JsonNodeType.Property or JsonNodeType.EndObject"); }
/// <summary> /// Adds the specified function to the current entry. /// </summary> /// <param name="function">The function whcih is fully populated with the data from the payload.</param> public void AddFunctionToEntry(ODataFunction function) { Debug.Assert(function != null, "function != null"); this.entry.AddFunction(function); }
private bool TryReadOperation(IODataAtomReaderEntryState entryState) { ODataOperation operation; bool flag = false; if (base.XmlReader.LocalNameEquals(this.ODataActionElementName)) { flag = true; } else if (!base.XmlReader.LocalNameEquals(this.ODataFunctionElementName)) { return false; } if (flag) { operation = new ODataAction(); ReaderUtils.AddActionToEntry(entryState.Entry, (ODataAction) operation); } else { operation = new ODataFunction(); ReaderUtils.AddFunctionToEntry(entryState.Entry, (ODataFunction) operation); } string localName = base.XmlReader.LocalName; while (base.XmlReader.MoveToNextAttribute()) { if (base.XmlReader.NamespaceEquals(base.EmptyNamespace)) { string uriFromPayload = base.XmlReader.Value; if (base.XmlReader.LocalNameEquals(this.ODataOperationMetadataAttribute)) { operation.Metadata = base.ProcessUriFromPayload(uriFromPayload, base.XmlReader.XmlBaseUri, false); } else { if (base.XmlReader.LocalNameEquals(this.ODataOperationTargetAttribute)) { operation.Target = base.ProcessUriFromPayload(uriFromPayload, base.XmlReader.XmlBaseUri); continue; } if (base.XmlReader.LocalNameEquals(this.ODataOperationTitleAttribute)) { operation.Title = base.XmlReader.Value; } } } } if (operation.Metadata == null) { throw new ODataException(Microsoft.Data.OData.Strings.ODataAtomEntryAndFeedDeserializer_OperationMissingMetadataAttribute(localName)); } if (operation.Target == null) { throw new ODataException(Microsoft.Data.OData.Strings.ODataAtomEntryAndFeedDeserializer_OperationMissingTargetAttribute(localName)); } base.XmlReader.Skip(); return true; }
public virtual ODataOperation CreateODataOperation(IEdmOperation operation, ResourceSetContext resourceSetContext, ODataSerializerContext writeContext) { if (operation == null) { throw Error.ArgumentNull("operation"); } if (resourceSetContext == null) { throw Error.ArgumentNull("resourceSetContext"); } if (writeContext == null) { throw Error.ArgumentNull("writeContext"); } ODataMetadataLevel metadataLevel = writeContext.MetadataLevel; IEdmModel model = writeContext.Model; if (metadataLevel != ODataMetadataLevel.FullMetadata) { return(null); } OperationLinkBuilder builder; builder = model.GetOperationLinkBuilder(operation); if (builder == null) { return(null); } Uri target = builder.BuildLink(resourceSetContext); if (target == null) { return(null); } Uri baseUri = new Uri(writeContext.Url.CreateODataLink(MetadataSegment.Instance)); Uri metadata = new Uri(baseUri, "#" + operation.FullName()); ODataOperation odataOperation; IEdmAction action = operation as IEdmAction; if (action != null) { odataOperation = new ODataAction(); } else { odataOperation = new ODataFunction(); } odataOperation.Metadata = metadata; // Always omit the title in minimal/no metadata modes. ODataResourceSerializer.EmitTitle(model, operation, odataOperation); // Omit the target in minimal/no metadata modes unless it doesn't follow conventions. if (metadataLevel == ODataMetadataLevel.FullMetadata || !builder.FollowsConventions) { odataOperation.Target = target; } return(odataOperation); }
internal ODataCallExpression(ODataFunction function, IReadOnlyList <ODataExpression> arguments, Type returnClrType) : base(ODataExpressionKind.Call, returnClrType.ToODataExpressionType(), returnClrType) { this.Function = function; this.Arguments = arguments; }
internal static ODataCallExpression Call(ODataFunction function, IEnumerable<ODataExpression> arguments) { var argumentsList = (arguments as IReadOnlyList<ODataExpression>) ?? arguments.ToArray(); var signatures = FunctionSignatures[function]; var matches = (from s in signatures let args = s.Arguments.Select((v, i) => new { Value = v, Index = i }) let score = s.Arguments.Count != argumentsList.Count ? default(int?) : args.All(iv => !iv.Value.HasValue || iv.Value.Value == argumentsList[iv.Index].Type) ? 0 : args.All(iv => !iv.Value.HasValue || argumentsList[iv.Index].Type.IsImplicityCastableTo(iv.Value.Value)) ? 1 : default(int?) where score.HasValue orderby score select new { sig = s, score }) .ToArray(); Throw<ArgumentException>.If(matches.Length == 0, () => string.Format("No version of {0} matched the argument types [{1}]", function, arguments.Select(a => a.Type).ToDelimitedString(", "))); Throw<ArgumentException>.If(matches.Length > 1 && matches[0].score == matches[1].score, () => string.Format("Ambiguous match for argument types [{0}] between {1} and {2}", arguments.Select(a => a.Type).ToDelimitedString(", "), matches[0].sig, matches[1].sig)); var match = matches[0].sig; var castArguments = argumentsList.Select((a, i) => (!match.Arguments[i].HasValue || a.Type == match.Arguments[i]) ? a : Convert(a, match.Arguments[i].Value.ToClrType())) .ToList() .AsReadOnly(); // the ?? here on return type handles cast, whose return type is dynamic depending on its arguments return new ODataCallExpression( function, castArguments, match.ReturnType.HasValue ? match.ReturnType.Value.ToClrType() : (Type)((ODataConstantExpression)castArguments[1]).Value ); }