Example #1
0
        public void CanCreateDerivedComplexType()
        {
            // Arrange
            ODataModelBuilder builder = new ODataModelBuilder();

            builder.ComplexType <BaseComplexType>().Abstract().Property(v => v.BaseProperty);
            builder.ComplexType <DerivedComplexType>().DerivesFrom <BaseComplexType>().Property(v => v.DerivedProperty);

            // Act
            IEdmModel model = builder.GetEdmModel();

            // Assert
            IEdmComplexType baseComplexType = model.AssertHasComplexType(typeof(BaseComplexType));

            Assert.Null(baseComplexType.BaseComplexType());
            Assert.Single(baseComplexType.Properties());
            baseComplexType.AssertHasPrimitiveProperty(model, "BaseProperty", EdmPrimitiveTypeKind.String, true);

            IEdmComplexType derivedComplexType = model.AssertHasComplexType(typeof(DerivedComplexType));

            Assert.Equal(baseComplexType, derivedComplexType.BaseComplexType());
            Assert.Equal(2, derivedComplexType.Properties().Count());
            derivedComplexType.AssertHasPrimitiveProperty(model, "BaseProperty", EdmPrimitiveTypeKind.String, true);
            derivedComplexType.AssertHasPrimitiveProperty(model, "DerivedProperty", EdmPrimitiveTypeKind.Int32, false);
        }
Example #2
0
        internal static bool ContainsProperty(this IEdmType type, IEdmProperty property)
        {
            Func <IEdmProperty, bool>           predicate = null;
            Func <IEdmProperty, bool>           func2     = null;
            Func <IEdmNavigationProperty, bool> func3     = null;
            IEdmComplexType type2 = type as IEdmComplexType;

            if (type2 != null)
            {
                if (predicate == null)
                {
                    predicate = p => p == property;
                }
                return(type2.Properties().Any <IEdmProperty>(predicate));
            }
            IEdmEntityType type3 = type as IEdmEntityType;

            if (type3 == null)
            {
                return(false);
            }
            if (func2 == null)
            {
                func2 = p => p == property;
            }
            if (type3.Properties().Any <IEdmProperty>(func2))
            {
                return(true);
            }
            if (func3 == null)
            {
                func3 = p => p == property;
            }
            return(type3.NavigationProperties().Any <IEdmNavigationProperty>(func3));
        }
Example #3
0
        /// <summary>
        /// Parses the next OData path segment following a complex-typed segment.
        /// </summary>
        /// <param name="model">The model to use for path parsing.</param>
        /// <param name="previous">The previous path segment.</param>
        /// <param name="previousEdmType">The EDM type of the OData path up to the previous segment.</param>
        /// <param name="segment">The value of the segment to parse.</param>
        /// <returns>A parsed representation of the segment.</returns>
        protected virtual ODataPathSegment ParseAtComplex(IEdmModel model, ODataPathSegment previous, IEdmType previousEdmType, string segment)
        {
            if (previous == null)
            {
                throw Error.ArgumentNull("previous");
            }
            if (String.IsNullOrEmpty(segment))
            {
                throw Error.Argument(SRResources.SegmentNullOrEmpty);
            }

            IEdmComplexType previousType = previousEdmType as IEdmComplexType;

            if (previousType == null)
            {
                throw Error.Argument(SRResources.PreviousSegmentMustBeComplexType, previousEdmType);
            }

            // look for properties
            IEdmProperty property = previousType.Properties().SingleOrDefault(p => p.Name == segment);

            if (property != null)
            {
                return(new PropertyAccessPathSegment(property));
            }

            // Treating as an open property
            return(new UnresolvedPathSegment(segment));
        }
Example #4
0
        public void GetEdmModel_Works_ForOpenComplexTypeWithDerivedDynamicProperty()
        {
            // Arrange
            ODataConventionModelBuilder builder = ODataConventionModelBuilderFactory.Create();
            builder.ComplexType<OpenComplexTypeWithDerivedDynamicProperty>();

            // Act
            IEdmModel model = builder.GetEdmModel();

            // Assert
            Assert.NotNull(model);
            IEdmComplexType complexType = Assert.Single(model.SchemaElements.OfType<IEdmComplexType>());
            Assert.True(complexType.IsOpen);
            IEdmProperty edmProperty = Assert.Single(complexType.Properties());
            Assert.Equal("StringProperty", edmProperty.Name);
        }
