/// <summary>
        /// Sets the expected property for the top-level property instance.
        /// </summary>
        /// <param name="property">The property instance to set the expected property for.</param>
        /// <param name="owningType">The type owning the expected property.</param>
        /// <param name="expectedPropertyName">The name of the property to set as the expected property.</param>
        /// <returns>The <paramref name="property"/> after its expected property was set.</returns>
        public static PropertyInstance ExpectedProperty(
            this PropertyInstance property,
            NamedStructuralType owningType,
            string expectedPropertyName)
        {
            ExceptionUtilities.CheckArgumentNotNull(property, "property");
            ExceptionUtilities.CheckArgumentNotNull(owningType, "owningType");
            ExceptionUtilities.CheckStringArgumentIsNotNullOrEmpty(expectedPropertyName, "expectedPropertyName");

            ExpectedTypeODataPayloadElementAnnotation annotation = AddExpectedTypeAnnotation(property);

            annotation.OwningType = owningType;
            MemberProperty memberProperty = owningType.GetProperty(expectedPropertyName);

            if (memberProperty != null)
            {
                annotation.MemberProperty = memberProperty;
                annotation.ExpectedType   = memberProperty.PropertyType;
            }
            else
            {
                ExceptionUtilities.Assert(owningType.IsOpen, "For non-declared properties the owning type must be open.");
                annotation.OpenMemberPropertyName = expectedPropertyName;
            }

            return(property);
        }
        /// <summary>
        /// Sets the expected base entity type for the top-level entity set.
        /// </summary>
        /// <param name="entitySetInstance">The entity set instance to set the expected set for.</param>
        /// <param name="entitySet">The entity set the entities belong to.</param>
        /// <param name="baseEntityType">The base entity type to set as the expected base entity type.</param>
        /// <returns>The <paramref name="entitySetInstance"/> after its expected type was set.</returns>
        public static EntitySetInstance ExpectedEntityType(this EntitySetInstance entitySetInstance, EntitySet entitySet, EntityDataType baseEntityType)
        {
            ExceptionUtilities.CheckArgumentNotNull(entitySetInstance, "entitySetInstance");
            ExpectedTypeODataPayloadElementAnnotation annotation = AddExpectedTypeAnnotation(entitySetInstance);
            EntityDataType entityType = baseEntityType ?? (entitySet == null ? null : DataTypes.EntityType.WithDefinition(entitySet.EntityType));

            annotation.ExpectedType = entityType;
            annotation.EntitySet    = entitySet;
            return(entitySetInstance);
        }
        /// <summary>
        /// Sets the expected base entity type for the top-level entity set.
        /// </summary>
        /// <param name="entitySetInstance">The entity set instance to set the expected set for.</param>
        /// <param name="entitySet">The entity set the entities belong to.</param>
        /// <param name="baseEntityType">The base entity type to set as the expected base entity type.</param>
        /// <returns>The <paramref name="entitySetInstance"/> after its expected type was set.</returns>
        public static EntitySetInstance ExpectedEntityType(this EntitySetInstance entitySetInstance, IEdmTypeReference baseEntityType, IEdmEntitySet entitySet = null)
        {
            ExceptionUtilities.CheckArgumentNotNull(entitySetInstance, "entitySetInstance");
            ExpectedTypeODataPayloadElementAnnotation annotation = ODataPayloadElementExtensions.AddExpectedTypeAnnotation(entitySetInstance);
            var entityType = baseEntityType ?? (entitySet == null ? null : entitySet.EntityType().ToTypeReference());

            annotation.EdmExpectedType = entityType;
            annotation.EdmEntitySet    = entitySet;
            return(entitySetInstance);
        }
        /// <summary>
        /// Sets the expected function import for a top-level payload element.
        /// </summary>
        /// <param name="payloadElement">The payload element to set the expected function import for.</param>
        /// <param name="functionImport">The function import to set.</param>
        /// <returns>The <paramref name="payloadElement"/> after its expected function import was set.</returns>
        public static T ExpectedFunctionImport <T>(
            this T payloadElement,
            EdmOperationImport functionImport) where T : ODataPayloadElement
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");

            ExpectedTypeODataPayloadElementAnnotation annotation = AddExpectedTypeAnnotation(payloadElement);

            annotation.ProductFunctionImport = functionImport;
            return(payloadElement);
        }
        /// <summary>
        /// Gets or adds the expected type annotation.
        /// </summary>
        /// <param name="payloadElement">The payload element to get or add the annotation to.</param>
        /// <returns>The expected type annotation to use.</returns>
        public static ExpectedTypeODataPayloadElementAnnotation AddExpectedTypeAnnotation(this ODataPayloadElement payloadElement)
        {
            Debug.Assert(payloadElement != null, "payloadElement != null");

            var expectedTypeAnnotation = payloadElement.GetAnnotation <ExpectedTypeODataPayloadElementAnnotation>();

            if (expectedTypeAnnotation == null)
            {
                expectedTypeAnnotation = new ExpectedTypeODataPayloadElementAnnotation();
                payloadElement.SetAnnotation(expectedTypeAnnotation);
            }

            return(expectedTypeAnnotation);
        }
        /// <summary>
        /// Gets or adds the expected type annotation.
        /// </summary>
        /// <param name="payloadElement">The payload element to get or add the annotation to.</param>
        /// <returns>The expected type annotation to use.</returns>
        public static ExpectedTypeODataPayloadElementAnnotation AddExpectedTypeAnnotation(this ODataPayloadElement payloadElement, IEdmType expectedType)
        {
            Debug.Assert(payloadElement != null, "payloadElement != null");

            var expectedTypeAnnotation = payloadElement.GetAnnotation <ExpectedTypeODataPayloadElementAnnotation>();

            if (expectedTypeAnnotation == null)
            {
                expectedTypeAnnotation = new ExpectedTypeODataPayloadElementAnnotation();
                payloadElement.SetAnnotation(expectedTypeAnnotation);
            }

            expectedTypeAnnotation.EdmExpectedType = expectedType.ToTypeReference();
            return(expectedTypeAnnotation);
        }
        /// <summary>
        /// Sets the expected navigation property for a top-level entity reference links collection.
        /// </summary>
        /// <param name="entityReferenceLinks">The entity reference links collection to set the expected navigation property for.</param>
        /// <param name="owningType">The type owning the expected property.</param>
        /// <param name="navigationPropertyName">The name of the navigation property to set as the expected property.</param>
        /// <returns>The <paramref name="entityReferenceLinks"/> after its expected property was set.</returns>
        public static LinkCollection ExpectedNavigationProperty(
            this LinkCollection entityReferenceLinks,
            EntitySet entitySet,
            EntityType owningType,
            string navigationPropertyName)
        {
            ExceptionUtilities.CheckArgumentNotNull(entityReferenceLinks, "entityReferenceLinks");
            ExceptionUtilities.CheckArgumentNotNull(owningType, "owningType");
            ExceptionUtilities.CheckStringArgumentIsNotNullOrEmpty(navigationPropertyName, "navigationProperty");

            ExpectedTypeODataPayloadElementAnnotation annotation = AddExpectedTypeAnnotation(entityReferenceLinks);

            annotation.EntitySet          = entitySet;
            annotation.OwningType         = owningType;
            annotation.NavigationProperty = owningType.GetNavigationProperty(navigationPropertyName);
            return(entityReferenceLinks);
        }
        /// <summary>
        /// Sets the expected navigation property for a top-level entity reference link.
        /// </summary>
        /// <param name="entityReferenceLink">The entity reference link instance to set the expected navigation property for.</param>
        /// <param name="owningType">The type owning the expected property.</param>
        /// <param name="navigationPropertyName">The name of the navigation property to set as the expected property.</param>
        /// <returns>The <paramref name="entityReferenceLink"/> after its expected property was set.</returns>
        public static DeferredLink ExpectedNavigationProperty(
            this DeferredLink entityReferenceLink,
            IEdmEntitySet entitySet,
            IEdmEntityType owningType,
            string navigationPropertyName)
        {
            ExceptionUtilities.CheckArgumentNotNull(entityReferenceLink, "entityReferenceLink");
            ExceptionUtilities.CheckArgumentNotNull(owningType, "owningType");
            ExceptionUtilities.CheckStringArgumentIsNotNullOrEmpty(navigationPropertyName, "navigationPropertyName");

            ExpectedTypeODataPayloadElementAnnotation annotation = AddExpectedTypeAnnotation(entityReferenceLink);

            annotation.EdmEntitySet          = entitySet;
            annotation.EdmOwningType         = owningType;
            annotation.EdmNavigationProperty = owningType.FindProperty(navigationPropertyName);
            return(entityReferenceLink);
        }
 /// <summary>
 /// Sets an expected type annotation.
 /// </summary>
 /// <param name="payloadElement">The payload element to set the annotation on.</param>
 /// <param name="annotation">The <see cref="ExpectedTypeODataPayloadElementAnnotation"/> to add to <paramref name="payloadElement"/>.</param>
 /// <returns>The annotated <paramref name="payloadElement"/> for composability.</returns>
 public static ODataPayloadElement AddExpectedTypeAnnotation(this ODataPayloadElement payloadElement, ExpectedTypeODataPayloadElementAnnotation annotation)
 {
     Debug.Assert(payloadElement != null, "payloadElement != null");
     payloadElement.SetAnnotation(annotation);
     return(payloadElement);
 }
            /// <summary>
            /// Returns the navigation property for the given payload element (only for entity reference links).
            /// </summary>
            /// <param name="expectedTypeAnnotation">The expected type annotation.</param>
            /// <param name="model">The model to get the navigation property from.</param>
            /// <returns>The expected navigation property for the specified payload element.</returns>
            private static IEdmNavigationProperty GetExpectedNavigationProperty(ExpectedTypeODataPayloadElementAnnotation expectedTypeAnnotation, IEdmModel model)
            {
                ExceptionUtilities.Assert(model != null, "model != null");

                if (expectedTypeAnnotation != null)
                {
                    if (expectedTypeAnnotation.EdmNavigationProperty != null)
                    {
                        return expectedTypeAnnotation.EdmNavigationProperty as IEdmNavigationProperty;
                    }
                    NavigationProperty expectedNavigationProperty = expectedTypeAnnotation.NavigationProperty;
                    if (expectedNavigationProperty != null)
                    {
                        NamedStructuralType expectedOwningType = expectedTypeAnnotation.OwningType;
                        ExceptionUtilities.Assert(expectedOwningType != null, "Need an owning type if a navigation property is specified.");

                        IEdmEntityType owningEntityType = model.FindType(expectedOwningType.FullName) as IEdmEntityType;
                        ExceptionUtilities.Assert(owningEntityType != null, "Did not find expected entity type in the model.");

                        IEdmNavigationProperty navigationProperty = owningEntityType.FindProperty(expectedNavigationProperty.Name) as IEdmNavigationProperty;
                        ExceptionUtilities.Assert(navigationProperty != null, "Did not find expected navigation property in the model.");

                        return navigationProperty;
                    }
                }

                return null;
            }
            /// <summary>
            /// Returns the structural property for the given payload element (only for properties).
            /// </summary>
            /// <param name="expectedTypeAnnotation">The expected type annotation.</param>
            /// <param name="model">The model to get the structural property from.</param>
            /// <returns>The expected structural property for the specified payload element.</returns>
            private static IEdmStructuralProperty GetExpectedStructuralProperty(ExpectedTypeODataPayloadElementAnnotation expectedTypeAnnotation, IEdmModel model)
            {
                ExceptionUtilities.Assert(model != null, "model != null");

                if (expectedTypeAnnotation != null)
                {
                    if (expectedTypeAnnotation.EdmProperty != null)
                    {
                        return expectedTypeAnnotation.EdmProperty as IEdmStructuralProperty;
                    }
                    MemberProperty expectedStructuralProperty = expectedTypeAnnotation.MemberProperty;
                    if (expectedStructuralProperty != null)
                    {
                        NamedStructuralType expectedOwningType = expectedTypeAnnotation.OwningType;
                        ExceptionUtilities.Assert(expectedOwningType != null, "Need an owning type if a structural property is specified.");

                        IEdmStructuredType owningType = model.FindType(expectedOwningType.FullName) as IEdmStructuredType;
                        ExceptionUtilities.Assert(owningType != null, "Did not find expected structured type in the model.");

                        IEdmStructuralProperty structuralProperty = owningType.FindProperty(expectedStructuralProperty.Name) as IEdmStructuralProperty;
                        ExceptionUtilities.Assert(structuralProperty != null, "Did not find expected structural property in the model.");

                        return structuralProperty;
                    }
                }

                return null;
            }
            /// <summary>
            /// Returns the entity set for the given payload element (only for entries and feeds).
            /// </summary>
            /// <param name="expectedTypeAnnotation">The expected type annotation.</param>
            /// <param name="model">The model to get the type from.</param>
            /// <param name="payloadElement">The payload element to get the expected type for.</param>
            /// <returns>The expected type for the specified payload element.</returns>
            private static IEdmEntitySet GetExpectedEntitySet(ExpectedTypeODataPayloadElementAnnotation expectedTypeAnnotation, IEdmModel model, ODataPayloadElement payloadElement)
            {
                ExceptionUtilities.Assert(model != null, "model != null");
                ExceptionUtilities.Assert(payloadElement != null, "payloadElement != null");

                if (payloadElement.GetAnnotation<IgnoreEntitySetAnnotation>() != null)
                {
                    // Entity set information is explicitly ignored
                    return null;
                }

                if (expectedTypeAnnotation != null)
                {
                    if (expectedTypeAnnotation.EdmEntitySet != null)
                    {
                        return expectedTypeAnnotation.EdmEntitySet;
                    }
                    EntitySet entitySet = expectedTypeAnnotation.EntitySet;
                    if (entitySet != null)
                    {
                        return model.EntityContainersAcrossModels().Select(m => m.FindEntitySet(entitySet.Name)).FirstOrDefault(s => s != null);
                    }
                }

                EntityModelTypeAnnotation typeAnnotation = payloadElement.GetAnnotation<EntityModelTypeAnnotation>();
                if (typeAnnotation != null)
                {
                    var edmEntityType = typeAnnotation.EdmModelType;
                    return model.EntityContainersAcrossModels().First().EntitySets().SingleOrDefault(es => es.EntityType().FullName() == edmEntityType.FullName());
                }

                return null;
            }
            /// <summary>
            /// Returns the expected type for the given payload element.
            /// </summary>
            /// <param name="expectedTypeAnnotation">The expected type annotation.</param>
            /// <param name="model">The model to get the type from.</param>
            /// <returns>The expected type for the specified payload element.</returns>
            private static IEdmTypeReference GetExpectedType(ExpectedTypeODataPayloadElementAnnotation expectedTypeAnnotation, IEdmModel model)
            {
                if (expectedTypeAnnotation != null)
                {
                    if (expectedTypeAnnotation.EdmExpectedType != null)
                    {
                        return expectedTypeAnnotation.EdmExpectedType;
                    }
                    if (expectedTypeAnnotation.ExpectedType != null)
                    {
                        DataType expectedDataType = expectedTypeAnnotation.ExpectedType;
                        return EdmModelUtils.ResolveEntityModelSchemaType(model, expectedDataType);
                    }
                }

                return null;
            }
            /// <summary>
            /// Returns the function import for a parameters payload.
            /// </summary>
            /// <param name="expectedTypeAnnotation">The expected type annotation.</param>
            /// <param name="model">The model to get the function import from.</param>
            /// <returns>Returns the function import for a parameters payload.</returns>
            private static IEdmOperationImport GetExpectedFunctionImport(ExpectedTypeODataPayloadElementAnnotation expectedTypeAnnotation, IEdmModel model)
            {
                ExceptionUtilities.Assert(model != null, "model != null");

                if (expectedTypeAnnotation != null)
                {
                    if (expectedTypeAnnotation.ProductFunctionImport != null)
                    {
                        return expectedTypeAnnotation.ProductFunctionImport;
                    }
                    FunctionImport functionImport = expectedTypeAnnotation.FunctionImport;
                    if (functionImport != null)
                    {
                        var container = model.FindEntityContainer(functionImport.Container.FullName);
                        var functionImports = container.FindOperationImports(functionImport.Name);
                        if (functionImports != null && functionImports.Any())
                        {
                            // Note that we don't support overload for Actions. Single() will throw if the model is invalid.
                            return functionImports.Single();
                        }
                    }
                }

                return null;
            }
