public void EdmPathExpression()
        {
            var e = new EdmPathExpression("x", "y");

            Assert.IsFalse(e.IsBad(), "e good");
            Assert.AreEqual(EdmExpressionKind.Path, e.ExpressionKind, "e.ExpressionKind");
            Assert.AreEqual(2, e.Path.Count(), "e.Path.Count()");
            var s1 = e.Path.First();

            Assert.AreEqual("x", s1, "s1");
            Assert.AreEqual("y", e.Path.Last(), "e.Path.Last()");

            try
            {
                new EdmPathExpression((string[])null);
                Assert.Fail("exception expected");
            }
            catch (ArgumentNullException)
            {
            }

            var ee = new MutablePathExpression();

            Assert.IsNull(ee.Path, "ee.Path");
            Assert.IsTrue(ee.IsBad(), "Expression is bad.");
            Assert.AreEqual(1, ee.Errors().Count(), "Expression has no errors");
        }
        public OpenApiRequestBodyGeneratorTest()
        {
            EdmModel           model     = new EdmModel();
            EdmEntityContainer container = new EdmEntityContainer("NS", "Default");

            model.AddElement(container);

            EdmEntityType customer = new EdmEntityType("NS", "Customer", null, false, false, true);

            customer.AddKeys(customer.AddStructuralProperty("ID", EdmPrimitiveTypeKind.Int32));

            var boolType = EdmCoreModel.Instance.GetBoolean(false);

            var actionEntitySetPath = new EdmPathExpression("Param1/Nav");
            var edmAction           = new EdmAction("NS", "Checkout", boolType, true, actionEntitySetPath);

            edmAction.AddParameter(new EdmOperationParameter(edmAction, "bindingParameter", new EdmEntityTypeReference(customer, true)));
            edmAction.AddParameter("param", EdmCoreModel.Instance.GetString(true));
            model.AddElement(edmAction);

            var actionImportEntitySetPath = new EdmPathExpression("Param1/Nav2");
            var edmActionImport           = new EdmActionImport(container, "CheckoutImport", edmAction, actionImportEntitySetPath);

            container.AddElement(edmActionImport);

            _model        = model;
            _entityType   = customer;
            _action       = edmAction;
            _actionImport = edmActionImport;
        }
        private static IEdmEntitySetBase GetTargetEntitySet(EdmPathExpression edmPathExpression, out IEdmEntitySet targetEntitySet, bool addParameters = false, bool isBindable = true)
        {
            var model     = new EdmModel();
            var container = new EdmEntityContainer("Fake", "Container");

            model.AddElement(container);
            var edmEntityType = new EdmEntityType("Fake", "EntityType");

            var sourceEntitySet = container.AddEntitySet("SourceEntitySet", edmEntityType);
            var middleEntitySet = container.AddEntitySet("MiddleEntitySet", edmEntityType);

            targetEntitySet = container.AddEntitySet("TargetEntitySet", edmEntityType);

            var nav1 = edmEntityType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo {
                Name = "Navigation1", Target = edmEntityType, TargetMultiplicity = EdmMultiplicity.ZeroOrOne
            });
            var nav2 = edmEntityType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo {
                Name = "Navigation2", Target = edmEntityType, TargetMultiplicity = EdmMultiplicity.Many
            });

            sourceEntitySet.AddNavigationTarget(nav1, middleEntitySet);
            middleEntitySet.AddNavigationTarget(nav2, targetEntitySet);

            var action = new EdmAction("Fake", "FakeAction", new EdmEntityTypeReference(edmEntityType, false), isBindable, null /*EntitySetPath*/);

            if (addParameters)
            {
                action.AddParameter("p1", new EdmEntityTypeReference(edmEntityType, false));
                action.AddParameter("p2", new EdmEntityTypeReference(edmEntityType, false));
            }

            var actionImport = container.AddActionImport("FakeAction", action, edmPathExpression);

            return(actionImport.GetTargetEntitySet(sourceEntitySet, model));
        }
Example #4
0
        public void EnsureFunctionImportIsAddedAndWithCorrectEntitySetExpression()
        {
            EdmEntityContainer container = new EdmEntityContainer("Default", "Container");
            EdmAction          action    = new EdmAction("DS", "TestAction", EdmCoreModel.Instance.GetBoolean(false));
            var entitySetExpression      = new EdmPathExpression("EntitySet");
            var actionImport             = container.AddActionImport("OtherName", action, entitySetExpression);

            Assert.Same(action, actionImport.Action);
            Assert.Equal("OtherName", actionImport.Name);
            Assert.Same(entitySetExpression, actionImport.EntitySet);
            Assert.Same(actionImport, container.Elements.ToArray()[0]);
        }
        public void GetTargetEntitySetForFunctionWithNoStaticSetOrSourceSetShouldBeNull()
        {
            var model     = new EdmModel();
            var container = new EdmEntityContainer("Fake", "Container");

            model.AddElement(container);
            var function        = new EdmFunction("Fake", "FakeFunction", new EdmEntityTypeReference(new EdmEntityType("Fake", "EntityType"), false));
            var expression      = new EdmPathExpression("p1/Navigation1");
            var operationImport = container.AddFunctionImport("FakeAction", function, expression);

            operationImport.GetTargetEntitySet(null, model).Should().BeNull();
        }
Example #6
0
        public void EdmActionConstructorShouldHaveSpecifiedConstructorValues()
        {
            var entitySetPath = new EdmPathExpression("Param1/Nav");
            var edmAction     = new EdmAction(defaultNamespaceName, checkout, this.boolType, true, entitySetPath);

            edmAction.AddParameter(new EdmOperationParameter(edmAction, "Param1", new EdmEntityTypeReference(personType, false)));
            edmAction.Namespace.Should().Be(defaultNamespaceName);
            edmAction.Name.Should().Be(checkout);
            edmAction.ReturnType.Should().Be(this.boolType);
            edmAction.EntitySetPath.Should().Be(entitySetPath);
            edmAction.IsBound.Should().BeTrue();
            edmAction.SchemaElementKind.Should().Be(EdmSchemaElementKind.Action);
        }