Example #5
0
        public void GetEdmModel_WorksOnModelBuilder_ForOpenComplexType()
        {
            // Arrange
            ODataModelBuilder builder = new ODataModelBuilder();
            ComplexTypeConfiguration<SimpleOpenComplexType> complex = builder.ComplexType<SimpleOpenComplexType>();
            complex.Property(c => c.IntProperty);
            complex.HasDynamicProperties(c => c.DynamicProperties);

            // Act
            IEdmModel model = builder.GetEdmModel();

            // Assert
            Assert.NotNull(model);
            IEdmComplexType complexType = Assert.Single(model.SchemaElements.OfType<IEdmComplexType>());
            Assert.True(complexType.IsOpen);
            IEdmProperty edmProperty = Assert.Single(complexType.Properties());
            Assert.Equal("IntProperty", edmProperty.Name);
        }
Example #6
0
        public void GetEdmModel_WorksOnConventionModelBuilder_ForOpenComplexType()
        {
            // Arrange
            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();

            builder.ComplexType <SimpleOpenComplexType>();

            // Act
            IEdmModel model = builder.GetEdmModel();

            // Assert
            Assert.NotNull(model);
            IEdmComplexType complexType = Assert.Single(model.SchemaElements.OfType <IEdmComplexType>());

            Assert.True(complexType.IsOpen);
            IEdmProperty edmProperty = Assert.Single(complexType.Properties());

            Assert.Equal("IntProperty", edmProperty.Name);
        }
Example #7
0
        public void ODataConventionModelBuilder_IgnoresIndexerProperties()
        {
            MockType type =
                new MockType("ComplexType")
                .Property <int>("Item");

            MockPropertyInfo pi = type.GetProperty("Item");

            pi.Setup(p => p.GetIndexParameters()).Returns(new[] { new Mock <ParameterInfo>().Object }); // make it indexer

            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();

            builder.AddComplexType(type);

            IEdmModel       model       = builder.GetEdmModel();
            IEdmComplexType complexType = model.AssertHasComplexType(type);

            Assert.Empty(complexType.Properties());
        }
Example #8
0
        public void CanDefinePropertyOnDerivedType_NotPresentInBaseType_ButPresentInDerivedType()
        {
            // Arrange
            ODataModelBuilder builder = new ODataModelBuilder();
            builder.ComplexType<DerivedComplexType>().DerivesFrom<BaseComplexType>().Property(m => m.BaseProperty);

            // Act
            IEdmModel model = builder.GetEdmModel();

            // Assert
            IEdmComplexType baseComplex = model.AssertHasComplexType(typeof(BaseComplexType));
            Assert.Null(baseComplex.BaseComplexType());
            Assert.Empty(baseComplex.Properties());

            IEdmComplexType derivedComplex = model.AssertHasComplexType(typeof(DerivedComplexType));
            Assert.Equal(baseComplex, derivedComplex.BaseComplexType());
            Assert.Single(derivedComplex.Properties());
            derivedComplex.AssertHasPrimitiveProperty(model, "BaseProperty", EdmPrimitiveTypeKind.String, true);
        }
        public void ConvertComplexType_Inheritance()
        {
            var taupoModel = new EntityModelSchema()
            {
                new ComplexType("NS1", "BaseComplex")
                {
                    new MemberProperty("p1", EdmDataTypes.Int16),
                },
                new ComplexType("NS2", "DerivedComplex")
                {
                    BaseType   = "BaseComplex",
                    Properties = { new MemberProperty("p2", EdmDataTypes.Int16) },
                },
            }
            .Resolve();

            IEdmModel result = this.converter.ConvertToEdmModel(taupoModel);

            Assert.IsNull(result.EntityContainer);
            Assert.AreEqual(2, result.SchemaElements.Count());
            Assert.AreEqual(2, result.SchemaElements.OfType <IEdmComplexType>().Count());

            IEdmComplexType baseComplex = result.SchemaElements.OfType <IEdmComplexType>().ElementAt(0);

            Assert.AreEqual("NS1.BaseComplex", baseComplex.FullName());
            Assert.AreEqual(1, baseComplex.DeclaredStructuralProperties().Count());
            Assert.AreEqual("p1", baseComplex.DeclaredStructuralProperties().First().Name);

            IEdmComplexType derivedComplex = result.SchemaElements.OfType <IEdmComplexType>().ElementAt(1);

            Assert.AreEqual("NS2.DerivedComplex", derivedComplex.FullName());
            Assert.AreEqual(1, derivedComplex.DeclaredStructuralProperties().Count());
            Assert.AreEqual("p2", derivedComplex.DeclaredStructuralProperties().First().Name);

            Assert.AreEqual(2, derivedComplex.StructuralProperties().Count());
            Assert.AreEqual(2, derivedComplex.Properties().Count());
            Assert.AreEqual(baseComplex, derivedComplex.BaseComplexType());
        }