Ejemplo n.º 15
0
        /// <summary>
        /// Gets the data type of a property value specified in the property instance payload element.
        /// </summary>
        /// <param name="propertyInstance">The property instance payload element to inspect.</param>
        /// <returns>The data type of the property value (can be used to define the metadata for this property).</returns>
        public static IEdmTypeReference GetPayloadEdmElementPropertyValueType(PropertyInstance propertyInstance)
        {
            ExceptionUtilities.CheckArgumentNotNull(propertyInstance, "propertyInstance");

            IEdmTypeReference result = GetEdmTypeFromEntityModelTypeAnnotation(propertyInstance);

            if (result == null)
            {
                switch (propertyInstance.ElementType)
                {
                case ODataPayloadElementType.NullPropertyInstance:
                    NullPropertyInstance nullPropertyInstance = (NullPropertyInstance)propertyInstance;
                    if (nullPropertyInstance.FullTypeName != null)
                    {
                        result = GetPrimitiveEdmType(nullPropertyInstance.FullTypeName);
                        if (result == null)
                        {
                            result = CreateComplexTypeReference(nullPropertyInstance.FullTypeName);
                        }
                    }

                    break;

                case ODataPayloadElementType.PrimitiveProperty:
                    result = GetEdmTypeFromEntityModelTypeAnnotation(((PrimitiveProperty)propertyInstance).Value);
                    if (result == null)
                    {
                        result = GetPrimitiveEdmType(((PrimitiveProperty)propertyInstance).Value.FullTypeName);
                    }

                    break;

                case ODataPayloadElementType.ComplexProperty:
                    result = GetEdmTypeFromEntityModelTypeAnnotation(((ComplexProperty)propertyInstance).Value);
                    if (result == null)
                    {
                        result = CreateComplexTypeReference(((ComplexProperty)propertyInstance).Value.FullTypeName);
                    }

                    break;

                case ODataPayloadElementType.NamedStreamInstance:
                    result = EdmCoreModel.Instance.GetStream(isNullable: false);

                    break;

                case ODataPayloadElementType.PrimitiveMultiValueProperty:
                    PrimitiveMultiValue primitiveMultiValue = ((PrimitiveMultiValueProperty)propertyInstance).Value;
                    result = GetEdmTypeFromEntityModelTypeAnnotation(primitiveMultiValue);
                    if (result == null && primitiveMultiValue.FullTypeName != null)
                    {
                        string itemTypeName = EntityModelUtils.GetCollectionItemTypeName(primitiveMultiValue.FullTypeName);
                        if (itemTypeName != null)
                        {
                            result = EdmCoreModel.GetCollection(GetPrimitiveEdmType(itemTypeName));
                        }
                    }

                    break;

                case ODataPayloadElementType.ComplexMultiValueProperty:
                    ComplexMultiValue complexMultiValue = ((ComplexMultiValueProperty)propertyInstance).Value;
                    result = GetEdmTypeFromEntityModelTypeAnnotation(complexMultiValue);
                    if (result == null && complexMultiValue.FullTypeName != null)
                    {
                        string itemTypeName = EntityModelUtils.GetCollectionItemTypeName(complexMultiValue.FullTypeName);
                        if (itemTypeName != null)
                        {
                            return(EdmCoreModel.GetCollection(CreateComplexTypeReference(itemTypeName)));
                        }
                    }

                    break;

                case ODataPayloadElementType.PrimitiveCollection:
                case ODataPayloadElementType.ComplexInstanceCollection:
                    ExceptionUtilities.Assert(false, "Primitive and complex collections cannot be used in properties but only at the top-level.");
                    return(null);

                default:
                    ExceptionUtilities.Assert(false, "GetPayloadElementPropertyValueType doesn't support '{0}' yet.", propertyInstance.ElementType);
                    return(null);
                }
            }

            // Use the expected type if there's any since it also specifies metadata
            if (result == null)
            {
                ExpectedTypeODataPayloadElementAnnotation expectedTypeAnnotation = propertyInstance.GetAnnotation <ExpectedTypeODataPayloadElementAnnotation>();
                if (expectedTypeAnnotation != null && expectedTypeAnnotation.ExpectedType != null)
                {
                    result = expectedTypeAnnotation.EdmExpectedType;
                }
            }

            return(result);
        }
        private void AddExpectedFunctionImportToCollection(ODataPayloadElementCollection collection)
        {
            var expectedTypeAnnotation = collection.GetAnnotation<ExpectedTypeODataPayloadElementAnnotation>();
            if (expectedTypeAnnotation == null)
            {
                expectedTypeAnnotation = new ExpectedTypeODataPayloadElementAnnotation();
                collection.Add(expectedTypeAnnotation);
            }

            if (expectedTypeAnnotation.ProductFunctionImport == null)
            {
                var typeAnnotation = collection.GetAnnotation<EntityModelTypeAnnotation>();
                var collectionType = typeAnnotation.EdmModelType;

                if (this.testDescriptor.PayloadEdmModel != null)
                {
                    EdmModel model = this.testDescriptor.PayloadEdmModel as EdmModel;
                    EdmEntityContainer container = model.EntityContainer as EdmEntityContainer;
                    var functionImport = container.OperationImports().FirstOrDefault(f =>
                    { return f.Operation.ReturnType != null && f.Operation.ReturnType == collectionType; });
                    if (functionImport == null)
                    {
                        functionImport = container.OperationImports().FirstOrDefault(f =>
                        { return f.Operation.ReturnType != null && f.Operation.ReturnType.IsCollection(); });

                        if (functionImport == null)
                        {
                            var collectionNameAnnotation = collection.GetAnnotation<CollectionNameAnnotation>();
                            container.AddFunctionAndFunctionImport(model, collectionNameAnnotation == null ? "NewFunctionImport" : collectionNameAnnotation.Name,
                                collectionType);
                            this.testDescriptor.ResetCachedModel();
                        }
                    }

                    expectedTypeAnnotation.ProductFunctionImport = functionImport as EdmOperationImport;
                }
            }
        }