Example #7
0
        public void EdmActionImportConstructorShouldHaveSpecifiedConstructorValues()
        {
            var actionEntitySetPath = new EdmPathExpression("Param1/Nav");
            var edmAction           = new EdmAction("DefaultNamespace", "Checkout", this.boolType, true, actionEntitySetPath);

            edmAction.AddParameter(new EdmOperationParameter(edmAction, "Param1", new EdmEntityTypeReference(personType, true)));

            var actionImportEntitySetPath = new EdmPathExpression("Param1/Nav2");
            var edmActionImport           = new EdmActionImport(this.entityContainer, "checkoutImport", edmAction, actionImportEntitySetPath);

            edmActionImport.Name.Should().Be("checkoutImport");
            edmActionImport.Container.Should().Be(this.entityContainer);
            edmActionImport.EntitySet.Should().Be(actionImportEntitySetPath);
            edmActionImport.Action.Should().Be(edmAction);
        }
Example #8
0
        public void EdmFunctionConstructorShouldHaveSpecifiedConstructorValues()
        {
            var entitySetPath = new EdmPathExpression("Param1/Nav");
            var edmFunction   = new EdmFunction(defaultNamespaceName, checkout, this.boolType, true, entitySetPath, true /*IsComposable*/);

            edmFunction.AddParameter(new EdmOperationParameter(edmFunction, "Param1", new EdmEntityTypeReference(personType, false)));
            Assert.Equal(defaultNamespaceName, edmFunction.Namespace);
            Assert.Equal(checkout, edmFunction.Name);
            Assert.Same(this.boolType, edmFunction.ReturnType);
            Assert.Same(entitySetPath, edmFunction.EntitySetPath);
            Assert.True(edmFunction.IsBound);
            Assert.Equal(EdmSchemaElementKind.Function, edmFunction.SchemaElementKind);
            Assert.True(edmFunction.IsComposable);

            Assert.NotNull(edmFunction.Return);
            Assert.Same(edmFunction.ReturnType, edmFunction.Return.Type);
        }
Example #9
0
        /// <summary>
        /// Initializes a new <see cref="IEdmOperationImport"/> instance.
        /// </summary>
        /// <param name="name">name of the service operation.</param>
        /// <param name="function">Function imported in.</param>
        /// <param name="resultSet">EntitySet of the result expected from this operation.</param>
        public EdmFunctionImport AddFunctionAndFunctionImport(string name, IEdmTypeReference bindingType, IEdmTypeReference resultType, IEdmEntitySet resultSet, bool isBindable)
        {
            var edmFunction = new EdmFunction(this.Namespace, name, resultType, isBindable, null, false /*isComposable*/);

            if (isBindable)
            {
                edmFunction.AddParameter("bindingparameter", bindingType);
            }

            IEdmPathExpression entitySetExpression = null;

            if (resultSet != null)
            {
                entitySetExpression = new EdmPathExpression(resultSet.Name);
            }

            this.AddOperation(edmFunction);
            var functionImport = new EdmFunctionImport(this, name, edmFunction, entitySetExpression, false);

            this.AddOperationImport(name, functionImport);
            return(functionImport);
        }
        /// <summary>
        /// Get the string representation of <see cref="ODataPath"/>.
        /// mainly translate Context Url path.
        /// </summary>
        /// <param name="path">Path to perform the computation on.</param>
        /// <returns>The string representation of the Context Url path.</returns>
        public static string ToContextUrlPathString(this ODataPath path)
        {
            StringBuilder pathString = new StringBuilder();
            PathSegmentToContextUrlPathTranslator pathTranslator = PathSegmentToContextUrlPathTranslator.DefaultInstance;
            ODataPathSegment priorSegment = null;
            bool             foundOperationWithoutPath = false;

            foreach (ODataPathSegment segment in path)
            {
                OperationSegment       operationSegment       = segment as OperationSegment;
                OperationImportSegment operationImportSegment = segment as OperationImportSegment;
                if (operationImportSegment != null)
                {
                    IEdmOperationImport operationImport = operationImportSegment.OperationImports.FirstOrDefault();
                    Debug.Assert(operationImport != null);

                    EdmPathExpression pathExpression = operationImport.EntitySet as EdmPathExpression;
                    if (pathExpression != null)
                    {
                        Debug.Assert(priorSegment == null); // operation import is always the first segment?
                        pathString.Append(pathExpression.Path);
                    }
                    else
                    {
                        pathString = operationImport.Operation.ReturnType != null ?
                                     new StringBuilder(operationImport.Operation.ReturnType.FullName()) :
                                     new StringBuilder("Edm.Untyped");

                        foundOperationWithoutPath = true;
                    }
                }
                else if (operationSegment != null)
                {
                    IEdmOperation operation = operationSegment.Operations.FirstOrDefault();
                    Debug.Assert(operation != null);

                    if (operation.IsBound &&
                        priorSegment != null &&
                        operation.Parameters.First().Type.Definition == priorSegment.EdmType)
                    {
                        if (operation.EntitySetPath != null)
                        {
                            foreach (string pathSegment in operation.EntitySetPath.PathSegments.Skip(1))
                            {
                                pathString.Append('/');
                                pathString.Append(pathSegment);
                            }
                        }
                        else if (operationSegment.EntitySet != null)
                        {
                            // Is it correct to check EntitySet?
                            pathString = new StringBuilder(operationSegment.EntitySet.Name);
                        }
                        else
                        {
                            pathString = operation.ReturnType != null ?
                                         new StringBuilder(operation.ReturnType.FullName()) :
                                         new StringBuilder("Edm.Untyped");

                            foundOperationWithoutPath = true;
                        }
                    }
                }
                else
                {
                    if (foundOperationWithoutPath)
                    {
                        pathString = new StringBuilder(segment.EdmType.FullTypeName());
                        foundOperationWithoutPath = false;
                    }
                    else
                    {
                        pathString.Append(segment.TranslateWith(pathTranslator));
                    }
                }

                priorSegment = segment;
            }

            return(pathString.ToString().TrimStart('/'));
        }
