/// <summary> /// Visits a property /// </summary> /// <param name="payloadElement">The property to visit</param> /// <param name="value">The value of the property</param> protected override void VisitProperty(PropertyInstance payloadElement, ODataPayloadElement value) { this.VisitProperty(payloadElement, value, null); }
private void VisitProperty(PropertyInstance payloadElement, ODataPayloadElement value, Action action) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); try { var currentType = this.typeStack.Peek(); ExceptionUtilities.CheckObjectNotNull(currentType, "Current type should not be null"); var propertyInfo = currentType.GetProperty(payloadElement.Name); ExceptionUtilities.CheckObjectNotNull(propertyInfo, "Could not find property '{0}' on type '{1}'", payloadElement.Name, currentType); var genericCollectionType = propertyInfo.PropertyType.GetInterfaces().Where(t => t.IsGenericType()).SingleOrDefault(t => typeof(ICollection<>) == t.GetGenericTypeDefinition()); if (genericCollectionType != null) { this.typeStack.Push(genericCollectionType.GetGenericArguments()[0]); } else { this.typeStack.Push(propertyInfo.PropertyType); } base.VisitProperty(payloadElement, value); if (action != null) { action(); } } finally { this.typeStack.Pop(); } }
/// <summary> /// Replace the old property with a new property /// </summary> /// <param name="oldInstance">The old property to be replaced</param> /// <param name="newInstance">The property to replace the old one</param> public void Replace(PropertyInstance oldInstance, PropertyInstance newInstance) { this.properties[this.properties.IndexOf(oldInstance)] = newInstance; }
public void ComplexValueWithMetadataTest() { // Use some standard complex value payloads first IEnumerable<PayloadReaderTestDescriptor> testDescriptors = PayloadReaderTestDescriptorGenerator.CreateComplexValueTestDescriptors(this.Settings, true); // Add metadata validation tests EdmModel model = new EdmModel(); var innerComplexType = model.ComplexType("InnerComplexType"); innerComplexType.AddStructuralProperty("name", EdmCoreModel.Instance.GetString(true)); var complexType = model.ComplexType("ComplexType"); complexType.AddStructuralProperty("number", EdmPrimitiveTypeKind.Int32); complexType.AddStructuralProperty("string", EdmCoreModel.Instance.GetString(true)); complexType.AddStructuralProperty("complex", MetadataUtils.ToTypeReference(innerComplexType, true)); var entityType = model.EntityType("EntityType"); entityType.KeyProperty("Id", EdmCoreModel.Instance.GetInt32(false)); model.Fixup(); // Test that different types of properties not present in the metadata all fail IEnumerable<PropertyInstance> undeclaredPropertyTestCases = new PropertyInstance[] { PayloadBuilder.PrimitiveProperty("undeclared", 42), PayloadBuilder.Property("undeclared", PayloadBuilder.ComplexValue(innerComplexType.FullName())), PayloadBuilder.Property("undeclared", PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.Int32"))), PayloadBuilder.Property("undeclared", PayloadBuilder.ComplexMultiValue(EntityModelUtils.GetCollectionTypeName("TestModel.InnerComplexType"))), }; testDescriptors = testDescriptors.Concat( undeclaredPropertyTestCases.Select(tc => { return new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ComplexValue(complexType.FullName()).WithTypeAnnotation(complexType) .Property(tc), PayloadEdmModel = model, ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_PropertyDoesNotExistOnType", "undeclared", "TestModel.ComplexType"), }; })); testDescriptors = testDescriptors.Concat(new[] { // Property which should take typename not from value but from the parent metadata new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ComplexValue(complexType.FullName()).WithTypeAnnotation(complexType) .Property("complex", PayloadBuilder.ComplexValue(innerComplexType.FullName()).PrimitiveProperty("name", null) .JsonRepresentation("{ \"name\" : null }").XmlRepresentation("<d:name m:null=\"true\" />") .AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null })), PayloadEdmModel = model, }, // Property which is declared in the metadata but with a different type new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ComplexValue(complexType.FullName()).WithTypeAnnotation(complexType) .Property("complex", PayloadBuilder.ComplexValue(complexType.FullName())), PayloadEdmModel = model, ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_IncompatibleType", "TestModel.ComplexType", "TestModel.InnerComplexType"), }, // Property which is declared in the metadata but with a wrong kind new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ComplexValue(complexType.FullName()).WithTypeAnnotation(complexType) .Property("complex", PayloadBuilder.ComplexValue(entityType.FullName())), PayloadEdmModel = model, ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_IncorrectTypeKind", "TestModel.EntityType", "Complex", "Entity"), }, new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ComplexValue("").WithTypeAnnotation(complexType), PayloadEdmModel = model, ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_UnrecognizedTypeName", string.Empty) }, new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ComplexValue("TestModel.NonExistant").WithTypeAnnotation(complexType), PayloadEdmModel = model, ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_UnrecognizedTypeName", "TestModel.NonExistant"), }, }); // Wrap the complex type in a property testDescriptors = testDescriptors .Select((td, index) => new PayloadReaderTestDescriptor(td) { PayloadDescriptor = td.PayloadDescriptor.InProperty("propertyName" + index)}) .SelectMany(td => this.PayloadGenerator.GenerateReaderPayloads(td)); // Handcrafted cases testDescriptors = testDescriptors.Concat(new[] { // Top-level complex property without expected type new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.Property("property", PayloadBuilder.ComplexValue(complexType.FullName()).PrimitiveProperty("number", 42)), PayloadEdmModel = model }, }); this.CombinatorialEngineProvider.RunCombinations( testDescriptors, this.ReaderTestConfigurationProvider.ExplicitFormatConfigurations, (testDescriptor, testConfiguration) => { var property = testDescriptor.PayloadElement as PropertyInstance; if (property != null && testConfiguration.Format == ODataFormat.Atom) { property.Name = null; } testDescriptor.RunTest(testConfiguration); }); }
/// <summary> /// Adds the given property to the complex instance, and sets it as the property's parent /// </summary> /// <param name="toAdd">The property to add</param> public void Add(PropertyInstance toAdd) { this.properties.Add(toAdd); }
/// <summary> /// Removes the given property, if present, and sets it's parent to null /// </summary> /// <param name="toRemove">The property to remove</param> public void Remove(PropertyInstance toRemove) { this.properties.Remove(toRemove); }
/// <summary> /// Helper method for visiting null or empty properties /// </summary> /// <param name="payloadElement">The property to visit</param> protected override void VisitEmptyOrNullProperty(PropertyInstance payloadElement) { base.VisitEmptyOrNullProperty(payloadElement); var property = this.MetadataStack.Peek() as MemberProperty; var navigation = this.MetadataStack.Peek() as NavigationProperty; if (property != null) { ExceptionUtilities.Assert(payloadElement.Name == property.Name, "Property name mismatch"); payloadElement.AddAnnotationIfNotExist(new MemberPropertyAnnotation() { Property = property }); } else { ExceptionUtilities.CheckObjectNotNull(navigation, "Expected property or navigation, got '{0}'", this.MetadataStack.Peek()); ExceptionUtilities.Assert(payloadElement.Name == navigation.Name, "Property name mismatch"); payloadElement.AddAnnotationIfNotExist(new NavigationPropertyAnnotation() { Property = navigation }); var emptyCollection = payloadElement as EmptyCollectionProperty; if (emptyCollection != null && emptyCollection.Value != null) { emptyCollection.Value.AddAnnotationIfNotExist(new EntitySetAnnotation() { EntitySet = this.CurrentEntitySet.GetRelatedEntitySet(navigation) }); } } }
public void UndeclaredClosedPropertyTest() { EdmModel model = new EdmModel(); var entityType = new EdmEntityType("TestModel", "ClosedEntityType"); entityType.AddKeys(entityType.AddStructuralProperty("ID", EdmCoreModel.Instance.GetInt32(false))); model.AddElement(entityType); var complexType = new EdmComplexType("TestModel", "DeclaredComplexType"); complexType.AddStructuralProperty("foo", EdmCoreModel.Instance.GetString(true)); model.AddElement(complexType); var container = new EdmEntityContainer("TestModel", "DefaultContainer"); container.AddEntitySet("ClosedEntitySet", entityType); model.AddElement(container); string propertyName = "UndeclaredProperty"; // Test various types of properties, all of which are undeclared in metadata. IEnumerable<PropertyInstance> testCases = new PropertyInstance[] { // Primitive property PayloadBuilder.PrimitiveProperty(propertyName, 15), // Complex property PayloadBuilder.Property(propertyName, PayloadBuilder.ComplexValue("TestModel.DeclaredComplexType").PrimitiveProperty("foo", "bar")), // Stream property PayloadBuilder.StreamProperty(propertyName, "http://odata.org/readlink"), // Collection property (over primitive type) PayloadBuilder.Property(propertyName, PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.Boolean"))), // Collection property (over declared complex type) PayloadBuilder.Property(propertyName, PayloadBuilder.ComplexMultiValue(EntityModelUtils.GetCollectionTypeName("TestModel.DeclaredComplexType"))), // Collection property (over undeclared complex type) PayloadBuilder.Property(propertyName, PayloadBuilder.ComplexMultiValue(EntityModelUtils.GetCollectionTypeName("TestModel.UndeclaredComplexType"))), // Navigation property PayloadBuilder.NavigationProperty(propertyName, "http://odata.org/navlink"), }; IEnumerable<PayloadReaderTestDescriptor> testDescriptors = testCases.Select(testCase => { return new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.Entity("TestModel.ClosedEntityType") .PrimitiveProperty("ID", 42) .Property(testCase), PayloadEdmModel = model, ExpectedResultCallback = (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings) { ExpectedException = (tc.Format == ODataFormat.Json && testCase is NavigationPropertyInstance) ? tc.IsRequest ? ODataExpectedExceptions.ODataException("ODataJsonLightEntryAndFeedDeserializer_PropertyWithoutValueWithUnknownType", propertyName) : ODataExpectedExceptions.ODataException("ValidationUtils_PropertyDoesNotExistOnType", propertyName, "TestModel.ClosedEntityType") : ODataExpectedExceptions.ODataException("ValidationUtils_PropertyDoesNotExistOnType", propertyName, "TestModel.ClosedEntityType"), }, SkipTestConfiguration = tc => testCase is NamedStreamInstance && tc.IsRequest }; }); testDescriptors = testDescriptors.SelectMany(td => this.PayloadGenerator.GenerateReaderPayloads(td)); this.CombinatorialEngineProvider.RunCombinations( testDescriptors, this.ReaderTestConfigurationProvider.ExplicitFormatConfigurations, (testDescriptor, testConfiguration) => { testDescriptor.RunTest(testConfiguration); }); }
private bool ShouldReplaceWithCollection(PropertyInstance property, bool isNull, string collectionTypeName) { ExceptionUtilities.CheckArgumentNotNull(property, "property"); // only replace root elements with no null-marker or type name bool shouldReplace = this.isRoot && !isNull && collectionTypeName == null; // only replace if it is from a service operation which returns a collection of complex or primitive types if (shouldReplace) { var functionAnnotation = property.Annotations.OfType<FunctionAnnotation>().SingleOrDefault(); if (functionAnnotation != null) { var dataTypeAnnotation = property.Annotations.OfType<DataTypeAnnotation>().SingleOrDefault(); if (dataTypeAnnotation != null) { ExceptionUtilities.CheckObjectNotNull(dataTypeAnnotation.DataType, "DataType Annotation doesn't contain a DataType"); var collectionType = dataTypeAnnotation.DataType as CollectionDataType; if (collectionType != null) { return collectionType.ElementDataType is ComplexDataType || collectionType.ElementDataType is PrimitiveDataType; } } } } return false; }
/// <summary> /// Helper method for visiting properties /// </summary> /// <param name="payloadElement">The property to visit</param> /// <param name="value">The value of the property</param> protected override void VisitProperty(PropertyInstance payloadElement, ODataPayloadElement value) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); var property = this.MetadataStack.Peek() as MemberProperty; if (property != null) { ExceptionUtilities.Assert(payloadElement.Name == property.Name, "Property name mismatch"); payloadElement.AddAnnotationIfNotExist(new MemberPropertyAnnotation() { Property = property }); try { this.MetadataStack.Push(property.PropertyType); base.VisitProperty(payloadElement, value); } finally { this.MetadataStack.Pop(); } } else { var navprop = this.MetadataStack.Peek() as NavigationProperty; if (navprop != null) { ExceptionUtilities.Assert(payloadElement.Name == navprop.Name, "Property name mismatch"); try { this.MetadataStack.Push(this.CurrentEntitySet.GetRelatedEntitySet(navprop)); base.VisitProperty(payloadElement, value); } finally { this.MetadataStack.Pop(); } } else { var serviceOperation = this.MetadataStack.OfType<Function>().SingleOrDefault(f => f.Name.Equals(payloadElement.Name, StringComparison.Ordinal)); if (payloadElement.Name.Contains('.')) { // if the action has a name collision with a property in the entity, it will have the <container name>.<action name> in the payload // split the payloadElement.Name and get the last token which will match the function name string lastToken = payloadElement.Name.Split('.').Last(); serviceOperation = this.MetadataStack.OfType<Function>().SingleOrDefault(f => f.Name.Equals(lastToken, StringComparison.Ordinal)); } ExceptionUtilities.CheckObjectNotNull(serviceOperation, "Expected property, got " + this.MetadataStack.Peek().ToString()); // Non-entity values returned from a service operation call appear identical to member properties, // with the operation name as the property name base.VisitProperty(payloadElement, value); } } }
/// <summary> /// Creates a set of interesting entity instances along with metadata. /// </summary> /// <param name="settings">The test descriptor settings to use.</param> /// <param name="model">If non-null, the method creates complex types for the complex values and adds them to the model.</param> /// <param name="withTypeNames">true if the payloads should specify type names.</param> /// <returns>List of test descriptors with interesting entity instances as payload.</returns> public static IEnumerable<PayloadTestDescriptor> CreateEntityInstanceTestDescriptors( EdmModel model, bool withTypeNames) { IEnumerable<PrimitiveValue> primitiveValues = TestValues.CreatePrimitiveValuesWithMetadata(fullSet: false); IEnumerable<ComplexInstance> complexValues = TestValues.CreateComplexValues(model, withTypeNames, fullSet: false); IEnumerable<NamedStreamInstance> streamReferenceValues = TestValues.CreateStreamReferenceValues(fullSet: false); IEnumerable<PrimitiveMultiValue> primitiveMultiValues = TestValues.CreatePrimitiveCollections(withTypeNames, fullSet: false); IEnumerable<ComplexMultiValue> complexMultiValues = TestValues.CreateComplexCollections(model, withTypeNames, fullSet: false); IEnumerable<NavigationPropertyInstance> navigationProperties = TestValues.CreateDeferredNavigationLinks(); // NOTE we have to copy the EntityModelTypeAnnotation on the primitive value to the NullPropertyInstance for null values since the // NullPropertyInstance does not expose a value. We will later copy it back to the value we generate for the null property. IEnumerable<PropertyInstance> primitiveProperties = primitiveValues.Select((pv, ix) => PayloadBuilder.Property("PrimitiveProperty" + ix, pv).CopyAnnotation<PropertyInstance, EntityModelTypeAnnotation>(pv)); IEnumerable<PropertyInstance> complexProperties = complexValues.Select((cv, ix) => PayloadBuilder.Property("ComplexProperty" + ix, cv)); IEnumerable<PropertyInstance> primitiveMultiValueProperties = primitiveMultiValues.Select((pmv, ix) => PayloadBuilder.Property("PrimitiveMultiValueProperty" + ix, pmv)); IEnumerable<PropertyInstance> complexMultiValueProperties = complexMultiValues.Select((cmv, ix) => PayloadBuilder.Property("ComplexMultiValueProperty" + ix, cmv)); PropertyInstance[][] propertyMatrix = new PropertyInstance[6][]; propertyMatrix[0] = primitiveProperties.ToArray(); propertyMatrix[1] = complexProperties.ToArray(); propertyMatrix[2] = streamReferenceValues.ToArray(); propertyMatrix[3] = primitiveMultiValueProperties.ToArray(); propertyMatrix[4] = complexMultiValueProperties.ToArray(); propertyMatrix[5] = navigationProperties.ToArray(); IEnumerable<PropertyInstance[]> propertyCombinations = propertyMatrix.ColumnCombinations(0, 1, 6); int count = 0; foreach (PropertyInstance[] propertyCombination in propertyCombinations) { // build the entity type, add it to the model EdmEntityType generatedEntityType = null; string typeName = "PGEntityType" + count; EdmEntityContainer container = null; EdmEntitySet entitySet = null; if (model != null) { // generate a new type with the auto-generated name, check that no type with this name exists and add the default key property to it. Debug.Assert(model.FindDeclaredType(typeName) == null, "Entity type '" + typeName + "' already exists."); generatedEntityType = new EdmEntityType("TestModel", typeName); generatedEntityType.AddKeys(generatedEntityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32)); model.AddElement(generatedEntityType); container = model.EntityContainer as EdmEntityContainer; if (container == null) { container = new EdmEntityContainer("TestModel", "DefaultNamespace"); model.AddElement(container); } entitySet = container.AddEntitySet(typeName, generatedEntityType); } EntityInstance entityInstance = PayloadBuilder.Entity("TestModel." + typeName) .Property("Id", PayloadBuilder.PrimitiveValue(count).WithTypeAnnotation(EdmCoreModel.Instance.GetInt32(false))); for (int i = 0; i < propertyCombination.Length; ++i) { PropertyInstance currentProperty = propertyCombination[i]; entityInstance.Add(currentProperty); if (model != null) { if (entitySet == null) { entitySet = container.FindEntitySet(typeName) as EdmEntitySet; } switch (currentProperty.ElementType) { case ODataPayloadElementType.ComplexProperty: ComplexProperty complexProperty = (ComplexProperty)currentProperty; generatedEntityType.AddStructuralProperty(complexProperty.Name, complexProperty.Value.GetAnnotation<EntityModelTypeAnnotation>().EdmModelType); break; case ODataPayloadElementType.PrimitiveProperty: PrimitiveProperty primitiveProperty = (PrimitiveProperty)currentProperty; if (primitiveProperty.Value == null) { generatedEntityType.AddStructuralProperty( primitiveProperty.Name, PayloadBuilder.PrimitiveValueType(null)); } else { generatedEntityType.AddStructuralProperty(primitiveProperty.Name, primitiveProperty.Value.GetAnnotation<EntityModelTypeAnnotation>().EdmModelType); } break; case ODataPayloadElementType.NamedStreamInstance: NamedStreamInstance streamProperty = (NamedStreamInstance)currentProperty; generatedEntityType.AddStructuralProperty(streamProperty.Name, EdmPrimitiveTypeKind.Stream); break; case ODataPayloadElementType.EmptyCollectionProperty: throw new NotImplementedException(); case ODataPayloadElementType.NavigationPropertyInstance: NavigationPropertyInstance navigationProperty = (NavigationPropertyInstance)currentProperty; var navProperty = generatedEntityType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo() { ContainsTarget = false, Name = navigationProperty.Name, Target = generatedEntityType, TargetMultiplicity = EdmMultiplicity.One }); entitySet.AddNavigationTarget(navProperty, entitySet); break; case ODataPayloadElementType.ComplexMultiValueProperty: ComplexMultiValueProperty complexMultiValueProperty = (ComplexMultiValueProperty)currentProperty; generatedEntityType.AddStructuralProperty(complexMultiValueProperty.Name, complexMultiValueProperty.Value.GetAnnotation<EntityModelTypeAnnotation>().EdmModelType); break; case ODataPayloadElementType.PrimitiveMultiValueProperty: PrimitiveMultiValueProperty primitiveMultiValueProperty = (PrimitiveMultiValueProperty)currentProperty; generatedEntityType.AddStructuralProperty(primitiveMultiValueProperty.Name, primitiveMultiValueProperty.Value.GetAnnotation<EntityModelTypeAnnotation>().EdmModelType); break; default: throw new NotSupportedException("Unsupported element type found : " + propertyCombination[i].ElementType); } } } if (generatedEntityType != null) { entityInstance.AddAnnotation(new EntityModelTypeAnnotation(generatedEntityType.ToTypeReference(true))); } yield return new PayloadTestDescriptor() { PayloadElement = entityInstance, PayloadEdmModel = model }; count++; } }
/// <summary> /// Adds a JSON-L odata.type property annotation to any properties of an open type that are /// not defined by the entity type. /// </summary> /// <param name="property">The property to annotate.</param> /// <param name="propertyValue">The property's value.</param> private void AnnotateIfOpenProperty(PropertyInstance property, ITypedValue propertyValue) { string propertyTypeName = propertyValue.FullTypeName; if (this.payloadElementStack.Count > 1 && !string.IsNullOrEmpty(propertyTypeName)) { var parentEntity = this.payloadElementStack.Skip(1).First() as EntityInstance; if (parentEntity != null) { if (this.testDescriptor.PayloadEdmModel != null) { var parentType = this.testDescriptor.PayloadEdmModel.EntityTypes().SingleOrDefault(t => t.TestFullName() == parentEntity.FullTypeName); if (parentType != null && parentType.IsOpen && parentType.Properties().All(p => p.Name != property.Name) && property.Annotations.OfType<JsonLightPropertyAnnotationAnnotation>().All(a => a.AnnotationName != JsonLightConstants.ODataTypeAnnotationName)) { property.WithPropertyAnnotation(JsonLightConstants.ODataTypeAnnotationName, propertyTypeName); } } } } }
/// <summary> /// Adds or modifies a property's ExpectedTypeODataPayloadElementAnnotation, to aid generation of the context uri. /// </summary> /// <param name="property">The property to annotate.</param> /// <param name="propertyValueType">The type of the property's value.</param> /// <param name="matchesProperty">Delegate for matching the property instance to a MemberProperty.</param> /// <remarks> /// If the method cannot resolve the parent type of the property, one will be created and added to the test descriptor's /// PayloadModel. The descriptor's cached model will be reset. /// </remarks> private void AddExpectedTypeToProperty(PropertyInstance property, IEdmTypeReference propertyValueType, Func<IEdmProperty, bool> matchesProperty) { if (property.Annotations.OfType<JsonLightContextUriAnnotation>().Any()) { return; } var typeAnnotation = property.Annotations.OfType<ExpectedTypeODataPayloadElementAnnotation>().SingleOrDefault(); if (typeAnnotation == null || (typeAnnotation.MemberProperty == null && string.IsNullOrEmpty(typeAnnotation.OpenMemberPropertyName))) { ExpectedTypeODataPayloadElementAnnotation annotation = typeAnnotation ?? new ExpectedTypeODataPayloadElementAnnotation(); IEdmModel model = this.testDescriptor.PayloadEdmModel; var entityType = model.EntityTypes().SingleOrDefault(t => t.Properties().Any(matchesProperty)); if (entityType != null) { annotation.EdmEntitySet = FindEntitySet(model, entityType); annotation.EdmOwningType = entityType; annotation.EdmProperty = entityType.Properties().FirstOrDefault(matchesProperty); } else { var complexType = model.SchemaElements.OfType<IEdmComplexType>().SingleOrDefault(t => t.Properties().Any(matchesProperty)); if (complexType != null) { var complexProperty = complexType.Properties().Single(p => p.Name == property.Name); annotation.EdmOwningType = complexType; annotation.EdmProperty = complexProperty; annotation.EdmExpectedType = complexProperty.Type; } else { // Add new entity type to the model and use that IEdmTypeReference propertyType = annotation.EdmExpectedType ?? propertyValueType; EdmEntityType newEntityType = model.FindDeclaredType("TestModel.NewType") as EdmEntityType; IEdmEntitySet newEntitySet = null; IEdmProperty newProperty = null; string newPorpertyName = property.Name ?? propertyType.FullName() ?? "EmptyName"; if (newEntityType == null) { newEntityType = new EdmEntityType("TestModel", "NewType"); newProperty = newEntityType.AddStructuralProperty(newPorpertyName, propertyType); ((EdmModel)model).AddElement(newEntityType); var container = model.EntityContainersAcrossModels().Single() as EdmEntityContainer; newEntitySet = container.AddEntitySet("NewTypes", newEntityType); } else { newProperty = newEntityType.AddStructuralProperty(newPorpertyName, propertyType); newEntitySet = FindEntitySet(model, newEntityType); } annotation.EdmEntitySet = newEntitySet; annotation.EdmOwningType = newEntityType; annotation.EdmProperty = newProperty; annotation.EdmExpectedType = propertyType; this.testDescriptor.PayloadEdmModel = model; this.testDescriptor.ResetCachedModel(); } } property.SetAnnotation(annotation); } }
/// <summary> /// Normalizes the name of a property instance (JSON Light reports an empty name for top-level properties in requests). /// </summary> /// <param name="payloadElement">The property instance to normalize the name for.</param> private void NormalizePropertyName(PropertyInstance payloadElement) { if (this.IsRootElement(payloadElement)) { // NOTE: in JSON Light we report null property names. payloadElement.Name = null; } }
/// <summary> /// Helper method for visiting properties /// </summary> /// <param name="payloadElement">The property to visit</param> /// <param name="value">The value of the property</param> protected override void VisitProperty(PropertyInstance payloadElement, ODataPayloadElement value) { using (new DelegateBasedDisposable(() => this.currentPath.Pop())) { this.currentPath.Push(payloadElement.Name); base.VisitProperty(payloadElement, value); } }