Example #10
0
        internal bool WriteComplexValue(
            ODataComplexValue complexValue,
            IEdmTypeReference metadataTypeReference,
            bool isOpenPropertyType,
            bool isWritingCollection,
            Action beforeValueAction,
            Action afterValueAction,
            DuplicatePropertyNamesChecker duplicatePropertyNamesChecker,
            CollectionWithoutExpectedTypeValidator collectionValidator,
            EpmValueCache epmValueCache,
            EpmSourcePathSegment epmSourcePathSegment,
            ProjectedPropertiesAnnotation projectedProperties)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(complexValue != null, "complexValue != null");

            string typeName = complexValue.TypeName;

            if (collectionValidator != null)
            {
                collectionValidator.ValidateCollectionItem(typeName, EdmTypeKind.Complex);
            }

            this.IncreaseRecursionDepth();

            // resolve the type name to the type; if no type name is specified we will use the
            // type inferred from metadata
            IEdmComplexTypeReference complexTypeReference = TypeNameOracle.ResolveAndValidateTypeNameForValue(this.Model, metadataTypeReference, complexValue, isOpenPropertyType).AsComplexOrNull();

            string collectionItemTypeName;

            typeName = this.AtomOutputContext.TypeNameOracle.GetValueTypeNameForWriting(complexValue, complexTypeReference, complexValue.GetAnnotation <SerializationTypeNameAnnotation>(), collectionValidator, out collectionItemTypeName);
            Debug.Assert(collectionItemTypeName == null, "collectionItemTypeName == null");

            Action beforeValueCallbackWithTypeName = beforeValueAction;

            if (typeName != null)
            {
                // The beforeValueAction (if specified) will write the actual property element start.
                // So if we are to write the type attribute, we must postpone that after the start element was written.
                // And so we chain the existing action with our type attribute writing and use that
                // as the before action instead.
                if (beforeValueAction != null)
                {
                    beforeValueCallbackWithTypeName = () =>
                    {
                        beforeValueAction();
                        this.WritePropertyTypeAttribute(typeName);
                    };
                }
                else
                {
                    this.WritePropertyTypeAttribute(typeName);
                }
            }

            // NOTE: see the comments on ODataWriterBehavior.UseV1ProviderBehavior for more information
            // NOTE: We have to check for ProjectedPropertiesAnnotation.Empty here to avoid filling the cache for
            //       complex values we are writing only to ensure we don't have nested EPM-mapped null values
            //       that will end up in the content eventually.
            if (this.MessageWriterSettings.WriterBehavior != null &&
                this.MessageWriterSettings.WriterBehavior.UseV1ProviderBehavior &&
                !object.ReferenceEquals(projectedProperties, ProjectedPropertiesAnnotation.EmptyProjectedPropertiesInstance))
            {
                IEdmComplexType complexType = (IEdmComplexType)complexTypeReference.Definition;
                CachedPrimitiveKeepInContentAnnotation keepInContentCache = this.Model.EpmCachedKeepPrimitiveInContent(complexType);
                if (keepInContentCache == null)
                {
                    // we are about to write the first value of the given type; compute the keep-in-content information for the primitive properties of this type.
                    List <string> keepInContentPrimitiveProperties = null;

                    // initialize the cache with all primitive properties
                    foreach (IEdmProperty edmProperty in complexType.Properties().Where(p => p.Type.IsODataPrimitiveTypeKind()))
                    {
                        // figure out the keep-in-content value
                        EntityPropertyMappingAttribute entityPropertyMapping = EpmWriterUtils.GetEntityPropertyMapping(epmSourcePathSegment, edmProperty.Name);
                        if (entityPropertyMapping != null && entityPropertyMapping.KeepInContent)
                        {
                            if (keepInContentPrimitiveProperties == null)
                            {
                                keepInContentPrimitiveProperties = new List <string>();
                            }

                            keepInContentPrimitiveProperties.Add(edmProperty.Name);
                        }
                    }

                    this.Model.SetAnnotationValue <CachedPrimitiveKeepInContentAnnotation>(complexType, new CachedPrimitiveKeepInContentAnnotation(keepInContentPrimitiveProperties));
                }
            }

            bool propertyWritten = this.WriteProperties(
                complexTypeReference == null ? null : complexTypeReference.ComplexDefinition(),
                EpmValueCache.GetComplexValueProperties(epmValueCache, complexValue, true),
                isWritingCollection,
                beforeValueCallbackWithTypeName,
                afterValueAction,
                duplicatePropertyNamesChecker,
                epmValueCache,
                epmSourcePathSegment,
                projectedProperties);

            this.DecreaseRecursionDepth();
            return(propertyWritten);
        }