Example #11
0
        public EdmModel BuildEdmModel(params IEdmModel[] refModels)
        {
            AddOperations();

            Dictionary <Type, EntityTypeInfo> entityTypeInfos = BuildEntityTypes(refModels);

            foreach (EntityTypeInfo typeInfo in entityTypeInfos.Values)
            {
                if (!typeInfo.IsRefModel)
                {
                    typeInfo.BuildProperties(entityTypeInfos, _enumTypes, _complexTypes);
                }
            }

            foreach (EntityTypeInfo typeInfo in entityTypeInfos.Values)
            {
                foreach (FKeyInfo fkeyInfo in typeInfo.NavigationClrProperties)
                {
                    fkeyInfo.EdmNavigationProperty = CreateNavigationProperty(fkeyInfo);
                }
            }

            var edmModel   = new EdmModel();
            var containers = new Dictionary <Db.OeDataAdapter, EdmEntityContainer>();

            edmModel.AddElements(_enumTypes.Values);
            foreach (KeyValuePair <Type, EdmEnumType> enumType in _enumTypes)
            {
                edmModel.SetClrType(enumType.Value, enumType.Key);
            }

            edmModel.AddElements(_complexTypes.Values);
            foreach (KeyValuePair <Type, EdmComplexType> complexType in _complexTypes)
            {
                edmModel.SetClrType(complexType.Value, complexType.Key);
            }

            var container = new EdmEntityContainer(_dataAdapter.DataContextType.Namespace, _dataAdapter.DataContextType.Name);

            edmModel.SetDataAdapter(container, _dataAdapter);

            var entitySets = new Dictionary <IEdmEntityType, EdmEntitySet>(entityTypeInfos.Count);

            foreach (EntityTypeInfo typeInfo in entityTypeInfos.Values)
            {
                edmModel.AddElement(typeInfo.EdmType);
                edmModel.SetClrType(typeInfo.EdmType, typeInfo.ClrType);

                foreach (Db.OeEntitySetAdapter entitySetAdapter in _dataAdapter.EntitySetAdapters)
                {
                    if (entitySetAdapter.EntityType == typeInfo.ClrType)
                    {
                        EdmEntitySet entitySet = container.AddEntitySet(entitySetAdapter.EntitySetName, typeInfo.EdmType);
                        edmModel.SetEntitySetAdapter(entitySet, entitySetAdapter);
                        entitySets.Add(typeInfo.EdmType, entitySet);
                        break;
                    }
                }
            }

            var manyToManyBuilder = new ManyToManyBuilder(edmModel, _metadataProvider, entityTypeInfos);

            foreach (EntityTypeInfo typeInfo in entityTypeInfos.Values)
            {
                foreach (FKeyInfo fkeyInfo in typeInfo.NavigationClrProperties)
                {
                    EdmEntitySet principal = entitySets[fkeyInfo.PrincipalInfo.EdmType];
                    EdmEntitySet dependent = entitySets[fkeyInfo.DependentInfo.EdmType];

                    if (fkeyInfo.DependentNavigationProperty == null)
                    {
                        principal.AddNavigationTarget(fkeyInfo.EdmNavigationProperty, dependent);
                    }
                    else
                    {
                        dependent.AddNavigationTarget(fkeyInfo.EdmNavigationProperty, principal);
                        if (fkeyInfo.EdmNavigationProperty.Partner != null)
                        {
                            principal.AddNavigationTarget(fkeyInfo.EdmNavigationProperty.Partner, dependent);
                        }
                    }
                }

                if (!typeInfo.IsRefModel)
                {
                    manyToManyBuilder.Build(typeInfo);
                }
            }

            foreach (OeOperationConfiguration operationConfiguration in _operationConfigurations)
            {
                if (operationConfiguration.IsEdmFunction)
                {
                    EdmPathExpression path        = null;
                    EdmFunction       edmFunction = BuildFunction(operationConfiguration, entityTypeInfos);
                    if (edmFunction.ReturnType.Definition.AsElementType() is IEdmEntityType entityType)
                    {
                        path = new EdmPathExpression(_dataAdapter.DataContextType.FullName, entitySets[entityType].Name);
                    }

                    edmModel.AddElement(edmFunction);
                    container.AddFunctionImport(operationConfiguration.Name, edmFunction, path);
                    edmModel.SetIsDbFunction(edmFunction, operationConfiguration.IsDbFunction);
                }
                else
                {
                    EdmAction edmAction = BuildAction(operationConfiguration, entityTypeInfos);
                    edmModel.AddElement(edmAction);
                    container.AddActionImport(operationConfiguration.Name, edmAction);
                    edmModel.SetIsDbFunction(edmAction, operationConfiguration.IsDbFunction);
                }
            }

            edmModel.AddElement(container);
            _dataAdapter.SetEdmModel(edmModel);
            foreach (IEdmModel refModel in refModels)
            {
                edmModel.AddReferencedModel(refModel);
            }
            return(edmModel);
        }
