private static ComplexInstanceCollection GetComplexInstanceCollection(IRandomNumberGenerator random, EdmModel model = null, ODataVersion version = ODataVersion.V4) { var complex = GetComplexInstance(random, model, version); int numinstances = random.ChooseFrom(new[] { 0, 1, 3 }); var payload = new ComplexInstanceCollection(GenerateSimilarComplexInstances(random, complex, numinstances).ToArray()); if (model != null) { var container = model.EntityContainersAcrossModels().Single() as EdmEntityContainer; var collectionType = new EdmCollectionType((model.FindDeclaredType(complex.FullTypeName) as EdmComplexType).ToTypeReference()); var function = new EdmFunction(container.Namespace, "GetComplexInstances", collectionType.ToTypeReference()); var functionImport = container.AddFunctionImport("GetComplexInstances", function); payload.AddAnnotation(new FunctionAnnotation() { FunctionImport = functionImport }); payload.AddAnnotation(new DataTypeAnnotation() { EdmDataType = collectionType }); } return(payload); }
/// <summary> /// Normalizes complex properties, potentially replacing them with collections if the metadata indicates the payload is from a service operation /// </summary> /// <param name="payloadElement">The payload element to potentially replace</param> /// <returns>The original element or a copy to replace it with</returns> public override ODataPayloadElement Visit(ComplexProperty payloadElement) { var replaced = base.Visit(payloadElement); if (replaced.ElementType == ODataPayloadElementType.ComplexProperty) { payloadElement = (ComplexProperty)replaced; // if the payload looks like // <Foo> // <element m:type="Edm.Int32">3</element> // </Foo> // or // <Foo> // <element m:type="Complex"> // <Bar>3</Bar> // </element> // </Foo> // then it may be deserialized as a complex instance with exactly 1 property, when it should be a collection of size 1 // if (this.ShouldReplaceWithCollection(payloadElement, payloadElement.Value.IsNull, payloadElement.Value.FullTypeName)) { // only replace if there is exactly 1 property if (payloadElement.Value.Properties.Count() == 1) { // get the single property and check to see if its name is 'element' var property = payloadElement.Value.Properties.Single(); if (property.Name == ODataConstants.CollectionItemElementName) { // determine whether it is a primitive or complex value based on the kind of property ODataPayloadElementCollection collection = null; if (property.ElementType == ODataPayloadElementType.PrimitiveProperty) { var primitiveProperty = (PrimitiveProperty)property; collection = new PrimitiveCollection(primitiveProperty.Value); } else if (property.ElementType == ODataPayloadElementType.ComplexProperty) { var complexProperty = (ComplexProperty)property; collection = new ComplexInstanceCollection(complexProperty.Value); } // if it was primitive or complex, replace it if (collection != null) { return(payloadElement .ReplaceWith(collection) .WithAnnotations(new CollectionNameAnnotation() { Name = payloadElement.Name })); } } } } } return(replaced); }
/// <summary> /// Visits a payload element whose root is a ComplexInstanceCollection. /// </summary> /// <param name="payloadElement">The root node of the payload element being visited.</param> public override void Visit(ComplexInstanceCollection payloadElement) { base.Visit(payloadElement); if (this.CurrentElementIsRoot()) { this.AddExpectedFunctionImportToCollection(payloadElement); } }
/// <summary> /// Visits a payload element whose root is an <see cref="ComplexInstanceCollection"/>. /// </summary> /// <param name="payloadElement">The root node of the payload element being visited.</param> public override void Visit(ComplexInstanceCollection payloadElement) { base.Visit(payloadElement); // Collections use a different format in JSON for V2 (and higher) payloads (in responses) if (!this.requestPayload) { this.AddVersionAnnotation(payloadElement); } }
/// <summary> /// Visits the payload element and removes the collection name if it is present. /// </summary> /// <param name="payloadElement">The payload element to visit</param> public override void Visit(ComplexInstanceCollection payloadElement) { CollectionNameAnnotation collectionNameAnnotation = payloadElement.GetAnnotation<CollectionNameAnnotation>(); if (payloadElement != null && collectionNameAnnotation != null) { collectionNameAnnotation.Name = string.Empty; } base.Visit(payloadElement); }
/// <summary> /// Visits the payload element and removes the collection name if it is present. /// </summary> /// <param name="payloadElement">The payload element to visit</param> public override void Visit(ComplexInstanceCollection payloadElement) { CollectionNameAnnotation collectionNameAnnotation = payloadElement.GetAnnotation<CollectionNameAnnotation>(); if (payloadElement != null && collectionNameAnnotation != null) { payloadElement.Annotations.Remove(collectionNameAnnotation); } base.Visit(payloadElement); }
/// <summary> /// Visits a payload element whose root is a ComplexInstanceCollection. /// </summary> /// <param name="expected">The root node of payload element being visited.</param> public void Visit(ComplexInstanceCollection expected) { ExceptionUtilities.CheckArgumentNotNull(expected, "expected"); var observed = this.GetNextObservedElement <ComplexInstanceCollection>(); using (this.Assert.WithMessage("Complex instance collection did not match expectation")) { this.CompareCollection(expected, observed); } }
/// <summary> /// Visits the payload element and removes the collection name if it is present. /// </summary> /// <param name="payloadElement">The payload element to visit</param> public override void Visit(ComplexInstanceCollection payloadElement) { CollectionNameAnnotation collectionNameAnnotation = payloadElement.GetAnnotation <CollectionNameAnnotation>(); if (payloadElement != null && collectionNameAnnotation != null) { payloadElement.Annotations.Remove(collectionNameAnnotation); } base.Visit(payloadElement); }
/// <summary> /// Visits the payload element and removes the collection name if it is present. /// </summary> /// <param name="payloadElement">The payload element to visit</param> public override void Visit(ComplexInstanceCollection payloadElement) { CollectionNameAnnotation collectionNameAnnotation = payloadElement.GetAnnotation <CollectionNameAnnotation>(); if (payloadElement != null && collectionNameAnnotation != null) { collectionNameAnnotation.Name = string.Empty; } base.Visit(payloadElement); }
/// <summary> /// Visits the children of the given payload element and replaces it with a copy if any child changes /// </summary> /// <param name="payloadElement">The payload element to potentially replace</param> /// <returns>The original element or a copy to replace it with</returns> public virtual ODataPayloadElement Visit(ComplexInstanceCollection payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); var replaced = this.VisitCollection(payloadElement); if (!this.ShouldReplace(replaced, payloadElement)) { return(payloadElement); } return(payloadElement.ReplaceWith(new ComplexInstanceCollection(replaced.ToArray()))); }
/// <summary> /// Converts the ComplexInstanceCollection into an EntitySetInstance based on if the element type of the collection is entity instance /// </summary> /// <param name="payloadElement">The payload element to potentially replace</param> /// <returns>The original element or a copy to replace it with</returns> public override ODataPayloadElement Visit(ComplexInstanceCollection payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); var replaced = (ComplexInstanceCollection)base.Visit(payloadElement); ExceptionUtilities.CheckObjectNotNull(replaced, "ComplexInstanceCollection Expected"); if (replaced.All(e => e.ElementType == ODataPayloadElementType.EntityInstance) && replaced.Count > 0) { var entitySet = new EntitySetInstance(replaced.Cast<EntityInstance>().ToArray()); return replaced.ReplaceWith(entitySet); } return replaced; }
/// <summary> /// Visits a payload element whose root is a ComplexInstanceCollection. /// </summary> /// <param name="payloadElement">The root node of payload element being visited.</param> public void Visit(ComplexInstanceCollection payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); ExceptionUtilities.Assert(this.isRootElement, "Complex collection is only supported as the root element"); this.isRootElement = false; this.writer.StartArrayScope(); foreach (var item in payloadElement) { this.Recurse(item); } this.writer.EndScope(); }
/// <summary> /// Converts the ComplexInstanceCollection into an EntitySetInstance based on if the element type of the collection is entity instance /// </summary> /// <param name="payloadElement">The payload element to potentially replace</param> /// <returns>The original element or a copy to replace it with</returns> public override ODataPayloadElement Visit(ComplexInstanceCollection payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); var replaced = (ComplexInstanceCollection)base.Visit(payloadElement); ExceptionUtilities.CheckObjectNotNull(replaced, "ComplexInstanceCollection Expected"); if (replaced.All(e => e.ElementType == ODataPayloadElementType.EntityInstance) && replaced.Count > 0) { var entitySet = new EntitySetInstance(replaced.Cast <EntityInstance>().ToArray()); return(replaced.ReplaceWith(entitySet)); } return(replaced); }
/// <summary> /// Visits a collection start. /// </summary> /// <param name="collection">The collection start to visit.</param> protected override ODataPayloadElement VisitCollectionStart(ODataCollectionStart collection) { ExceptionUtilities.CheckArgumentNotNull(collection, "collection"); // NOTE the Taupo OM does not currently support heterogenous collections; we determine the // type of the collection by looking at the first non-null item ODataCollectionItemsObjectModelAnnotation itemsAnnotation = collection.GetAnnotation <ODataCollectionItemsObjectModelAnnotation>(); ExceptionUtilities.Assert(itemsAnnotation != null, "itemsAnnotation != null"); // NOTE we assume that it is a primitive collection; if we find a collection of only null items we treat it as primitive bool isComplexCollection = false; foreach (object item in itemsAnnotation) { if (item != null) { isComplexCollection = item is ODataComplexValue; break; } } if (isComplexCollection) { ComplexInstanceCollection complexCollection = PayloadBuilder.ComplexCollection(collection.Name); foreach (object item in itemsAnnotation) { ComplexInstance complexInstance = item == null ? new ComplexInstance(null, /*isNull*/ true) : (ComplexInstance)this.Visit((ODataComplexValue)item); complexCollection.Add(complexInstance); } return(complexCollection); } else { PrimitiveCollection primitiveCollection = PayloadBuilder.PrimitiveCollection(collection.Name); foreach (object item in itemsAnnotation) { PrimitiveValue primitiveValue = (PrimitiveValue)this.Visit(item); primitiveCollection.Add(primitiveValue); } return(primitiveCollection); } }
/// <summary> /// Build QueryValue from action response payload /// </summary> /// <param name="payload">response payload element</param> /// <param name="queryType">query type to build</param> /// <returns>query value that represents the payload</returns> private QueryValue BuildQueryValueForActionResponse(ODataPayloadElement payload, QueryType queryType) { EntitySetInstance entitySetInstance = payload as EntitySetInstance; PrimitiveProperty primitiveProperty = payload as PrimitiveProperty; ComplexProperty complexProperty = payload as ComplexProperty; PrimitiveMultiValueProperty primitiveMultiValueProperty = payload as PrimitiveMultiValueProperty; ComplexMultiValueProperty complexMultiValueProperty = payload as ComplexMultiValueProperty; PrimitiveCollection primitiveCollection = payload as PrimitiveCollection; ComplexInstanceCollection complexInstanceCollection = payload as ComplexInstanceCollection; if (entitySetInstance != null) { var xmlBaseAnnotations = payload.Annotations.OfType <XmlBaseAnnotation>(); var collectionType = this.currentExpression.ExpressionType as QueryCollectionType; ExceptionUtilities.CheckObjectNotNull(collectionType, "Cannot cast expression type to QueryCollectionType."); var elementType = collectionType.ElementType as QueryEntityType; return(this.BuildFromEntitySetInstance(entitySetInstance, elementType, xmlBaseAnnotations)); } else if (primitiveProperty != null) { return(this.PayloadElementToQueryValueConverter.Convert(primitiveProperty.Value, queryType)); } else if (complexProperty != null) { return(this.PayloadElementToQueryValueConverter.Convert(complexProperty.Value, queryType)); } else if (primitiveMultiValueProperty != null) { return(this.PayloadElementToQueryValueConverter.Convert(primitiveMultiValueProperty.Value, queryType)); } else if (complexMultiValueProperty != null) { return(this.PayloadElementToQueryValueConverter.Convert(complexMultiValueProperty.Value, queryType)); } else if (primitiveCollection != null) { return(this.PayloadElementToQueryValueConverter.Convert(primitiveCollection, queryType)); } else if (complexInstanceCollection != null) { return(this.PayloadElementToQueryValueConverter.Convert(complexInstanceCollection, queryType)); } else { ExceptionUtilities.CheckArgumentNotNull(payload as EntityInstance, "Unexpected response payload type: " + payload.ElementType + "."); return(this.PayloadElementToQueryValueConverter.Convert(payload, queryType)); } }
/// <summary> /// Normalizes primitive properties, potentially replacing them with collections if the metadata indicates the payload is from a service operation /// </summary> /// <param name="payloadElement">The payload element to potentially replace</param> /// <returns>The original element or a copy to replace it with</returns> public override ODataPayloadElement Visit(PrimitiveProperty payloadElement) { var replaced = base.Visit(payloadElement); if (replaced.ElementType == ODataPayloadElementType.PrimitiveProperty) { payloadElement = (PrimitiveProperty)replaced; // if the payload looks like // <Foo /> // then it will be deserialized as a primitive property, when it could be an empty collection // if (this.ShouldReplaceWithCollection(payloadElement, payloadElement.Value.IsNull, payloadElement.Value.FullTypeName)) { // if the value is an empty string var stringValue = payloadElement.Value.ClrValue as string; if (stringValue != null && stringValue.Length == 0) { // get the element data type. Note that this must succeed based on the checks performed earlier var dataType = ((CollectionDataType)payloadElement.Annotations.OfType <DataTypeAnnotation>().Single().DataType).ElementDataType; // determine whether to return a complex or primitive collection based on the data type ODataPayloadElementCollection collection; if (dataType is PrimitiveDataType) { collection = new PrimitiveCollection(); } else { ExceptionUtilities.Assert(dataType is ComplexDataType, "Data type was neither primitive nor complex"); collection = new ComplexInstanceCollection(); } // return the replacement return(payloadElement .ReplaceWith(collection) .WithAnnotations(new CollectionNameAnnotation() { Name = payloadElement.Name })); } } } return(replaced); }
/// <summary> /// Calls the base class method to process the instance collection. /// </summary> /// <param name="payloadElement">The complex instance collection to process.</param> public override void Visit(ComplexInstanceCollection payloadElement) { ODataCollectionStart collectionStart = new ODataCollectionStart(); this.items.Push(collectionStart); var annotation = new ODataCollectionItemsObjectModelAnnotation(); foreach (var complex in payloadElement) { this.items.Push(new ODataComplexValue() { TypeName = complex.FullTypeName }); this.Recurse(complex); annotation.Add(this.items.Pop()); } collectionStart.SetAnnotation <ODataCollectionItemsObjectModelAnnotation>(annotation); }
/// <summary> /// Converts the given payload into a series of named value pairs /// </summary> /// <param name="element">The payload to convert</param> /// <param name="queryTypeToBuild">Query Type to build</param> /// <returns>The queryValue that represents the ODataPayload</returns> public QueryValue Convert(ODataPayloadElement element, QueryType queryTypeToBuild) { var typedValue = element as ITypedValue; if (typedValue != null && typedValue.IsNull) { return(queryTypeToBuild.NullValue); } var queryCollectionType = queryTypeToBuild as QueryCollectionType; // return empty QueryCollectionValue for all types of empty collections PrimitiveCollection primitiveCollection = element as PrimitiveCollection; ComplexInstanceCollection complexInstanceCollection = element as ComplexInstanceCollection; PrimitiveMultiValue primitiveMultiValue = element as PrimitiveMultiValue; ComplexMultiValue complexMultiValue = element as ComplexMultiValue; if ((primitiveCollection != null && primitiveCollection.Count == 0) || (complexInstanceCollection != null && complexInstanceCollection.Count == 0) || (primitiveMultiValue != null && primitiveMultiValue.Count == 0) || (complexMultiValue != null && complexMultiValue.Count == 0)) { return(queryCollectionType.CreateCollectionWithValues(new QueryValue[] { })); } if (element.ElementType == ODataPayloadElementType.PrimitiveValue) { return(CreateQueryScalarValue(element, queryTypeToBuild)); } else if (queryCollectionType != null && element.ElementType == ODataPayloadElementType.PrimitiveMultiValue) { return(queryCollectionType.CreateCollectionWithValues(primitiveMultiValue.Select(p => CreateQueryScalarValue(p, queryCollectionType.ElementType)))); } var namedValues = this.PayloadElementToNamedValuesConverter.ConvertToNamedValues(element); return(this.NamedValueToQueryValueConverter.Convert(namedValues, queryTypeToBuild)); }
/// <summary> /// Creates a set of interesting homogeneous collection values with primitive and complex items. /// </summary> /// <param name="model">The model to add complex types to.</param> /// <param name="withTypeNames">true if the collection and complex value payloads should specify type names.</param> /// <param name="withExpectedType">true if an expected type annotation should be added to the generated payload element; otherwise false.</param> /// <param name="withcollectionName">true if the collection is not in the top level, otherwise false</param> /// <param name="fullSet">true if all available collection values should be returned, false if only the most interesting subset should be returned.</param> /// <returns>List of interesting collection values.</returns> public static IEnumerable<ODataPayloadElementCollection> CreateHomogeneousCollectionValues( EdmModel model, bool withTypeNames, bool withExpectedType, bool withcollectionName, bool fullset = true) { IEdmTypeReference itemTypeAnnotationType = null; IEdmTypeReference collectionTypeAnnotationType = null; EdmOperationImport primitiveCollectionFunctionImport = null; EdmEntityContainer defaultContainer = null; if (model != null) { defaultContainer = model.FindEntityContainer("TestModel.TestContainer") as EdmEntityContainer; if (defaultContainer == null) { defaultContainer = new EdmEntityContainer("TestModel", "TestContainer"); model.AddElement(defaultContainer); } itemTypeAnnotationType = EdmCoreModel.Instance.GetString(true); collectionTypeAnnotationType = EdmCoreModel.GetCollection(itemTypeAnnotationType); var function = new EdmFunction("TestModel", "PrimitiveCollectionFunctionImport", collectionTypeAnnotationType); model.AddElement(function); primitiveCollectionFunctionImport = defaultContainer.AddFunctionImport("PrimitiveCollectionFunctionImport", function); } // primitive collection with single null item yield return new PrimitiveCollection(PayloadBuilder.PrimitiveValue(null).WithTypeAnnotation(itemTypeAnnotationType)) .WithTypeAnnotation(collectionTypeAnnotationType) .ExpectedCollectionItemType(withExpectedType ? itemTypeAnnotationType : null) .ExpectedFunctionImport(withExpectedType ? primitiveCollectionFunctionImport : null) .CollectionName(withcollectionName ? "PrimitiveCollectionFunctionImport" : null); // primitive collection with multiple items (same type) yield return new PrimitiveCollection( PayloadBuilder.PrimitiveValue("Vienna").WithTypeAnnotation(itemTypeAnnotationType), PayloadBuilder.PrimitiveValue("Prague").WithTypeAnnotation(itemTypeAnnotationType), PayloadBuilder.PrimitiveValue("Redmond").WithTypeAnnotation(itemTypeAnnotationType) ) .WithTypeAnnotation(collectionTypeAnnotationType) .ExpectedCollectionItemType(withExpectedType ? itemTypeAnnotationType : null) .ExpectedFunctionImport(withExpectedType ? primitiveCollectionFunctionImport : null) .CollectionName(withcollectionName ? "PrimitiveCollectionFunctionImport" : null); if (fullset) { // empty primitive collection yield return new PrimitiveCollection() .WithTypeAnnotation(collectionTypeAnnotationType) .ExpectedCollectionItemType(withExpectedType ? itemTypeAnnotationType : null) .ExpectedFunctionImport(withExpectedType ? primitiveCollectionFunctionImport : null) .CollectionName(withcollectionName ? "PrimitiveCollectionFunctionImport" : null); // primitive collection with a single item yield return new PrimitiveCollection( PayloadBuilder.PrimitiveValue("Vienna").WithTypeAnnotation(itemTypeAnnotationType) ).WithTypeAnnotation(collectionTypeAnnotationType) .ExpectedCollectionItemType(withExpectedType ? itemTypeAnnotationType : null) .ExpectedFunctionImport(withExpectedType ? primitiveCollectionFunctionImport : null) .CollectionName(withcollectionName ? "PrimitiveCollectionFunctionImport" : null); // primitive collection with multiple null items yield return new PrimitiveCollection( PayloadBuilder.PrimitiveValue(null).WithTypeAnnotation(itemTypeAnnotationType), PayloadBuilder.PrimitiveValue(null).WithTypeAnnotation(itemTypeAnnotationType), PayloadBuilder.PrimitiveValue(null).WithTypeAnnotation(itemTypeAnnotationType) ).WithTypeAnnotation(collectionTypeAnnotationType) .ExpectedCollectionItemType(withExpectedType ? itemTypeAnnotationType : null) .ExpectedFunctionImport(withExpectedType ? primitiveCollectionFunctionImport : null) .CollectionName(withcollectionName ? "PrimitiveCollectionFunctionImport" : null); } string localPersonTypeName = "ComplexCollectionPersonItemType"; string personTypeName = GetFullTypeName(localPersonTypeName); EdmOperationImport complexCollectionFunctionImport = null; if (model != null) { EdmComplexType complexItemType = model.FindDeclaredType(personTypeName) as EdmComplexType; if (complexItemType == null) { complexItemType = new EdmComplexType(NamespaceName, localPersonTypeName); complexItemType.AddStructuralProperty("FirstName", EdmCoreModel.Instance.GetString(true)); complexItemType.AddStructuralProperty("LastName", EdmCoreModel.Instance.GetString(true)); model.AddElement(complexItemType); } itemTypeAnnotationType = complexItemType.ToTypeReference(); collectionTypeAnnotationType = EdmCoreModel.GetCollection(itemTypeAnnotationType); complexCollectionFunctionImport = defaultContainer.FindOperationImports("ComplexCollectionFunctionImport").SingleOrDefault() as EdmOperationImport; if (complexCollectionFunctionImport == null) { var complexCollectionFunction = new EdmFunction("TestModel", "ComplexCollectionFunctionImport", collectionTypeAnnotationType); model.AddElement(complexCollectionFunction); complexCollectionFunctionImport = defaultContainer.AddFunctionImport("ComplexCollectionFunctionImport", complexCollectionFunction); } } // complex collection with multiple complex values var complexInstance1 = PayloadBuilder.ComplexValue(withTypeNames ? personTypeName : null).Property("FirstName", PayloadBuilder.PrimitiveValue("Clemens")).Property("LastName", PayloadBuilder.PrimitiveValue("Kerer")).WithTypeAnnotation(itemTypeAnnotationType); var complexInstance2 = PayloadBuilder.ComplexValue(withTypeNames ? personTypeName : null).Property("FirstName", PayloadBuilder.PrimitiveValue("Vitek")).Property("LastName", PayloadBuilder.PrimitiveValue("Karas")).WithTypeAnnotation(itemTypeAnnotationType); if (!withTypeNames && model != null) { complexInstance1.AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null }); complexInstance2.AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null }); } var complexInstanceCollection = new ComplexInstanceCollection( complexInstance1, complexInstance2 ).WithTypeAnnotation(collectionTypeAnnotationType) .ExpectedCollectionItemType(withExpectedType ? itemTypeAnnotationType : null) .ExpectedFunctionImport(withExpectedType ? complexCollectionFunctionImport : null) .CollectionName(withcollectionName ? "ComplexCollectionFunctionImport" : null); yield return complexInstanceCollection; if (fullset) { // complex collection with a single complex value complexInstance1 = PayloadBuilder.ComplexValue(withTypeNames ? personTypeName : null) .Property("FirstName", PayloadBuilder.PrimitiveValue("Clemens")) .Property("LastName", PayloadBuilder.PrimitiveValue("Kerer")) .WithTypeAnnotation(itemTypeAnnotationType); if (!withTypeNames && model != null) { complexInstance1.AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null }); } yield return new ComplexInstanceCollection( complexInstance1 ).WithTypeAnnotation(collectionTypeAnnotationType) .ExpectedCollectionItemType(withExpectedType ? itemTypeAnnotationType : null) .ExpectedFunctionImport(withExpectedType ? complexCollectionFunctionImport : null) .CollectionName(withcollectionName ? "ComplexCollectionFunctionImport" : null); string localCityTypeName = "ComplexCollectionCityItemType"; IEdmTypeReference cityItemTypeAnnotation = null; if (model != null) { EdmComplexType complexItemType = model.FindDeclaredType(GetFullTypeName(localCityTypeName)) as EdmComplexType; if (complexItemType == null) { complexItemType = new EdmComplexType(NamespaceName, localCityTypeName); complexItemType.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(true)); model.AddElement(complexItemType); } cityItemTypeAnnotation = complexItemType.ToTypeReference(); } } }
/// <summary> /// Calls the base class method to process the instance collection. /// </summary> /// <param name="payloadElement">The complex instance collection to process.</param> public override void Visit(ComplexInstanceCollection payloadElement) { base.Visit(payloadElement); }
/// <summary> /// Converts the given name/value pair into a property element. /// And infers the type of property from the converted value. /// </summary> /// <param name="jsonProperty">the property value</param> /// <returns>the converted property</returns> private PropertyInstance ConvertProperty(JsonProperty jsonProperty) { if (jsonProperty.Value.JsonType == JsonValueType.JsonPrimitiveValue && ((JsonPrimitiveValue)jsonProperty.Value).Value == null) { return(new NullPropertyInstance() { Name = jsonProperty.Name }); } else { ODataPayloadElement elem = this.ConvertValue(jsonProperty.Value); ExceptionUtilities.CheckObjectNotNull(elem, "Converted property value was null"); if (elem.ElementType == ODataPayloadElementType.PrimitiveValue) { return(new PrimitiveProperty(jsonProperty.Name, (PrimitiveValue)elem)); } else if (elem.ElementType == ODataPayloadElementType.ComplexInstance) { return(new ComplexProperty(jsonProperty.Name, (ComplexInstance)elem)); } else if (elem.ElementType == ODataPayloadElementType.EntityInstance) { return(new NavigationPropertyInstance(jsonProperty.Name, new ExpandedLink(elem))); } else if (elem.ElementType == ODataPayloadElementType.DeferredLink) { DeferredLink deferredLink = (DeferredLink)elem; return(new NavigationPropertyInstance(jsonProperty.Name, deferredLink)); } else if (elem.ElementType == ODataPayloadElementType.EntitySetInstance) { return(new NavigationPropertyInstance(jsonProperty.Name, elem)); } else if (elem.ElementType == ODataPayloadElementType.ComplexMultiValue) { ComplexMultiValue complexMultiValue = (ComplexMultiValue)elem; return(new ComplexMultiValueProperty(jsonProperty.Name, complexMultiValue)); } else if (elem.ElementType == ODataPayloadElementType.PrimitiveMultiValue) { PrimitiveMultiValue primitiveMultiValue = (PrimitiveMultiValue)elem; return(new PrimitiveMultiValueProperty(jsonProperty.Name, primitiveMultiValue)); } else if (elem.ElementType == ODataPayloadElementType.ComplexInstanceCollection) { ComplexInstanceCollection complexCollection = (ComplexInstanceCollection)elem; return(new ComplexMultiValueProperty(jsonProperty.Name, new ComplexMultiValue(null, false, complexCollection.ToArray()))); } else if (elem.ElementType == ODataPayloadElementType.PrimitiveCollection) { PrimitiveCollection primitiveCollection = (PrimitiveCollection)elem; return(new PrimitiveMultiValueProperty(jsonProperty.Name, new PrimitiveMultiValue(null, false, primitiveCollection.ToArray()))); } else if (elem.ElementType == ODataPayloadElementType.NamedStreamInstance) { NamedStreamInstance nsi = (NamedStreamInstance)elem; nsi.Name = jsonProperty.Name; return(nsi); } else { ExceptionUtilities.Assert(elem.ElementType == ODataPayloadElementType.EmptyUntypedCollection, "Do not know how to handle element of type" + elem.ElementType); return(new EmptyCollectionProperty(jsonProperty.Name, (EmptyUntypedCollection)elem)); } } }
private static ComplexInstanceCollection GetComplexInstanceCollection(IRandomNumberGenerator random, EdmModel model = null, ODataVersion version = ODataVersion.V4) { var complex = GetComplexInstance(random, model, version); int numinstances = random.ChooseFrom(new[] { 0, 1, 3 }); var payload = new ComplexInstanceCollection(GenerateSimilarComplexInstances(random, complex, numinstances).ToArray()); if (model != null) { var container = model.EntityContainersAcrossModels().Single() as EdmEntityContainer; var collectionType = new EdmCollectionType((model.FindDeclaredType(complex.FullTypeName) as EdmComplexType).ToTypeReference()); var function = new EdmFunction(container.Namespace, "GetComplexInstances", collectionType.ToTypeReference()); var functionImport = container.AddFunctionImport("GetComplexInstances", function); payload.AddAnnotation(new FunctionAnnotation() { FunctionImport = functionImport }); payload.AddAnnotation(new DataTypeAnnotation() { EdmDataType = collectionType }); } return payload; }
/// <summary> /// Normalizes complex properties, potentially replacing them with collections if the metadata indicates the payload is from a service operation /// </summary> /// <param name="payloadElement">The payload element to potentially replace</param> /// <returns>The original element or a copy to replace it with</returns> public override ODataPayloadElement Visit(ComplexProperty payloadElement) { var replaced = base.Visit(payloadElement); if (replaced.ElementType == ODataPayloadElementType.ComplexProperty) { payloadElement = (ComplexProperty)replaced; // if the payload looks like // <Foo> // <element m:type="Edm.Int32">3</element> // </Foo> // or // <Foo> // <element m:type="Complex"> // <Bar>3</Bar> // </element> // </Foo> // then it may be deserialized as a complex instance with exactly 1 property, when it should be a collection of size 1 // if (this.ShouldReplaceWithCollection(payloadElement, payloadElement.Value.IsNull, payloadElement.Value.FullTypeName)) { // only replace if there is exactly 1 property if (payloadElement.Value.Properties.Count() == 1) { // get the single property and check to see if its name is 'element' var property = payloadElement.Value.Properties.Single(); if (property.Name == ODataConstants.CollectionItemElementName) { // determine whether it is a primitive or complex value based on the kind of property ODataPayloadElementCollection collection = null; if (property.ElementType == ODataPayloadElementType.PrimitiveProperty) { var primitiveProperty = (PrimitiveProperty)property; collection = new PrimitiveCollection(primitiveProperty.Value); } else if (property.ElementType == ODataPayloadElementType.ComplexProperty) { var complexProperty = (ComplexProperty)property; collection = new ComplexInstanceCollection(complexProperty.Value); } // if it was primitive or complex, replace it if (collection != null) { return payloadElement .ReplaceWith(collection) .WithAnnotations(new CollectionNameAnnotation() { Name = payloadElement.Name }); } } } } } return replaced; }
/// <summary> /// Visits the payload element. /// </summary> /// <param name="payloadElement">The payload element to visit.</param> public override void Visit(ComplexInstanceCollection payloadElement) { var observed = this.GetNextObservedElement <ComplexInstanceCollection>(); this.VisitEnumerable(payloadElement, observed); }
/// <summary> /// Visits a payload element whose root is a ComplexInstanceCollection. /// </summary> /// <param name="payloadElement">The root node of payload element being visited.</param> public void Visit(ComplexInstanceCollection payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); var current = this.expectedValueStack.Peek(); var value = current as QueryCollectionValue; ExceptionUtilities.CheckObjectNotNull(value, "Value was not a collection. Value was: '{0}'", current.ToString()); this.parent.Assert.AreEqual(value.Elements.Count, payloadElement.Count, "Complex instance collection count did not match expectation"); for (int i = 0; i < value.Elements.Count; i++) { this.RecurseWithMessage(payloadElement[i], value.Elements[i], "Complex instance at position {0} did not match expectation", i + 1); } }
/// <summary> /// Visits the payload element and removes the collection name if it is present. /// </summary> /// <param name="payloadElement">The payload element to visit</param> public override void Visit(ComplexInstanceCollection payloadElement) { payloadElement.RemoveAnnotations(typeof(CollectionNameAnnotation)); base.Visit(payloadElement); }
/// <summary> /// Visits the payload element /// </summary> /// <param name="payloadElement">The payload element to visit</param> public virtual void Visit(ComplexInstanceCollection payloadElement) { this.VisitCollection(payloadElement); }
/// <summary> /// Calls the base class method to process the instance collection. /// </summary> /// <param name="payloadElement">The complex instance collection to process.</param> public override void Visit(ComplexInstanceCollection payloadElement) { ODataCollectionStart collectionStart = new ODataCollectionStart(); this.items.Push(collectionStart); var annotation = new ODataCollectionItemsObjectModelAnnotation(); foreach (var complex in payloadElement) { this.items.Push(new ODataComplexValue() { TypeName = complex.FullTypeName }); this.Recurse(complex); annotation.Add(this.items.Pop()); } collectionStart.SetAnnotation<ODataCollectionItemsObjectModelAnnotation>(annotation); }
/// <summary> /// Visits a payload element whose root is a ComplexInstanceCollection. /// </summary> /// <param name="payloadElement">The root node of payload element being visited.</param> public override void Visit(ComplexInstanceCollection payloadElement) { RemoveChangeAnnotations(payloadElement); base.Visit(payloadElement); }
/// <summary> /// Visits the payload element /// </summary> /// <param name="payloadElement">The payload element to visit</param> public override void Visit(ComplexInstanceCollection payloadElement) { this.SerializeTypedValueCollection(payloadElement); }
/// <summary> /// Normalizes primitive properties, potentially replacing them with collections if the metadata indicates the payload is from a service operation /// </summary> /// <param name="payloadElement">The payload element to potentially replace</param> /// <returns>The original element or a copy to replace it with</returns> public override ODataPayloadElement Visit(PrimitiveProperty payloadElement) { var replaced = base.Visit(payloadElement); if (replaced.ElementType == ODataPayloadElementType.PrimitiveProperty) { payloadElement = (PrimitiveProperty)replaced; // if the payload looks like // <Foo /> // then it will be deserialized as a primitive property, when it could be an empty collection // if (this.ShouldReplaceWithCollection(payloadElement, payloadElement.Value.IsNull, payloadElement.Value.FullTypeName)) { // if the value is an empty string var stringValue = payloadElement.Value.ClrValue as string; if (stringValue != null && stringValue.Length == 0) { // get the element data type. Note that this must succeed based on the checks performed earlier var dataType = ((CollectionDataType)payloadElement.Annotations.OfType<DataTypeAnnotation>().Single().DataType).ElementDataType; // determine whether to return a complex or primitive collection based on the data type ODataPayloadElementCollection collection; if (dataType is PrimitiveDataType) { collection = new PrimitiveCollection(); } else { ExceptionUtilities.Assert(dataType is ComplexDataType, "Data type was neither primitive nor complex"); collection = new ComplexInstanceCollection(); } // return the replacement return payloadElement .ReplaceWith(collection) .WithAnnotations(new CollectionNameAnnotation() { Name = payloadElement.Name }); } } } return replaced; }