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); }
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)); }
/// <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)); }
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); }
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); }
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); }
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()); }
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()); }
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); }
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); }