Example #12
0
        private void InitializeEdmModel()
        {
            this.edmModel = new EdmModel();

            EdmEntityContainer defaultContainer = new EdmEntityContainer("TestModel", "DefaultContainer");

            this.edmModel.AddElement(defaultContainer);

            addressType = new EdmComplexType("TestModel", "Address");
            addressType.AddStructuralProperty("Street", EdmCoreModel.Instance.GetString(/*isNullable*/ false));
            addressType.AddStructuralProperty("Zip", EdmCoreModel.Instance.GetString(/*isNullable*/ false));

            this.cityType = new EdmEntityType("TestModel", "City", baseType: null, isAbstract: false, isOpen: true);
            EdmStructuralProperty cityIdProperty = cityType.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(/*isNullable*/ false));

            cityType.AddKeys(cityIdProperty);
            cityType.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(/*isNullable*/ false));
            cityType.AddStructuralProperty("Size", EdmCoreModel.Instance.GetInt32(/*isNullable*/ false));
            cityType.AddStructuralProperty("Restaurants", EdmCoreModel.GetCollection(EdmCoreModel.Instance.GetString(/*isNullable*/ false)));
            cityType.AddStructuralProperty("Address", new EdmComplexTypeReference(addressType, true));
            this.edmModel.AddElement(cityType);

            this.capitolCityType = new EdmEntityType("TestModel", "CapitolCity", cityType);
            capitolCityType.AddStructuralProperty("CapitolType", EdmCoreModel.Instance.GetString(/*isNullable*/ false));
            this.edmModel.AddElement(capitolCityType);

            this.districtType = new EdmEntityType("TestModel", "District");
            EdmStructuralProperty districtIdProperty = districtType.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(/*isNullable*/ false));

            districtType.AddKeys(districtIdProperty);
            districtType.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(/*isNullable*/ false));
            districtType.AddStructuralProperty("Zip", EdmCoreModel.Instance.GetInt32(/*isNullable*/ false));
            this.edmModel.AddElement(districtType);

            cityType.AddBidirectionalNavigation(
                new EdmNavigationPropertyInfo {
                Name = "Districts", Target = districtType, TargetMultiplicity = EdmMultiplicity.Many
            },
                new EdmNavigationPropertyInfo {
                Name = "City", Target = cityType, TargetMultiplicity = EdmMultiplicity.One
            });

            cityType.NavigationProperties().Single(np => np.Name == "Districts");
            capitolCityType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo {
                Name = "CapitolDistrict", Target = districtType, TargetMultiplicity = EdmMultiplicity.One
            });
            capitolCityType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo {
                Name = "OutlyingDistricts", Target = districtType, TargetMultiplicity = EdmMultiplicity.Many
            });

            this.citySet     = defaultContainer.AddEntitySet("Cities", cityType);
            this.districtSet = defaultContainer.AddEntitySet("Districts", districtType);

            this.singletonCity = defaultContainer.AddSingleton("SingletonCity", cityType);

            // operations
            var cityReference       = new EdmEntityTypeReference(cityType, true);
            var districtReference   = new EdmEntityTypeReference(districtType, true);
            IEdmPathExpression path = new EdmPathExpression("binding/Districts");
            var function            = new EdmFunction("TestModel", "GetOneDistrict", districtReference, true, path, true /*isComposable*/);

            function.AddParameter("binding", cityReference);
            edmModel.AddElement(function);
        }