Example #11
0
        internal bool WriteComplexValue(ODataComplexValue complexValue, IEdmTypeReference metadataTypeReference, bool isOpenPropertyType, bool isWritingCollection, Action beforeValueAction, Action afterValueAction, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, CollectionWithoutExpectedTypeValidator collectionValidator, EpmValueCache epmValueCache, EpmSourcePathSegment epmSourcePathSegment, ProjectedPropertiesAnnotation projectedProperties)
        {
            Action action2  = null;
            string typeName = complexValue.TypeName;

            if (collectionValidator != null)
            {
                collectionValidator.ValidateCollectionItem(typeName, EdmTypeKind.Complex);
            }
            this.IncreaseRecursionDepth();
            IEdmComplexTypeReference reference = WriterValidationUtils.ResolveTypeNameForWriting(base.Model, metadataTypeReference, ref typeName, EdmTypeKind.Complex, isOpenPropertyType).AsComplexOrNull();

            if (((typeName != null) && (collectionValidator != null)) && (string.CompareOrdinal(collectionValidator.ItemTypeNameFromCollection, typeName) == 0))
            {
                typeName = null;
            }
            SerializationTypeNameAnnotation annotation = complexValue.GetAnnotation <SerializationTypeNameAnnotation>();

            if (annotation != null)
            {
                typeName = annotation.TypeName;
            }
            Action beforePropertiesAction = beforeValueAction;

            if (typeName != null)
            {
                if (beforeValueAction != null)
                {
                    if (action2 == null)
                    {
                        action2 = delegate {
                            beforeValueAction();
                            this.WritePropertyTypeAttribute(typeName);
                        };
                    }
                    beforePropertiesAction = action2;
                }
                else
                {
                    this.WritePropertyTypeAttribute(typeName);
                }
            }
            if (((base.MessageWriterSettings.WriterBehavior != null) && base.MessageWriterSettings.WriterBehavior.UseV1ProviderBehavior) && !object.ReferenceEquals(projectedProperties, ProjectedPropertiesAnnotation.EmptyProjectedPropertiesMarker))
            {
                IEdmComplexType definition = (IEdmComplexType)reference.Definition;
                if (base.Model.EpmCachedKeepPrimitiveInContent(definition) == null)
                {
                    List <string> keptInContentPropertyNames = null;
                    foreach (IEdmProperty property in from p in definition.Properties()
                             where p.Type.IsODataPrimitiveTypeKind()
                             select p)
                    {
                        EntityPropertyMappingAttribute entityPropertyMapping = EpmWriterUtils.GetEntityPropertyMapping(epmSourcePathSegment, property.Name);
                        if ((entityPropertyMapping != null) && entityPropertyMapping.KeepInContent)
                        {
                            if (keptInContentPropertyNames == null)
                            {
                                keptInContentPropertyNames = new List <string>();
                            }
                            keptInContentPropertyNames.Add(property.Name);
                        }
                    }
                    base.Model.SetAnnotationValue <CachedPrimitiveKeepInContentAnnotation>(definition, new CachedPrimitiveKeepInContentAnnotation(keptInContentPropertyNames));
                }
            }
            bool flag = this.WriteProperties((reference == null) ? null : reference.ComplexDefinition(), EpmValueCache.GetComplexValueProperties(epmValueCache, complexValue, true), isWritingCollection, beforePropertiesAction, afterValueAction, duplicatePropertyNamesChecker, epmValueCache, epmSourcePathSegment, projectedProperties);

            this.DecreaseRecursionDepth();
            return(flag);
        }