Example #13
0
        internal static IEdmModel GetEdmModel()
        {
            var model = new EdmModel();

            // open address
            var address = new EdmComplexType("NS", "Address", null, false, true);

            address.AddStructuralProperty("Street", EdmCoreModel.Instance.GetString(true));
            address.AddStructuralProperty("City", EdmCoreModel.Instance.GetString(true));
            model.AddElement(address);

            // customer
            var customer = new EdmEntityType("NS", "Customer");

            customer.AddKeys(customer.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(false)));
            customer.AddStructuralProperty("HomeAddress", new EdmComplexTypeReference(address, true));
            model.AddElement(customer);

            // order
            var order = new EdmEntityType("NS", "Order");

            order.AddKeys(order.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(false)));
            model.AddElement(order);

            var nav = customer.AddBidirectionalNavigation(
                new EdmNavigationPropertyInfo
            {
                Name               = "Orders",
                Target             = order,
                TargetMultiplicity = EdmMultiplicity.Many
            },
                new EdmNavigationPropertyInfo
            {
                Name = "Customer",
                TargetMultiplicity = EdmMultiplicity.ZeroOrOne,
            });

            var container = new EdmEntityContainer("Default", "Container");

            model.AddElement(container);

            var customers = new EdmEntitySet(container, "Customers", customer);

            container.AddElement(customers);

            var orders = new EdmEntitySet(container, "Orders", order);

            container.AddElement(orders);
            customers.AddNavigationTarget(nav, orders);

            // bound operations
            var customerReference = new EdmEntityTypeReference(customer, true);
            var orderReference    = new EdmEntityTypeReference(order, true);

            IEdmPathExpression path = new EdmPathExpression("binding/Orders");

            // entityset path & return type
            var function = new EdmFunction("NS", "GetSomeOrders", new EdmCollectionTypeReference(new EdmCollectionType(orderReference)), true, path, true /*isComposable*/);

            function.AddParameter("binding", customerReference);
            model.AddElement(function);

            function = new EdmFunction("NS", "GetAnOrder", orderReference, true, path, true /*isComposable*/);
            function.AddParameter("binding", customerReference);
            model.AddElement(function);

            // GetSomeAddressFromCustomer
            function = new EdmFunction("NS", "GetSomeAddressFromCustomer1", new EdmComplexTypeReference(address, true), true, null, true /*isComposable*/);
            function.AddParameter("binding", new EdmEntityTypeReference(customer, true));
            model.AddElement(function);

            // We leave the "GetSomeAddressFromCustomer2" code here.
            // However, the operation with the entity set path containing a complex type doesn't make sense.
            IEdmPathExpression complexPath = new EdmPathExpression("binding/HomeAddress");

            function = new EdmFunction("NS", "GetSomeAddressFromCustomer2", new EdmComplexTypeReference(address, true), true, complexPath, true /*isComposable*/);
            function.AddParameter("binding", new EdmEntityTypeReference(customer, true));
            model.AddElement(function);

            function = new EdmFunction("NS", "GetSomeAddressFromCustomer3", new EdmComplexTypeReference(address, true), true, null, true /*isComposable*/);
            function.AddParameter("binding", new EdmEntityTypeReference(customer, true));
            model.AddElement(function);

            var action = new EdmAction("NS", "DoSomeThing", null, true, null);

            action.AddParameter("binding", new EdmEntityTypeReference(customer, true));
            model.AddElement(action);

            // operation import
            function = new EdmFunction("NS", "GetSomeOrders2", new EdmCollectionTypeReference(new EdmCollectionType(orderReference)));
            EdmFunctionImport functionImport = new EdmFunctionImport(container, "GetSomeOrders2", function, new EdmPathExpression("Orders"), false);

            container.AddElement(functionImport);

            function       = new EdmFunction("NS", "GetAnOrder2", orderReference);
            functionImport = new EdmFunctionImport(container, "GetAnOrder2", function, new EdmPathExpression("Orders"), false);
            container.AddElement(functionImport);

            function       = new EdmFunction("NS", "GetSomeAddress", new EdmComplexTypeReference(address, true), false, null, true);
            functionImport = new EdmFunctionImport(container, "GetSomeAddress", function, null, false);
            container.AddElement(functionImport);

            action = new EdmAction("NS", "DoSomeThing2", null, false, null);
            var actionImport = new EdmActionImport(container, "DoSomeThing2", action, null);

            container.AddElement(actionImport);
            return(model);
        }
        private void BuildOperations(EdmModel model, string modelNamespace)
        {
            foreach (OperationMethodInfo operationMethodInfo in this.operationInfos)
            {
                // With this method, if return type is nullable type,it will get underlying type
                var  returnType          = TypeHelper.GetUnderlyingTypeOrSelf(operationMethodInfo.Method.ReturnType);
                var  returnTypeReference = returnType.GetReturnTypeReference(model);
                bool isBound             = operationMethodInfo.IsBound;
                var  bindingParameter    = operationMethodInfo.Method.GetParameters().FirstOrDefault();

                if (bindingParameter == null && isBound)
                {
                    // Ignore the method which is marked as bounded but no parameters
                    continue;
                }

                string namespaceName = GetNamespaceName(operationMethodInfo, modelNamespace);

                EdmOperation      operation = null;
                EdmPathExpression path      = null;
                if (isBound)
                {
                    // Unbound actions or functions should not have EntitySetPath attribute
                    path = BuildEntitySetPathExpression(returnTypeReference, bindingParameter);
                }

                if (operationMethodInfo.HasSideEffects)
                {
                    operation = new EdmAction(
                        namespaceName,
                        operationMethodInfo.Name,
                        returnTypeReference,
                        isBound,
                        path);
                }
                else
                {
                    operation = new EdmFunction(
                        namespaceName,
                        operationMethodInfo.Name,
                        returnTypeReference,
                        isBound,
                        path,
                        operationMethodInfo.IsComposable);
                }

                BuildOperationParameters(operation, operationMethodInfo.Method, model);
                model.AddElement(operation);

                if (!isBound)
                {
                    // entitySetReferenceExpression refer to an entity set containing entities returned
                    // by this function/action import.
                    var entitySetReferenceExpression = BuildEntitySetReferenceExpression(
                        model, operationMethodInfo.EntitySet, returnTypeReference);
                    var entityContainer = model.EnsureEntityContainer(this.targetType);
                    if (operationMethodInfo.HasSideEffects)
                    {
                        entityContainer.AddActionImport(
                            operation.Name, (EdmAction)operation, entitySetReferenceExpression);
                    }
                    else
                    {
                        entityContainer.AddFunctionImport(
                            operation.Name, (EdmFunction)operation, entitySetReferenceExpression);
                    }
                }
            }
        }
Example #15
0
        public static IEdmModel CreateTripPinServiceModel(string ns)
        {
            EdmModel model            = new EdmModel();
            var      defaultContainer = new EdmEntityContainer(ns, "DefaultContainer");

            model.AddElement(defaultContainer);

            var genderType = new EdmEnumType(ns, "PersonGender", isFlags: false);

            genderType.AddMember("Male", new EdmEnumMemberValue(0));
            genderType.AddMember("Female", new EdmEnumMemberValue(1));
            genderType.AddMember("Unknown", new EdmEnumMemberValue(2));
            model.AddElement(genderType);

            var cityType = new EdmComplexType(ns, "City");

            cityType.AddProperty(new EdmStructuralProperty(cityType, "CountryRegion", EdmCoreModel.Instance.GetString(false)));
            cityType.AddProperty(new EdmStructuralProperty(cityType, "Name", EdmCoreModel.Instance.GetString(false)));
            cityType.AddProperty(new EdmStructuralProperty(cityType, "Region", EdmCoreModel.Instance.GetString(false)));
            model.AddElement(cityType);

            var locationType = new EdmComplexType(ns, "Location", null, false, true);

            locationType.AddProperty(new EdmStructuralProperty(locationType, "Address", EdmCoreModel.Instance.GetString(false)));
            locationType.AddProperty(new EdmStructuralProperty(locationType, "City", new EdmComplexTypeReference(cityType, false)));
            model.AddElement(locationType);

            var eventLocationType = new EdmComplexType(ns, "EventLocation", locationType, false, true);

            eventLocationType.AddProperty(new EdmStructuralProperty(eventLocationType, "BuildingInfo", EdmCoreModel.Instance.GetString(true)));
            model.AddElement(eventLocationType);

            var airportLocationType = new EdmComplexType(ns, "AirportLocation", locationType, false, true);

            airportLocationType.AddProperty(new EdmStructuralProperty(airportLocationType, "Loc", EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeographyPoint, false)));
            model.AddElement(airportLocationType);

            var photoType       = new EdmEntityType(ns, "Photo", null, false, false, true);
            var photoIdProperty = new EdmStructuralProperty(photoType, "Id", EdmCoreModel.Instance.GetInt64(false));

            photoType.AddProperty(photoIdProperty);
            photoType.AddKeys(photoIdProperty);
            photoType.AddProperty(new EdmStructuralProperty(photoType, "Name", EdmCoreModel.Instance.GetString(true)));
            model.AddElement(photoType);

            var photoSet = new EdmEntitySet(defaultContainer, "Photos", photoType);

            defaultContainer.AddElement(photoSet);

            var personType       = new EdmEntityType(ns, "Person", null, false, /* isOpen */ true);
            var personIdProperty = new EdmStructuralProperty(personType, "UserName", EdmCoreModel.Instance.GetString(false));

            personType.AddProperty(personIdProperty);
            personType.AddKeys(personIdProperty);
            personType.AddProperty(new EdmStructuralProperty(personType, "FirstName", EdmCoreModel.Instance.GetString(false)));
            personType.AddProperty(new EdmStructuralProperty(personType, "LastName", EdmCoreModel.Instance.GetString(false)));
            personType.AddProperty(new EdmStructuralProperty(personType, "Emails", new EdmCollectionTypeReference(new EdmCollectionType(EdmCoreModel.Instance.GetString(true)))));
            personType.AddProperty(new EdmStructuralProperty(personType, "AddressInfo", new EdmCollectionTypeReference(new EdmCollectionType(new EdmComplexTypeReference(locationType, true)))));
            personType.AddProperty(new EdmStructuralProperty(personType, "Gender", new EdmEnumTypeReference(genderType, true)));
            personType.AddProperty(new EdmStructuralProperty(personType, "Concurrency", EdmCoreModel.Instance.GetInt64(false)));
            model.AddElement(personType);

            var personSet = new EdmEntitySet(defaultContainer, "People", personType);

            defaultContainer.AddElement(personSet);

            var airlineType     = new EdmEntityType(ns, "Airline");
            var airlineCodeProp = new EdmStructuralProperty(airlineType, "AirlineCode", EdmCoreModel.Instance.GetString(false));

            airlineType.AddKeys(airlineCodeProp);
            airlineType.AddProperty(airlineCodeProp);
            airlineType.AddProperty(new EdmStructuralProperty(airlineType, "Name", EdmCoreModel.Instance.GetString(false)));

            model.AddElement(airlineType);
            var airlineSet = new EdmEntitySet(defaultContainer, "Airlines", airlineType);

            defaultContainer.AddElement(airlineSet);

            var airportType   = new EdmEntityType(ns, "Airport");
            var airportIdType = new EdmStructuralProperty(airportType, "IcaoCode", EdmCoreModel.Instance.GetString(false));

            airportType.AddProperty(airportIdType);
            airportType.AddKeys(airportIdType);
            airportType.AddProperty(new EdmStructuralProperty(airportType, "Name", EdmCoreModel.Instance.GetString(false)));
            airportType.AddProperty(new EdmStructuralProperty(airportType, "IataCode", EdmCoreModel.Instance.GetString(false)));
            airportType.AddProperty(new EdmStructuralProperty(airportType, "Location", new EdmComplexTypeReference(airportLocationType, false)));
            model.AddElement(airportType);

            var airportSet = new EdmEntitySet(defaultContainer, "Airports", airportType);

            defaultContainer.AddElement(airportSet);

            var planItemType   = new EdmEntityType(ns, "PlanItem");
            var planItemIdType = new EdmStructuralProperty(planItemType, "PlanItemId", EdmCoreModel.Instance.GetInt32(false));

            planItemType.AddProperty(planItemIdType);
            planItemType.AddKeys(planItemIdType);
            planItemType.AddProperty(new EdmStructuralProperty(planItemType, "ConfirmationCode", EdmCoreModel.Instance.GetString(true)));
            planItemType.AddProperty(new EdmStructuralProperty(planItemType, "StartsAt", EdmCoreModel.Instance.GetDateTimeOffset(true)));
            planItemType.AddProperty(new EdmStructuralProperty(planItemType, "EndsAt", EdmCoreModel.Instance.GetDateTimeOffset(true)));
            planItemType.AddProperty(new EdmStructuralProperty(planItemType, "Duration", EdmCoreModel.Instance.GetDuration(true)));
            model.AddElement(planItemType);

            var publicTransportationType = new EdmEntityType(ns, "PublicTransportation", planItemType);

            publicTransportationType.AddProperty(new EdmStructuralProperty(publicTransportationType, "SeatNumber", EdmCoreModel.Instance.GetString(true)));
            model.AddElement(publicTransportationType);

            var flightType       = new EdmEntityType(ns, "Flight", publicTransportationType);
            var flightNumberType = new EdmStructuralProperty(flightType, "FlightNumber", EdmCoreModel.Instance.GetString(false));

            flightType.AddProperty(flightNumberType);
            model.AddElement(flightType);

            var eventType = new EdmEntityType(ns, "Event", planItemType, false, true);

            eventType.AddProperty(new EdmStructuralProperty(eventType, "Description", EdmCoreModel.Instance.GetString(true)));
            eventType.AddProperty(new EdmStructuralProperty(eventType, "OccursAt", new EdmComplexTypeReference(eventLocationType, false)));
            model.AddElement(eventType);

            var tripType   = new EdmEntityType(ns, "Trip");
            var tripIdType = new EdmStructuralProperty(tripType, "TripId", EdmCoreModel.Instance.GetInt32(false));

            tripType.AddProperty(tripIdType);
            tripType.AddKeys(tripIdType);
            tripType.AddProperty(new EdmStructuralProperty(tripType, "ShareId", EdmCoreModel.Instance.GetGuid(true)));
            tripType.AddProperty(new EdmStructuralProperty(tripType, "Description", EdmCoreModel.Instance.GetString(true)));
            tripType.AddProperty(new EdmStructuralProperty(tripType, "Name", EdmCoreModel.Instance.GetString(false)));
            tripType.AddProperty(new EdmStructuralProperty(tripType, "Budget", EdmCoreModel.Instance.GetSingle(false)));
            tripType.AddProperty(new EdmStructuralProperty(tripType, "StartsAt", EdmCoreModel.Instance.GetDateTimeOffset(false)));
            tripType.AddProperty(new EdmStructuralProperty(tripType, "EndsAt", EdmCoreModel.Instance.GetDateTimeOffset(false)));
            tripType.AddProperty(new EdmStructuralProperty(tripType, "Tags", new EdmCollectionTypeReference(new EdmCollectionType(EdmCoreModel.Instance.GetString(false)))));
            model.AddElement(tripType);

            var friendsnNavigation = personType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo()
            {
                Name               = "Friends",
                Target             = personType,
                TargetMultiplicity = EdmMultiplicity.Many
            });

            var personTripNavigation = personType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo()
            {
                Name               = "Trips",
                Target             = tripType,
                TargetMultiplicity = EdmMultiplicity.Many,
                ContainsTarget     = true
            });

            var personPhotoNavigation = personType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo()
            {
                Name               = "Photo",
                Target             = photoType,
                TargetMultiplicity = EdmMultiplicity.ZeroOrOne,
            });

            var tripPhotosNavigation = tripType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo()
            {
                Name               = "Photos",
                Target             = photoType,
                TargetMultiplicity = EdmMultiplicity.Many,
            });

            var tripItemNavigation = tripType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo()
            {
                Name               = "PlanItems",
                Target             = planItemType,
                ContainsTarget     = true,
                TargetMultiplicity = EdmMultiplicity.Many
            });

            var flightFromAirportNavigation = flightType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo()
            {
                Name               = "From",
                Target             = airportType,
                TargetMultiplicity = EdmMultiplicity.One
            });

            var flightToAirportNavigation = flightType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo()
            {
                Name               = "To",
                Target             = airportType,
                TargetMultiplicity = EdmMultiplicity.One
            });

            var flightAirlineNavigation = flightType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo()
            {
                Name               = "Airline",
                Target             = airlineType,
                TargetMultiplicity = EdmMultiplicity.One
            });

            var me = new EdmSingleton(defaultContainer, "Me", personType);

            defaultContainer.AddElement(me);

            personSet.AddNavigationTarget(friendsnNavigation, personSet);
            me.AddNavigationTarget(friendsnNavigation, personSet);

            var path = new EdmPathExpression("Trips/PlanItems/Microsoft.OData.SampleService.Models.TripPin.Flight/Airline");

            personSet.AddNavigationTarget(flightAirlineNavigation, airlineSet, path);
            me.AddNavigationTarget(flightAirlineNavigation, airlineSet, path);

            path = new EdmPathExpression("Trips/PlanItems/Microsoft.OData.SampleService.Models.TripPin.Flight/From");
            personSet.AddNavigationTarget(flightFromAirportNavigation, airportSet, path);
            me.AddNavigationTarget(flightFromAirportNavigation, airportSet, path);

            path = new EdmPathExpression("Trips/PlanItems/Microsoft.OData.SampleService.Models.TripPin.Flight/To");
            personSet.AddNavigationTarget(flightToAirportNavigation, airportSet, path);
            me.AddNavigationTarget(flightToAirportNavigation, airportSet, path);

            personSet.AddNavigationTarget(personPhotoNavigation, photoSet);
            me.AddNavigationTarget(personPhotoNavigation, photoSet);

            path = new EdmPathExpression("Trips/Photos");
            personSet.AddNavigationTarget(tripPhotosNavigation, photoSet, path);
            me.AddNavigationTarget(tripPhotosNavigation, photoSet, path);

            var getFavoriteAirlineFunction = new EdmFunction(ns, "GetFavoriteAirline",
                                                             new EdmEntityTypeReference(airlineType, false), true,
                                                             new EdmPathExpression("person/Trips/PlanItems/Microsoft.OData.SampleService.Models.TripPin.Flight/Airline"), true);

            getFavoriteAirlineFunction.AddParameter("person", new EdmEntityTypeReference(personType, false));
            model.AddElement(getFavoriteAirlineFunction);

            var getInvolvedPeopleFunction = new EdmFunction(ns, "GetInvolvedPeople",
                                                            new EdmCollectionTypeReference(new EdmCollectionType(new EdmEntityTypeReference(personType, false))), true, null, true);

            getInvolvedPeopleFunction.AddParameter("trip", new EdmEntityTypeReference(tripType, false));
            model.AddElement(getInvolvedPeopleFunction);

            var getFriendsTripsFunction = new EdmFunction(ns, "GetFriendsTrips",
                                                          new EdmCollectionTypeReference(new EdmCollectionType(new EdmEntityTypeReference(tripType, false))),
                                                          true, new EdmPathExpression("person/Friends/Trips"), true);

            getFriendsTripsFunction.AddParameter("person", new EdmEntityTypeReference(personType, false));
            getFriendsTripsFunction.AddParameter("userName", EdmCoreModel.Instance.GetString(false));
            model.AddElement(getFriendsTripsFunction);

            var getNearestAirport = new EdmFunction(ns, "GetNearestAirport",
                                                    new EdmEntityTypeReference(airportType, false),
                                                    false, null, true);

            getNearestAirport.AddParameter("lat", EdmCoreModel.Instance.GetDouble(false));
            getNearestAirport.AddParameter("lon", EdmCoreModel.Instance.GetDouble(false));
            model.AddElement(getNearestAirport);
            var getNearestAirportFunctionImport = (IEdmFunctionImport)defaultContainer.AddFunctionImport("GetNearestAirport", getNearestAirport, new EdmPathExpression("Airports"), true);

            var resetDataSourceAction = new EdmAction(ns, "ResetDataSource", null, false, null);

            model.AddElement(resetDataSourceAction);
            defaultContainer.AddActionImport(resetDataSourceAction);

            var shareTripAction = new EdmAction(ns, "ShareTrip", null, true, null);

            shareTripAction.AddParameter("person", new EdmEntityTypeReference(personType, false));
            shareTripAction.AddParameter("userName", EdmCoreModel.Instance.GetString(false));
            shareTripAction.AddParameter("tripId", EdmCoreModel.Instance.GetInt32(false));
            model.AddElement(shareTripAction);

            model.SetDescriptionAnnotation(defaultContainer, "TripPin service is a sample service for OData V4.");
            model.SetOptimisticConcurrencyAnnotation(personSet, personType.StructuralProperties().Where(p => p.Name == "Concurrency"));
            // TODO: currently singleton does not support ETag feature
            // model.SetOptimisticConcurrencyAnnotation(me, personType.StructuralProperties().Where(p => p.Name == "Concurrency"));
            model.SetResourcePathCoreAnnotation(personSet, "People");
            model.SetResourcePathCoreAnnotation(me, "Me");
            model.SetResourcePathCoreAnnotation(airlineSet, "Airlines");
            model.SetResourcePathCoreAnnotation(airportSet, "Airports");
            model.SetResourcePathCoreAnnotation(photoSet, "Photos");
            model.SetResourcePathCoreAnnotation(getNearestAirportFunctionImport, "Microsoft.OData.SampleService.Models.TripPin.GetNearestAirport");
            model.SetDereferenceableIDsCoreAnnotation(defaultContainer, true);
            model.SetConventionalIDsCoreAnnotation(defaultContainer, true);
            model.SetPermissionsCoreAnnotation(personType.FindProperty("UserName"), CorePermission.Read);
            model.SetPermissionsCoreAnnotation(airlineType.FindProperty("AirlineCode"), CorePermission.Read);
            model.SetPermissionsCoreAnnotation(airportType.FindProperty("IcaoCode"), CorePermission.Read);
            model.SetPermissionsCoreAnnotation(planItemType.FindProperty("PlanItemId"), CorePermission.Read);
            model.SetPermissionsCoreAnnotation(tripType.FindProperty("TripId"), CorePermission.Read);
            model.SetPermissionsCoreAnnotation(photoType.FindProperty("Id"), CorePermission.Read);
            model.SetImmutableCoreAnnotation(airportType.FindProperty("IataCode"), true);
            model.SetComputedCoreAnnotation(personType.FindProperty("Concurrency"), true);
            model.SetAcceptableMediaTypesCoreAnnotation(photoType, new[] { "image/jpeg" });
            model.SetConformanceLevelCapabilitiesAnnotation(defaultContainer, CapabilitiesConformanceLevelType.Advanced);
            model.SetSupportedFormatsCapabilitiesAnnotation(defaultContainer, new[] { "application/json;odata.metadata=full;IEEE754Compatible=false;odata.streaming=true", "application/json;odata.metadata=minimal;IEEE754Compatible=false;odata.streaming=true", "application/json;odata.metadata=none;IEEE754Compatible=false;odata.streaming=true" });
            model.SetAsynchronousRequestsSupportedCapabilitiesAnnotation(defaultContainer, true);
            model.SetBatchContinueOnErrorSupportedCapabilitiesAnnotation(defaultContainer, false);
            model.SetNavigationRestrictionsCapabilitiesAnnotation(personSet, CapabilitiesNavigationType.None, new[] { new Tuple <IEdmNavigationProperty, CapabilitiesNavigationType>(friendsnNavigation, CapabilitiesNavigationType.Recursive) });
            model.SetFilterFunctionsCapabilitiesAnnotation(defaultContainer, new[] { "contains", "endswith", "startswith", "length", "indexof", "substring", "tolower", "toupper", "trim", "concat", "year", "month", "day", "hour", "minute", "second", "round", "floor", "ceiling", "cast", "isof" });
            model.SetSearchRestrictionsCapabilitiesAnnotation(personSet, true, CapabilitiesSearchExpressions.None);
            model.SetSearchRestrictionsCapabilitiesAnnotation(airlineSet, true, CapabilitiesSearchExpressions.None);
            model.SetSearchRestrictionsCapabilitiesAnnotation(airportSet, true, CapabilitiesSearchExpressions.None);
            model.SetSearchRestrictionsCapabilitiesAnnotation(photoSet, true, CapabilitiesSearchExpressions.None);
            model.SetInsertRestrictionsCapabilitiesAnnotation(personSet, true, new[] { personTripNavigation, friendsnNavigation });
            model.SetInsertRestrictionsCapabilitiesAnnotation(airlineSet, true, null);
            model.SetInsertRestrictionsCapabilitiesAnnotation(airportSet, false, null);
            model.SetInsertRestrictionsCapabilitiesAnnotation(photoSet, true, null);
            // TODO: model.SetUpdateRestrictionsCapabilitiesAnnotation();
            model.SetDeleteRestrictionsCapabilitiesAnnotation(airportSet, false, null);
            model.SetISOCurrencyMeasuresAnnotation(tripType.FindProperty("Budget"), "USD");
            model.SetScaleMeasuresAnnotation(tripType.FindProperty("Budget"), 2);

            return(model);
        }