public PropertyInstance MultiValuePropertyEmptyOrNull(MemberProperty memberProperty, object value) { var bagPropertyType = memberProperty.PropertyType as CollectionDataType; ExceptionUtilities.CheckObjectNotNull(bagPropertyType, "Expected property to be a BagProperty instead its a '{0}'", memberProperty.PropertyType); DataType elementDataType = bagPropertyType.ElementDataType; if (value == null) { return(new NullPropertyInstance(memberProperty.Name, elementDataType.BuildMultiValueTypeName())); } else { ExceptionUtilities.Assert(value == EmptyData.Value, "value MUST be null or EmptyData.Value"); PropertyInstance collectionProperty = null; if (elementDataType is ComplexDataType) { collectionProperty = new ComplexMultiValueProperty(memberProperty.Name, new ComplexMultiValue(elementDataType.BuildMultiValueTypeName(), false)); } else { ExceptionUtilities.Assert(elementDataType is PrimitiveDataType, "DataType is not a PrimitiveDataType '{0}'", elementDataType); collectionProperty = new PrimitiveMultiValueProperty(memberProperty.Name, new PrimitiveMultiValue(elementDataType.BuildMultiValueTypeName(), false)); } // Add an empty one if specified to return(collectionProperty); } }
private static ComplexMultiValueProperty GetComplexMultiValueProperty(IRandomNumberGenerator random, EdmModel model = null, ODataVersion version = ODataVersion.V4) { int numinstances = random.ChooseFrom(new[] { 0, 1, 3 }); var instance = GetComplexInstance(random, model, version); var instances = GenerateSimilarComplexInstances(random, instance, numinstances, true); var propertyName = "ComplexMultivalue" + instance.FullTypeName; var payload = new ComplexMultiValueProperty(propertyName, new ComplexMultiValue(propertyName, false, instances.ToArray())); if (model != null) { var entityDataType = instance.GetAnnotation <EntityModelTypeAnnotation>().EdmModelType.Definition as IEdmEntityType; ExceptionUtilities.CheckObjectNotNull(entityDataType, "Complex Instance must have an EntityModelTypeAnnotation with an EntityDataType"); var entityType = model.FindDeclaredType(entityDataType.FullName()) as EdmEntityType; ExceptionUtilities.CheckObjectNotNull(entityType, "entityType"); if (entityType.FindProperty(propertyName) != null) { entityType.AddStructuralProperty(propertyName, (model.FindDeclaredType(instance.FullTypeName) as EdmComplexType).ToTypeReference()); } payload.WithTypeAnnotation(entityType); } return(payload); }
/// <summary> /// Visits a complex property. A copy of the current properties to be written is taken so that /// the complex property can use the global list to track its properties as its children are visited. /// Adds the complex property to the list of properties to be written. /// </summary> /// <param name="payloadElement">The complex property to visit and add</param> public override void Visit(ComplexMultiValueProperty payloadElement) { // Save off properties of parent var arr = this.odataProperties; var items = new List <ODataComplexValue>(); foreach (var item in payloadElement.Value) { this.odataProperties = new List <ODataProperty>(); this.Visit(item); ExceptionUtilities.CheckObjectNotNull(this.odataProperties, "ODataProperties cannot be null"); var typename = item.FullTypeName.Substring(11, item.FullTypeName.Length - 12); var complexValue = new ODataComplexValue() { TypeName = typename }; complexValue.Properties = this.odataProperties.ToList();//.AsEnumerable(); items.Add(complexValue); } //Return the global property list to its initial state with the new complex property added this.odataProperties.Clear(); this.odataProperties.AddRange(arr); //create a new complex collection property to add to the list from the properties children this.odataProperties.Add(new ODataProperty() { Name = payloadElement.Name, Value = new ODataCollectionValue() { Items = items, TypeName = payloadElement.Value.FullTypeName } }); }
private void PopulateComplexMultiValuePropertyFromPaths(ComplexInstance instance, MemberProperty memberProperty, string propertyPath, IEnumerable <NamedValue> namedValues, ComplexDataType complexTypeElementDataType) { int i = 0; bool completed = false; var complexCollection = new ComplexMultiValueProperty(memberProperty.Name, new ComplexMultiValue(complexTypeElementDataType.BuildMultiValueTypeName(), false)); while (!completed) { IEnumerable <NamedValue> complexInstanceNamedValues = namedValues.Where(pp => pp.Name.StartsWith(propertyPath + "." + i + ".", StringComparison.Ordinal)).ToList(); if (complexInstanceNamedValues.Count() == 0) { completed = true; } else { ComplexInstance complexInstance = this.ComplexInstance(complexTypeElementDataType.Definition, propertyPath + "." + i, complexInstanceNamedValues); complexCollection.Value.Add(complexInstance); } i++; } if (i > 1) { instance.Add(complexCollection); } }
/// <summary> /// Visits a ComplexMultiValueProperty, if this is not the result of a service operation call, it will be a V3 payload /// </summary> /// <param name="payloadElement">payload Element</param> public override void Visit(ComplexMultiValueProperty payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); this.IncreaseVersionIfRequired(DataServiceProtocolVersion.V4); base.Visit(payloadElement); }
/// <summary> /// Visits the payload element /// </summary> /// <param name="payloadElement">The payload element to visit</param> public override void Visit(ComplexMultiValueProperty payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); var annotation = payloadElement.Annotations.Where(a => a is MemberPropertyAnnotation).SingleOrDefault(); payloadElement.Annotations.Remove(annotation); this.VisitProperty(payloadElement, payloadElement.Value); }
/// <summary> /// Fix up expected collection parameter payload element for comparison. /// </summary> /// <param name="expectedResultPayloadElement"></param> /// <returns>Modified expected collection payload element</returns> internal static ODataPayloadElement FixupExpectedCollectionParameterPayloadElement(ODataPayloadElement expectedResultPayloadElement) { ComplexInstance expected = expectedResultPayloadElement as ComplexInstance; if (expected != null) { List <ComplexMultiValueProperty> propertiesToReplace = new List <ComplexMultiValueProperty>(); List <PrimitiveMultiValueProperty> replacementProperties = new List <PrimitiveMultiValueProperty>(); foreach (PropertyInstance pi in expected.Properties) { PrimitiveMultiValueProperty primitiveCollectionProperty = pi as PrimitiveMultiValueProperty; ComplexMultiValueProperty complexCollectionProperty = pi as ComplexMultiValueProperty; if (primitiveCollectionProperty != null) { // collection parameter is an array of element without type name or result wrapper if (primitiveCollectionProperty.Value.Annotations.OfType <JsonCollectionResultWrapperAnnotation>().Any(a => !a.Value)) { primitiveCollectionProperty.Value.FullTypeName = null; } } else if (complexCollectionProperty != null) { if (complexCollectionProperty.Value.Annotations.OfType <JsonCollectionResultWrapperAnnotation>().Any(a => !a.Value)) { // collection parameter is an array of element without type name or result wrapper complexCollectionProperty.Value.FullTypeName = null; // replace empty ComplexMultiValueProperty with empty PrimitiveMultiValueProperty for comparison since they have the same payload if (complexCollectionProperty.Value.Count == 0) { PrimitiveMultiValueProperty replacementProperty = new PrimitiveMultiValueProperty(complexCollectionProperty.Name, null); replacementProperty.Value.IsNull = complexCollectionProperty.Value.IsNull; foreach (var annotation in complexCollectionProperty.Annotations) { replacementProperty.Annotations.Add(annotation); } propertiesToReplace.Add(complexCollectionProperty); replacementProperties.Add(replacementProperty); } } } } for (int i = 0; i < propertiesToReplace.Count; i++) { expected.Replace(propertiesToReplace[i], replacementProperties[i]); } return(expected); } return(expectedResultPayloadElement); }
/// <summary> /// Visits a payload element whose root is a ComplexMultiValueProperty. /// </summary> /// <param name="expected">The root node of payload element being visited.</param> public void Visit(ComplexMultiValueProperty expected) { ExceptionUtilities.CheckArgumentNotNull(expected, "expected"); var observed = this.GetNextObservedElement <ComplexMultiValueProperty>(); using (this.Assert.WithMessage("Complex multi-value property '{0}' did not match expectation", expected.Name)) { this.Assert.AreEqual(expected.Name, observed.Name, "Property name did not match expectation"); this.CompareAnnotations(expected.Annotations, observed.Annotations); this.WrapAccept(expected.Value, observed.Value); } }
/// <summary> /// Visits a payload element whose root is a ComplexCollectionProperty. /// </summary> /// <param name="payloadElement">The root node of payload element being visited.</param> public void Visit(ComplexMultiValueProperty payloadElement) { bool needsWrapping = this.isRootElement; if (needsWrapping) { this.isRootElement = false; this.writer.StartObjectScope(); } this.writer.WriteName(payloadElement.Name); // if an annotation is present that specifies not to use the wrapper, don't bool useResultsWrapper = !payloadElement.Value.Annotations.OfType <JsonCollectionResultWrapperAnnotation>().Any(a => !a.Value); if (useResultsWrapper) { this.writer.StartObjectScope(); if (payloadElement.Value.FullTypeName != null) { this.writer.WriteName("__metadata"); this.writer.StartObjectScope(); this.writer.WriteName("type"); this.writer.WriteString(payloadElement.Value.FullTypeName); this.writer.EndScope(); } this.writer.WriteName("results"); } if (payloadElement.Value.IsNull) { this.writer.WriteNull(); } else { this.Recurse(payloadElement.Value); } if (useResultsWrapper) { this.writer.EndScope(); } if (needsWrapping) { this.writer.EndScope(); } }
/// <summary> /// Creates a new MultiValue property and sets the value to an empty collection that will be filled when visiting the complex instances. /// </summary> /// <param name="payloadElement">The complex MultiValue property to process.</param> public override void Visit(ComplexMultiValueProperty payloadElement) { object parent = null; if (this.items.Any()) { parent = this.items.Peek(); } var value = new ODataCollectionValue() { Items = new List <object>(), TypeName = payloadElement.Value.FullTypeName }; this.items.Push(value); base.Visit(payloadElement); var odataProperty = new ODataProperty() { Name = payloadElement.Name, Value = value }; if (parent != null) { var entry = parent as ODataResource; if (entry != null) { var properties = (List <ODataProperty>)entry.Properties; properties.Add(odataProperty); } var complexValue = parent as ODataComplexValue; if (complexValue != null) { var properties = (List <ODataProperty>)complexValue.Properties; properties.Add(odataProperty); } // Remove property from items as it has been added to parent. this.items.Pop(); } else { // Remove the ODataCollectionValue and add the ODataProperty. this.items.Pop(); this.items.Push(odataProperty); } }
/// <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(ComplexMultiValueProperty payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); var replacedCollection = this.Recurse(payloadElement.Value) as ComplexMultiValue; ExceptionUtilities.CheckObjectNotNull(replacedCollection, "Replaced complex collection was null or wrong type"); if (!this.ShouldReplace(payloadElement.Value, replacedCollection)) { return(payloadElement); } return(payloadElement.ReplaceWith(new ComplexMultiValueProperty(payloadElement.Name, replacedCollection))); }
/// <summary> /// Visits a payload element whose root is a ComplexMultiValueProperty. /// </summary> /// <param name="payloadElement">The root node of the payload element being visited.</param> public override void Visit(ComplexMultiValueProperty payloadElement) { base.Visit(payloadElement); if (this.CurrentElementIsRoot()) { Func <MemberProperty, bool> matchesProperty = (p) => { if (p.Name == payloadElement.Name && p.PropertyType is CollectionDataType) { var complexElementType = ((CollectionDataType)p.PropertyType).ElementDataType as ComplexDataType; return(complexElementType != null && payloadElement.Value.FullTypeName == "Collection(" + complexElementType.Definition.FullName + ")"); } return(false); }; Func <IEdmProperty, bool> EdmMatchesProperty = (p) => { if (p.Name == payloadElement.Name && p.DeclaringType as IEdmCollectionType != null) { var complexElementType = ((IEdmCollectionType)p.DeclaringType).ElementType as IEdmComplexType; return(complexElementType != null && payloadElement.Value.FullTypeName == "Collection(" + complexElementType.FullName() + ")"); } return(false); }; var valueTypeAnnotation = payloadElement.Value.Annotations.OfType <EntityModelTypeAnnotation>().SingleOrDefault(); if (valueTypeAnnotation != null) { if (valueTypeAnnotation.EdmModelType != null) { var edmEntityType = valueTypeAnnotation.EdmModelType; this.AddExpectedTypeToProperty(payloadElement, edmEntityType, EdmMatchesProperty); } } else { var edmEntityType = this.ResolvePropertyEdmDataType(payloadElement.Value.FullTypeName); this.AddExpectedTypeToProperty(payloadElement, edmEntityType, EdmMatchesProperty); } } this.AnnotateIfOpenProperty(payloadElement, payloadElement.Value); }
/// <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 complex multi-value properties, potentially replacing them with complex 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(ComplexMultiValueProperty payloadElement) { var replaced = base.Visit(payloadElement); if (replaced.ElementType == ODataPayloadElementType.ComplexMultiValueProperty) { payloadElement = (ComplexMultiValueProperty)replaced; if (this.ShouldReplaceWithCollection(payloadElement, payloadElement.Value.IsNull, payloadElement.Value.FullTypeName)) { return payloadElement .ReplaceWith(new ComplexInstanceCollection(payloadElement.Value.ToArray())) .WithAnnotations(new CollectionNameAnnotation() { Name = payloadElement.Name }); } } return replaced; }
/// <summary> /// Creates a new MultiValue property and sets the value to an empty collection that will be filled when visiting the complex instances. /// </summary> /// <param name="payloadElement">The complex MultiValue property to process.</param> public override void Visit(ComplexMultiValueProperty payloadElement) { var odataProperty = new ODataProperty() { Name = payloadElement.Name, Value = new ODataCollectionValue() { Items = new List <object>(), TypeName = payloadElement.Value.FullTypeName } }; this.currentProperties.Add(odataProperty); base.Visit(payloadElement); }
/// <summary> /// Visits a complex multivalue property and clears its type name. /// Note: this has to be done at the property level rather than just at the multivalue in order to maintain the CLR type stack. /// </summary> /// <param name="payloadElement">The complex multivalue property</param> public override void Visit(ComplexMultiValueProperty payloadElement) { this.VisitProperty( payloadElement, payloadElement.Value, () => { payloadElement.Value.FullTypeName = null; if (this.contextData.ResolveName != null) { string elementName = this.contextData.ResolveName(this.typeStack.Peek()); payloadElement.Value.FullTypeName = string.Concat(ODataConstants.BeginMultiValueTypeIdentifier, elementName, ODataConstants.EndMultiValueTypeNameIdentifier); } payloadElement.Value.ForEach(v => v.FullTypeName = null); }); }
/// <summary> /// Normalizes complex multi-value properties, potentially replacing them with complex 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(ComplexMultiValueProperty payloadElement) { var replaced = base.Visit(payloadElement); if (replaced.ElementType == ODataPayloadElementType.ComplexMultiValueProperty) { payloadElement = (ComplexMultiValueProperty)replaced; if (this.ShouldReplaceWithCollection(payloadElement, payloadElement.Value.IsNull, payloadElement.Value.FullTypeName)) { return(payloadElement .ReplaceWith(new ComplexInstanceCollection(payloadElement.Value.ToArray())) .WithAnnotations(new CollectionNameAnnotation() { Name = payloadElement.Name })); } } return(replaced); }
/// <summary> /// Converts the ComplexMultiValueProperty into a NavigationPropertyInstance if the base returned an EntitySetInstance /// </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(ComplexMultiValueProperty payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); var replacedCollection = this.Recurse(payloadElement.Value); if (!this.ShouldReplace(payloadElement.Value, replacedCollection)) { return(payloadElement); } var complexmulti = replacedCollection as ComplexMultiValue; if (complexmulti != null) { return(payloadElement.ReplaceWith(new ComplexMultiValueProperty(payloadElement.Name, complexmulti))); } var entityset = replacedCollection as EntitySetInstance; ExceptionUtilities.CheckObjectNotNull(entityset, "Replaced collection should be either ComplexMultiValue or EntitySetInstance"); return(payloadElement.ReplaceWith(new NavigationPropertyInstance(payloadElement.Name, replacedCollection))); }
private static ComplexInstance GenerateSimilarComplexInstance(IRandomNumberGenerator random, ComplexInstance currentInstance, bool randomizePropertyValues = false) { ComplexInstance instance = ((ComplexInstance)currentInstance.DeepCopy()); if (!randomizePropertyValues) { return(instance); } foreach (var property in instance.Properties) { PrimitiveProperty primitive = property as PrimitiveProperty; if (primitive != null) { primitive.Value = TestValues.GetDifferentPrimitiveValue(primitive.Value); } ComplexProperty complex = property as ComplexProperty; if (complex != null) { complex.Value = GenerateSimilarComplexInstance(random, complex.Value); } PrimitiveMultiValueProperty pmultival = property as PrimitiveMultiValueProperty; if (pmultival != null) { pmultival.Value = GenerateSimilarPrimitiveMultiValue(random, pmultival.Value); } ComplexMultiValueProperty cmultival = property as ComplexMultiValueProperty; if (cmultival != null) { cmultival.Value = GenerateSimilarComplexMultiValue(random, cmultival.Value); } } return(instance); }
public PropertyInstance MultiValueProperty(MemberProperty memberProperty, object anonymous) { ExceptionUtilities.CheckArgumentNotNull(memberProperty, "memberProperty"); var collectionType = memberProperty.PropertyType as CollectionDataType; ExceptionUtilities.CheckObjectNotNull(collectionType, "Property '{0}' was not a collection"); var enumerable = anonymous as IEnumerable; ExceptionUtilities.CheckObjectNotNull(enumerable, "Value for property '{0}' was not enumerable"); var primitiveType = collectionType.ElementDataType as PrimitiveDataType; if (primitiveType != null) { var primitiveCollection = new PrimitiveMultiValueProperty(memberProperty.Name, new PrimitiveMultiValue(primitiveType.BuildMultiValueTypeName(), false)); foreach (var thing in enumerable) { primitiveCollection.Value.Add(this.PrimitiveProperty(new MemberProperty("temp", primitiveType), thing).Value); } return(primitiveCollection); } else { var complexType = collectionType.ElementDataType as ComplexDataType; ExceptionUtilities.CheckObjectNotNull(complexType, "Collection property '{0}' did not have a primitive or complex collection type", memberProperty.Name); var complexCollection = new ComplexMultiValueProperty(memberProperty.Name, new ComplexMultiValue(complexType.BuildMultiValueTypeName(), false)); foreach (var thing in enumerable) { complexCollection.Value.Add(this.ComplexInstance(complexType.Definition, thing)); } return(complexCollection); } }
/// <summary> /// Visits a payload element whose root is a ComplexCollectionProperty. /// </summary> /// <param name="payloadElement">The root node of payload element being visited.</param> public override void Visit(ComplexMultiValueProperty payloadElement) { RemoveChangeAnnotations(payloadElement); base.Visit(payloadElement); }
/// <summary> /// Converts the ComplexMultiValueProperty into a NavigationPropertyInstance if the base returned an EntitySetInstance /// </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(ComplexMultiValueProperty payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); var replacedCollection = this.Recurse(payloadElement.Value); if (!this.ShouldReplace(payloadElement.Value, replacedCollection)) { return payloadElement; } var complexmulti = replacedCollection as ComplexMultiValue; if (complexmulti != null) { return payloadElement.ReplaceWith(new ComplexMultiValueProperty(payloadElement.Name, complexmulti)); } var entityset = replacedCollection as EntitySetInstance; ExceptionUtilities.CheckObjectNotNull(entityset, "Replaced collection should be either ComplexMultiValue or EntitySetInstance"); return payloadElement.ReplaceWith(new NavigationPropertyInstance(payloadElement.Name, replacedCollection)); }
/// <summary> /// Normalizes a complex collection property. /// </summary> /// <param name="payloadElement">The payload element to normalize.</param> public override void Visit(ComplexMultiValueProperty payloadElement) { base.Visit(payloadElement); this.NormalizePropertyName(payloadElement); }
private static ComplexMultiValueProperty GetComplexMultiValueProperty(IRandomNumberGenerator random, EdmModel model = null, ODataVersion version = ODataVersion.V4) { int numinstances = random.ChooseFrom(new[] { 0, 1, 3 }); var instance = GetComplexInstance(random, model, version); var instances = GenerateSimilarComplexInstances(random, instance, numinstances, true); var propertyName = "ComplexMultivalue" + instance.FullTypeName; var payload = new ComplexMultiValueProperty(propertyName, new ComplexMultiValue(propertyName, false, instances.ToArray())); if (model != null) { var entityDataType = instance.GetAnnotation<EntityModelTypeAnnotation>().EdmModelType.Definition as IEdmEntityType; ExceptionUtilities.CheckObjectNotNull(entityDataType, "Complex Instance must have an EntityModelTypeAnnotation with an EntityDataType"); var entityType = model.FindDeclaredType(entityDataType.FullName()) as EdmEntityType; ExceptionUtilities.CheckObjectNotNull(entityType, "entityType"); if (entityType.FindProperty(propertyName) != null) { entityType.AddStructuralProperty(propertyName, (model.FindDeclaredType(instance.FullTypeName) as EdmComplexType).ToTypeReference()); } payload.WithTypeAnnotation(entityType); } return payload; }
public override void Visit(ComplexMultiValueProperty payloadElement) { base.Visit(payloadElement); this.ReplaceExpectedTypeAnnotationIfRootElement(payloadElement); }
/// <summary> /// Builds a complex instance from the given payloadElements to represent a parameters payload. /// </summary> /// <param name="payloadElements">Each ODataPayloadElement represents the value for each parameter.</param> /// <param name="model">EdmModel instance.</param> /// <param name="functionImportName">Name of the function import to add to the model.</param> /// <returns></returns> private static ComplexInstance PayloadElementsToParameterPayload(ODataPayloadElement[] payloadElements, EdmModel model, string functionImportName) { EdmOperationImport operationImport = (EdmOperationImport)model.EntityContainer.FindOperationImports(functionImportName).FirstOrDefault(); EdmOperation operation = (EdmOperation)operationImport.Operation; var parameterPayload = new ComplexInstance(null, false); for (int idx = 0; idx < payloadElements.Length; idx++) { ODataPayloadElement p = payloadElements[idx]; string parameterName = "p" + idx; PropertyInstance parameter; IEdmTypeReference entityModelType = p.GetAnnotation<EntityModelTypeAnnotation>().EdmModelType; switch (p.ElementType) { case ODataPayloadElementType.PrimitiveValue: object clrValue = ((PrimitiveValue)p).ClrValue; PrimitiveValue primitiveValue = new PrimitiveValue(clrValue == null ? null : clrValue.GetType().FullName, clrValue); primitiveValue.CopyAnnotation<PrimitiveValue, EntityModelTypeAnnotation>(p); parameter = new PrimitiveProperty(parameterName, primitiveValue); operation.AddParameter(parameterName, MetadataUtils.GetPrimitiveTypeReference(primitiveValue.ClrValue.GetType())); break; case ODataPayloadElementType.ComplexInstance: parameter = new ComplexProperty(parameterName, (ComplexInstance)p); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.PrimitiveMultiValue: PrimitiveMultiValue primitiveMultiValue = (PrimitiveMultiValue)p; if (primitiveMultiValue.Annotations.OfType<JsonCollectionResultWrapperAnnotation>().SingleOrDefault() == null) { primitiveMultiValue.Annotations.Add(new JsonCollectionResultWrapperAnnotation(false)); } parameter = new PrimitiveMultiValueProperty(parameterName, primitiveMultiValue); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.ComplexMultiValue: ComplexMultiValue complexMultiValue = (ComplexMultiValue)p; if (complexMultiValue.Annotations.OfType<JsonCollectionResultWrapperAnnotation>().SingleOrDefault() == null) { complexMultiValue.Annotations.Add(new JsonCollectionResultWrapperAnnotation(false)); } parameter = new ComplexMultiValueProperty(parameterName, complexMultiValue); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.EntityInstance: parameter = new NavigationPropertyInstance(parameterName, (EntityInstance)p); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.EntitySetInstance: parameter = new NavigationPropertyInstance(parameterName, (EntitySetInstance)p); operation.AddParameter(parameterName, entityModelType); break; default: throw new NotSupportedException("PayloadElementsToParameterPayload() is called on unsupported ODataPayloadElement type: " + p.ElementType); } parameterPayload.Add(parameter); } parameterPayload.ExpectedFunctionImport(operationImport); return parameterPayload; }
public PropertyInstance MultiValuePropertyEmptyOrNull(MemberProperty memberProperty, object value) { var bagPropertyType = memberProperty.PropertyType as CollectionDataType; ExceptionUtilities.CheckObjectNotNull(bagPropertyType, "Expected property to be a BagProperty instead its a '{0}'", memberProperty.PropertyType); DataType elementDataType = bagPropertyType.ElementDataType; if (value == null) { return new NullPropertyInstance(memberProperty.Name, elementDataType.BuildMultiValueTypeName()); } else { ExceptionUtilities.Assert(value == EmptyData.Value, "value MUST be null or EmptyData.Value"); PropertyInstance collectionProperty = null; if (elementDataType is ComplexDataType) { collectionProperty = new ComplexMultiValueProperty(memberProperty.Name, new ComplexMultiValue(elementDataType.BuildMultiValueTypeName(), false)); } else { ExceptionUtilities.Assert(elementDataType is PrimitiveDataType, "DataType is not a PrimitiveDataType '{0}'", elementDataType); collectionProperty = new PrimitiveMultiValueProperty(memberProperty.Name, new PrimitiveMultiValue(elementDataType.BuildMultiValueTypeName(), false)); } // Add an empty one if specified to return collectionProperty; } }
/// <summary> /// Visits the payload element. /// </summary> /// <param name="payloadElement">The payload element to visit.</param> public override void Visit(ComplexMultiValueProperty payloadElement) { var observed = this.GetNextObservedElement <ComplexMultiValueProperty>(); this.WrapAccept(payloadElement.Value, observed.Value); }
/// <summary> /// Creates a new MultiValue property and sets the value to an empty collection that will be filled when visiting the complex instances. /// </summary> /// <param name="payloadElement">The complex MultiValue property to process.</param> public override void Visit(ComplexMultiValueProperty payloadElement) { object parent = null; if (this.items.Any()) { parent = this.items.Peek(); } var value = new ODataCollectionValue() { Items = new List<object>(), TypeName = payloadElement.Value.FullTypeName }; this.items.Push(value); base.Visit(payloadElement); var odataProperty = new ODataProperty() { Name = payloadElement.Name, Value = value }; if (parent != null) { var entry = parent as ODataEntry; if (entry != null) { var properties = (List<ODataProperty>)entry.Properties; properties.Add(odataProperty); } var complexValue = parent as ODataComplexValue; if (complexValue != null) { var properties = (List<ODataProperty>)complexValue.Properties; properties.Add(odataProperty); } // Remove property from items as it has been added to parent. this.items.Pop(); } else { // Remove the ODataCollectionValue and add the ODataProperty. this.items.Pop(); this.items.Push(odataProperty); } }
/// <summary> /// Visits the payload element /// </summary> /// <param name="payloadElement">The payload element to visit</param> public virtual void Visit(ComplexMultiValueProperty payloadElement) { this.VisitProperty(payloadElement, payloadElement.Value); }
/// <summary> /// Visits the payload element /// </summary> /// <param name="payloadElement">The payload element to visit</param> public override void Visit(ComplexMultiValueProperty payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); this.SerializeMultiValueProperty <ComplexMultiValue, ComplexInstance>(payloadElement); }
/// <summary> /// Visits a payload element whose root is a ComplexMultiValueProperty. /// </summary> /// <param name="payloadElement">The root node of payload element being visited.</param> public void Visit(ComplexMultiValueProperty 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.RecurseWithMessage(payloadElement.Value, value, "Complex multi-value property '{0}' did not match expectation", payloadElement.Name); }
/// <summary> /// Deserializes a collection property /// </summary> /// <param name="propertyElement">The xml element representing the property</param> /// <returns>The deserialized property</returns> private PropertyInstance DeserializeCollectionProperty(XElement propertyElement) { ExceptionUtilities.CheckArgumentNotNull(propertyElement, "propertyElement"); ExceptionUtilities.CheckCollectionNotEmpty(propertyElement.Elements(), "propertyElement.Elements()"); ExceptionUtilities.Assert(propertyElement.Elements().All(e => e.Name == DataServicesElement), "Collection property sub elements had inconsistent names"); string propertyName = propertyElement.Name.LocalName; string fullTypeName = null; string bagElementTypeName = null; var type = propertyElement.Attribute(MetadataType); if (type != null) { fullTypeName = type.Value; bagElementTypeName = ParseBagElementTypeName(type.Value); } // convert the elements first, then decide if its a primitive or complex collection // note that a collection containing all null values will appear as a primitive collection, regardless of what the type really is List<PropertyInstance> elements = null; if (bagElementTypeName != null) { elements = propertyElement.Elements().Select(e => this.DeserializeProperty(e, bagElementTypeName)).ToList(); } else { elements = propertyElement.Elements().Select(e => this.DeserializeProperty(e)).ToList(); } if (elements.OfType<ComplexProperty>().Any()) { var complex = new ComplexMultiValueProperty(propertyName, new ComplexMultiValue(fullTypeName, false)); foreach (var complexElement in elements) { if (complexElement.ElementType == ODataPayloadElementType.NullPropertyInstance) { var nullProperty = complexElement as NullPropertyInstance; complex.Value.Add(new ComplexInstance(nullProperty.FullTypeName, true)); } else { ExceptionUtilities.Assert(complexElement.ElementType == ODataPayloadElementType.ComplexProperty, "Complex value collection contained non-complex, non-null value"); complex.Value.Add((complexElement as ComplexProperty).Value); } } return complex; } else { var primitive = new PrimitiveMultiValueProperty(propertyName, new PrimitiveMultiValue(fullTypeName, false)); foreach (var primitiveElement in elements) { if (primitiveElement.ElementType == ODataPayloadElementType.NullPropertyInstance) { var nullProperty = primitiveElement as NullPropertyInstance; primitive.Value.Add(new PrimitiveValue(nullProperty.FullTypeName, null)); } else { ExceptionUtilities.Assert(primitiveElement.ElementType == ODataPayloadElementType.PrimitiveProperty, "Primitive value collection contained non-primitive, non-null value"); primitive.Value.Add((primitiveElement as PrimitiveProperty).Value); } } return primitive; } }
/// <summary> /// Creates a new MultiValue property and sets the value to an empty collection that will be filled when visiting the complex instances. /// </summary> /// <param name="payloadElement">The complex MultiValue property to process.</param> public override void Visit(ComplexMultiValueProperty payloadElement) { var odataProperty = new ODataProperty() { Name = payloadElement.Name, Value = new ODataCollectionValue() { Items = new List<object>(), TypeName = payloadElement.Value.FullTypeName } }; this.currentProperties.Add(odataProperty); base.Visit(payloadElement); }
/// <summary> /// Deserializes the element as either a complex, a primitive, or a null property, based on the content /// </summary> /// <param name="property">The xml to deserialize</param> /// <param name="typeNameFallback">TypeName to use instead of the one from the XElement[type] attribute</param> /// <returns>A property representing the given xml</returns> private PropertyInstance DeserializeProperty(XElement property, string typeNameFallback) { string propertyName = property.Name.LocalName; // get the type name string typeNameFromPayload = null; XAttribute typeAttribute = property.Attribute(MetadataType); if (typeAttribute != null) { typeNameFromPayload = typeAttribute.Value; } // set type to be fallback when typeattribute does not exist var typeNameForClrTypeLookup = typeNameFromPayload; if (typeNameForClrTypeLookup == null && !string.IsNullOrEmpty(typeNameFallback)) { typeNameForClrTypeLookup = typeNameFallback; } // try to infer the clr type Type clrType = null; if (!string.IsNullOrEmpty(typeNameForClrTypeLookup)) { ExceptionUtilities.CheckObjectNotNull(this.PrimitiveDataTypeConverter, "Cannot infer clr type from edm type without converter"); clrType = this.PrimitiveDataTypeConverter.ToClrType(typeNameForClrTypeLookup); } PropertyInstance result; if (property.HasElements) { // must be complex, a multivalue, or spatial ExceptionUtilities.CheckObjectNotNull(this.SpatialFormatter, "Cannot safely deserialize element with children without spatial formatter."); // try to infer which spatial type hierarchy it is from the type name in the payload SpatialTypeKind? kind = null; if (clrType != null) { SpatialUtilities.TryInferSpatialTypeKind(clrType, out kind); } object spatialInstance; if (this.SpatialFormatter.TryParse(property.Elements().First(), kind, out spatialInstance)) { ExceptionUtilities.Assert(property.Elements().Count() == 1, "Spatial property had more than 1 sub-element"); result = new PrimitiveProperty(propertyName, typeNameFromPayload, spatialInstance); } else if (property.Elements().All(e => e.Name == DataServicesElement)) { result = this.DeserializeCollectionProperty(property); } else { result = new ComplexProperty(propertyName, this.DeserializeComplexInstance(property)); } } else { // check for the null attribute bool isNull = false; XAttribute isNullAttribute = property.Attribute(MetadataNull); if (isNullAttribute != null) { isNull = bool.Parse(isNullAttribute.Value); } // If its null and we can't tell whether it is primitive or complex, then return a null marker if (isNull && clrType == null) { result = new NullPropertyInstance(propertyName, typeNameFromPayload); } else if (typeNameFromPayload != null && typeNameFromPayload.StartsWith(ODataConstants.BeginMultiValueTypeIdentifier, StringComparison.Ordinal)) { ExceptionUtilities.CheckObjectNotNull(this.PrimitiveDataTypeConverter, "Cannot infer clr type from edm type without converter"); string elementTypeName = ParseBagElementTypeName(typeNameFromPayload); if (this.PrimitiveDataTypeConverter.ToClrType(elementTypeName) != null) { result = new PrimitiveMultiValueProperty(propertyName, new PrimitiveMultiValue(typeNameFromPayload, isNull)); } else { result = new ComplexMultiValueProperty(propertyName, new ComplexMultiValue(typeNameFromPayload, isNull)); } } else { object value; if (isNull) { value = null; } else if (clrType != null) { ExceptionUtilities.CheckObjectNotNull(this.PrimitiveConverter, "PrimitiveConverter has not been set."); value = this.PrimitiveConverter.DeserializePrimitive(property.Value, clrType); } else { value = property.Value; } result = new PrimitiveProperty(propertyName, typeNameFromPayload, value); } } AddXmlBaseAnnotation(result, property); return result; }
private void PopulateComplexMultiValuePropertyFromPaths(ComplexInstance instance, MemberProperty memberProperty, string propertyPath, IEnumerable<NamedValue> namedValues, ComplexDataType complexTypeElementDataType) { int i = 0; bool completed = false; var complexCollection = new ComplexMultiValueProperty(memberProperty.Name, new ComplexMultiValue(complexTypeElementDataType.BuildMultiValueTypeName(), false)); while (!completed) { IEnumerable<NamedValue> complexInstanceNamedValues = namedValues.Where(pp => pp.Name.StartsWith(propertyPath + "." + i + ".", StringComparison.Ordinal)).ToList(); if (complexInstanceNamedValues.Count() == 0) { completed = true; } else { ComplexInstance complexInstance = this.ComplexInstance(complexTypeElementDataType.Definition, propertyPath + "." + i, complexInstanceNamedValues); complexCollection.Value.Add(complexInstance); } i++; } if (i > 1) { instance.Add(complexCollection); } }
/// <summary> /// Visits a complex property. A copy of the current properties to be written is taken so that /// the complex property can use the global list to track its properties as its children are visited. /// Adds the complex property to the list of properties to be written. /// </summary> /// <param name="payloadElement">The complex property to visit and add</param> public override void Visit(ComplexMultiValueProperty payloadElement) { // Save off properties of parent var arr = this.odataProperties; var items = new List<ODataComplexValue>(); foreach (var item in payloadElement.Value) { this.odataProperties = new List<ODataProperty>(); this.Visit(item); ExceptionUtilities.CheckObjectNotNull(this.odataProperties, "ODataProperties cannot be null"); var typename = item.FullTypeName.Substring(11, item.FullTypeName.Length - 12); var complexValue = new ODataComplexValue() { TypeName = typename }; complexValue.Properties = this.odataProperties.ToList();//.AsEnumerable(); items.Add(complexValue); } //Return the global property list to its initial state with the new complex property added this.odataProperties.Clear(); this.odataProperties.AddRange(arr); //create a new complex collection property to add to the list from the properties children this.odataProperties.Add(new ODataProperty() { Name = payloadElement.Name, Value = new ODataCollectionValue() { Items = items, TypeName = payloadElement.Value.FullTypeName } }); }
/// <summary> /// Deserializes a collection property /// </summary> /// <param name="propertyElement">The xml element representing the property</param> /// <returns>The deserialized property</returns> private PropertyInstance DeserializeCollectionProperty(XElement propertyElement) { ExceptionUtilities.CheckArgumentNotNull(propertyElement, "propertyElement"); ExceptionUtilities.CheckCollectionNotEmpty(propertyElement.Elements(), "propertyElement.Elements()"); ExceptionUtilities.Assert(propertyElement.Elements().All(e => e.Name == DataServicesElement), "Collection property sub elements had inconsistent names"); string propertyName = propertyElement.Name.LocalName; string fullTypeName = null; string bagElementTypeName = null; var type = propertyElement.Attribute(MetadataType); if (type != null) { fullTypeName = type.Value; bagElementTypeName = ParseBagElementTypeName(type.Value); } // convert the elements first, then decide if its a primitive or complex collection // note that a collection containing all null values will appear as a primitive collection, regardless of what the type really is List <PropertyInstance> elements = null; if (bagElementTypeName != null) { elements = propertyElement.Elements().Select(e => this.DeserializeProperty(e, bagElementTypeName)).ToList(); } else { elements = propertyElement.Elements().Select(e => this.DeserializeProperty(e)).ToList(); } if (elements.OfType <ComplexProperty>().Any()) { var complex = new ComplexMultiValueProperty(propertyName, new ComplexMultiValue(fullTypeName, false)); foreach (var complexElement in elements) { if (complexElement.ElementType == ODataPayloadElementType.NullPropertyInstance) { var nullProperty = complexElement as NullPropertyInstance; complex.Value.Add(new ComplexInstance(nullProperty.FullTypeName, true)); } else { ExceptionUtilities.Assert(complexElement.ElementType == ODataPayloadElementType.ComplexProperty, "Complex value collection contained non-complex, non-null value"); complex.Value.Add((complexElement as ComplexProperty).Value); } } return(complex); } else { var primitive = new PrimitiveMultiValueProperty(propertyName, new PrimitiveMultiValue(fullTypeName, false)); foreach (var primitiveElement in elements) { if (primitiveElement.ElementType == ODataPayloadElementType.NullPropertyInstance) { var nullProperty = primitiveElement as NullPropertyInstance; primitive.Value.Add(new PrimitiveValue(nullProperty.FullTypeName, null)); } else { ExceptionUtilities.Assert(primitiveElement.ElementType == ODataPayloadElementType.PrimitiveProperty, "Primitive value collection contained non-primitive, non-null value"); primitive.Value.Add((primitiveElement as PrimitiveProperty).Value); } } return(primitive); } }
/// <summary> /// Visits a payload element whose root is a ComplexCollectionProperty. /// </summary> /// <param name="payloadElement">The root node of payload element being visited.</param> public void Visit(ComplexMultiValueProperty payloadElement) { bool needsWrapping = this.isRootElement; if (needsWrapping) { this.isRootElement = false; this.writer.StartObjectScope(); } this.writer.WriteName(payloadElement.Name); // if an annotation is present that specifies not to use the wrapper, don't bool useResultsWrapper = !payloadElement.Value.Annotations.OfType<JsonCollectionResultWrapperAnnotation>().Any(a => !a.Value); if (useResultsWrapper) { this.writer.StartObjectScope(); if (payloadElement.Value.FullTypeName != null) { this.writer.WriteName("__metadata"); this.writer.StartObjectScope(); this.writer.WriteName("type"); this.writer.WriteString(payloadElement.Value.FullTypeName); this.writer.EndScope(); } this.writer.WriteName("results"); } if (payloadElement.Value.IsNull) { this.writer.WriteNull(); } else { this.Recurse(payloadElement.Value); } if (useResultsWrapper) { this.writer.EndScope(); } if (needsWrapping) { this.writer.EndScope(); } }
/// <summary> /// Deserializes the element as either a complex, a primitive, or a null property, based on the content /// </summary> /// <param name="property">The xml to deserialize</param> /// <param name="typeNameFallback">TypeName to use instead of the one from the XElement[type] attribute</param> /// <returns>A property representing the given xml</returns> private PropertyInstance DeserializeProperty(XElement property, string typeNameFallback) { string propertyName = property.Name.LocalName; // get the type name string typeNameFromPayload = null; XAttribute typeAttribute = property.Attribute(MetadataType); if (typeAttribute != null) { typeNameFromPayload = typeAttribute.Value; } // set type to be fallback when typeattribute does not exist var typeNameForClrTypeLookup = typeNameFromPayload; if (typeNameForClrTypeLookup == null && !string.IsNullOrEmpty(typeNameFallback)) { typeNameForClrTypeLookup = typeNameFallback; } // try to infer the clr type Type clrType = null; if (!string.IsNullOrEmpty(typeNameForClrTypeLookup)) { ExceptionUtilities.CheckObjectNotNull(this.PrimitiveDataTypeConverter, "Cannot infer clr type from edm type without converter"); clrType = this.PrimitiveDataTypeConverter.ToClrType(typeNameForClrTypeLookup); } PropertyInstance result; if (property.HasElements) { // must be complex, a multivalue, or spatial ExceptionUtilities.CheckObjectNotNull(this.SpatialFormatter, "Cannot safely deserialize element with children without spatial formatter."); // try to infer which spatial type hierarchy it is from the type name in the payload SpatialTypeKind?kind = null; if (clrType != null) { SpatialUtilities.TryInferSpatialTypeKind(clrType, out kind); } object spatialInstance; if (this.SpatialFormatter.TryParse(property.Elements().First(), kind, out spatialInstance)) { ExceptionUtilities.Assert(property.Elements().Count() == 1, "Spatial property had more than 1 sub-element"); result = new PrimitiveProperty(propertyName, typeNameFromPayload, spatialInstance); } else if (property.Elements().All(e => e.Name == DataServicesElement)) { result = this.DeserializeCollectionProperty(property); } else { result = new ComplexProperty(propertyName, this.DeserializeComplexInstance(property)); } } else { // check for the null attribute bool isNull = false; XAttribute isNullAttribute = property.Attribute(MetadataNull); if (isNullAttribute != null) { isNull = bool.Parse(isNullAttribute.Value); } // If its null and we can't tell whether it is primitive or complex, then return a null marker if (isNull && clrType == null) { result = new NullPropertyInstance(propertyName, typeNameFromPayload); } else if (typeNameFromPayload != null && typeNameFromPayload.StartsWith(ODataConstants.BeginMultiValueTypeIdentifier, StringComparison.Ordinal)) { ExceptionUtilities.CheckObjectNotNull(this.PrimitiveDataTypeConverter, "Cannot infer clr type from edm type without converter"); string elementTypeName = ParseBagElementTypeName(typeNameFromPayload); if (this.PrimitiveDataTypeConverter.ToClrType(elementTypeName) != null) { result = new PrimitiveMultiValueProperty(propertyName, new PrimitiveMultiValue(typeNameFromPayload, isNull)); } else { result = new ComplexMultiValueProperty(propertyName, new ComplexMultiValue(typeNameFromPayload, isNull)); } } else { object value; if (isNull) { value = null; } else if (clrType != null) { ExceptionUtilities.CheckObjectNotNull(this.PrimitiveConverter, "PrimitiveConverter has not been set."); value = this.PrimitiveConverter.DeserializePrimitive(property.Value, clrType); } else { value = property.Value; } result = new PrimitiveProperty(propertyName, typeNameFromPayload, value); } } AddXmlBaseAnnotation(result, property); return(result); }
/// <summary> /// Builds a complex instance from the given payloadElements to represent a parameters payload. /// </summary> /// <param name="payloadElements">Each ODataPayloadElement represents the value for each parameter.</param> /// <param name="model">EdmModel instance.</param> /// <param name="functionImportName">Name of the function import to add to the model.</param> /// <returns></returns> private static ComplexInstance PayloadElementsToParameterPayload(ODataPayloadElement[] payloadElements, EdmModel model, string functionImportName) { EdmOperationImport operationImport = (EdmOperationImport)model.EntityContainer.FindOperationImports(functionImportName).FirstOrDefault(); EdmOperation operation = (EdmOperation)operationImport.Operation; var parameterPayload = new ComplexInstance(null, false); for (int idx = 0; idx < payloadElements.Length; idx++) { ODataPayloadElement p = payloadElements[idx]; string parameterName = "p" + idx; PropertyInstance parameter; IEdmTypeReference entityModelType = p.GetAnnotation <EntityModelTypeAnnotation>().EdmModelType; switch (p.ElementType) { case ODataPayloadElementType.PrimitiveValue: object clrValue = ((PrimitiveValue)p).ClrValue; PrimitiveValue primitiveValue = new PrimitiveValue(clrValue == null ? null : clrValue.GetType().FullName, clrValue); primitiveValue.CopyAnnotation <PrimitiveValue, EntityModelTypeAnnotation>(p); parameter = new PrimitiveProperty(parameterName, primitiveValue); operation.AddParameter(parameterName, MetadataUtils.GetPrimitiveTypeReference(primitiveValue.ClrValue.GetType())); break; case ODataPayloadElementType.ComplexInstance: parameter = new ComplexProperty(parameterName, (ComplexInstance)p); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.PrimitiveMultiValue: PrimitiveMultiValue primitiveMultiValue = (PrimitiveMultiValue)p; if (primitiveMultiValue.Annotations.OfType <JsonCollectionResultWrapperAnnotation>().SingleOrDefault() == null) { primitiveMultiValue.Annotations.Add(new JsonCollectionResultWrapperAnnotation(false)); } parameter = new PrimitiveMultiValueProperty(parameterName, primitiveMultiValue); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.ComplexMultiValue: ComplexMultiValue complexMultiValue = (ComplexMultiValue)p; if (complexMultiValue.Annotations.OfType <JsonCollectionResultWrapperAnnotation>().SingleOrDefault() == null) { complexMultiValue.Annotations.Add(new JsonCollectionResultWrapperAnnotation(false)); } parameter = new ComplexMultiValueProperty(parameterName, complexMultiValue); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.EntityInstance: parameter = new NavigationPropertyInstance(parameterName, (EntityInstance)p); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.EntitySetInstance: parameter = new NavigationPropertyInstance(parameterName, (EntitySetInstance)p); operation.AddParameter(parameterName, entityModelType); break; default: throw new NotSupportedException("PayloadElementsToParameterPayload() is called on unsupported ODataPayloadElement type: " + p.ElementType); } parameterPayload.Add(parameter); } parameterPayload.ExpectedFunctionImport(operationImport); return(parameterPayload); }
public void OpenTopLevelPropertiesTest() { IEdmModel model = TestModels.BuildTestModel(); var testCases = new OpenPropertyTestCase[] { new OpenPropertyTestCase { DebugDescription = "Integer open property.", ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", 42), ExpectedPropertyWhenTypeUnavailable = PayloadBuilder.PrimitiveProperty("OpenProperty", 42), ExpectedPropertyType = EdmCoreModel.Instance.GetInt32(false), JsonTypeInformation = "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"Edm.Int32\",", Json = "{0}{1}\"" + JsonLightConstants.ODataValuePropertyName + "\":42", }, new OpenPropertyTestCase { DebugDescription = "Null open property.", ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", null), ExpectedPropertyWhenTypeUnavailable = PayloadBuilder.PrimitiveProperty("OpenProperty", null), ExpectedPropertyType = EdmCoreModel.Instance.GetString(true), JsonTypeInformation = string.Empty, Json = "{0}{1}\"value\":null", }, new OpenPropertyTestCase { DebugDescription = "String open property.", ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", "value"), ExpectedPropertyWhenTypeUnavailable = PayloadBuilder.PrimitiveProperty("OpenProperty", "value"), ExpectedPropertyType = EdmCoreModel.Instance.GetString(true), JsonTypeInformation = "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"Edm.String\",", Json = "{0}{1}\"" + JsonLightConstants.ODataValuePropertyName + "\":\"" + JsonLightConstants.ODataValuePropertyName + "\"", }, new OpenPropertyTestCase { DebugDescription = "DateTimeOffset open property with type information.", ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", new DateTimeOffset(2012, 4, 13, 2, 43, 10, 215, TimeSpan.Zero)), ExpectedPropertyWhenTypeUnavailable = PayloadBuilder.PrimitiveProperty("OpenProperty", "2012-04-13T02:43:10.215Z"), ExpectedPropertyType = EdmCoreModel.Instance.GetDateTimeOffset(false), JsonTypeInformation = "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"Edm.DateTimeOffset\",", Json = "{0}{1}\"" + JsonLightConstants.ODataValuePropertyName + "\":\"2012-04-13T02:43:10.215Z\"", }, }; bool[] withExpectedTypes = new bool[] { true, false }; bool[] withPayloadTypes = new bool[] { true, false }; bool[] includeContextUri = new bool[] { true, false }; this.CombinatorialEngineProvider.RunCombinations( testCases, withExpectedTypes, withPayloadTypes, includeContextUri, this.ReaderTestConfigurationProvider.JsonLightFormatConfigurations, (testCase, withExpectedType, withPayloadType, withContextUri, testConfiguration) => { if (withContextUri && testConfiguration.IsRequest) { return; } string expectedTypeName = testCase.ExpectedPropertyType is IEdmCollectionTypeReference ? "Collection(" + ((IEdmCollectionType)testCase.ExpectedPropertyType.Definition).ElementType.FullName() + ")" : testCase.ExpectedPropertyType.TestFullName(); string contextUri = withContextUri ? "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + string.Format("\":\"http://odata.org/test/$metadata#{0}\",", expectedTypeName) : string.Empty; string json = string.Format( CultureInfo.InvariantCulture, testCase.Json, contextUri, withPayloadType ? testCase.JsonTypeInformation : string.Empty); bool typeGiven = withExpectedType || withPayloadType || withContextUri; if (!typeGiven && testCase.ExpectedPropertyWhenTypeUnavailable == null) { testCase.ExpectedException = ODataExpectedExceptions.ODataException("ReaderValidationUtils_ValueWithoutType"); } PropertyInstance property = typeGiven || testCase.ExpectedPropertyWhenTypeUnavailable == null ? testCase.ExpectedProperty : testCase.ExpectedPropertyWhenTypeUnavailable; property = property.DeepCopy(); if (withExpectedType) { property = property.ExpectedPropertyType(testCase.ExpectedPropertyType); } if (!withPayloadType) { ComplexProperty complexProperty = property as ComplexProperty; if (complexProperty != null) { complexProperty.Value.AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null }); } else { PrimitiveMultiValueProperty primitiveCollectionProperty = property as PrimitiveMultiValueProperty; if (primitiveCollectionProperty != null) { primitiveCollectionProperty.Value.AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null }); } else { ComplexMultiValueProperty complexCollectionProperty = property as ComplexMultiValueProperty; if (complexCollectionProperty != null) { complexCollectionProperty.Value.AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null }); } } } } ExpectedException expectedException = testCase.ExpectedException; if (!withContextUri && !testConfiguration.IsRequest) { expectedException = ODataExpectedExceptions.ODataException("ODataJsonLightDeserializer_ContextLinkNotFoundAsFirstProperty"); } PayloadReaderTestDescriptor testDescriptor = new PayloadReaderTestDescriptor(this.Settings) { DebugDescription = testCase.DebugDescription + "[Expected type: " + withExpectedType + ", payload type: " + withPayloadType + "]", PayloadElement = property .JsonRepresentation("{" + json + "}"), PayloadEdmModel = model, ExpectedException = expectedException, }; // These descriptors are already tailored specifically for Json Light and // do not require normalization. testDescriptor.TestDescriptorNormalizers.Clear(); testDescriptor.RunTest(testConfiguration); }); }
public void NullPropertyNameTest() { EdmModel model = new EdmModel(); var complexType1 = new EdmComplexType("TestNS", "ComplexType1"); complexType1.AddStructuralProperty("StringProperty", EdmPrimitiveTypeKind.String, isNullable: false); model.AddElement(complexType1); var entityType1 = new EdmEntityType("TestNS", "EntityType1"); entityType1.AddStructuralProperty("ComplexProperty", new EdmComplexTypeReference(complexType1, isNullable: false)); model.AddElement(entityType1); var entityType2 = new EdmEntityType("TestNS", "EntityType2"); entityType2.AddStructuralProperty("ComplexCollection", EdmCoreModel.GetCollection(new EdmComplexTypeReference(complexType1, isNullable: false))); model.AddElement(entityType2); // For these payloads we expect that the product will infer and write the type on the complex and collection properties on the entries. // As such we expect a different payload to what we write. // Complex Property + expected ComplexInstance instance = PayloadBuilder.ComplexValue(); instance.PrimitiveProperty("StringProperty", "Hello"); ComplexProperty complexProperty = new ComplexProperty("ComplexProperty", instance); ComplexInstance instanceWithType = PayloadBuilder.ComplexValue("TestNS.ComplexType1"); instanceWithType.PrimitiveProperty("StringProperty", "Hello"); ComplexProperty complexPropertyWithType = new ComplexProperty("ComplexProperty", instanceWithType); // Entity Instance with complex property + expected EntityInstance entity1 = new EntityInstance("TestNS.EntityType1", false /*isNull*/); entity1.Property(complexProperty); entity1.Id = "urn:Id"; entity1.WithTypeAnnotation(entityType1); EntityInstance expectedEntity1 = new EntityInstance("TestNS.EntityType1", false /*isNull*/); expectedEntity1.Property(complexPropertyWithType); expectedEntity1.Id = "urn:Id"; expectedEntity1.WithTypeAnnotation(entityType1); // Complex Collection Property ComplexMultiValueProperty collection = new ComplexMultiValueProperty("ComplexCollection", new ComplexMultiValue(null, false, instance)); ComplexMultiValueProperty collectionWithType = new ComplexMultiValueProperty("ComplexCollection", new ComplexMultiValue("Collection(TestNS.ComplexType1)", false, instanceWithType)); // Entity Instance with collection property EntityInstance entity2 = new EntityInstance("TestNS.EntityType2", false); entity2.Property(collection); entity2.Id = "urn:Id"; entity2.WithTypeAnnotation(entityType2); EntityInstance expectedEntity2 = new EntityInstance("TestNS.EntityType2", false); expectedEntity2.Property(collectionWithType); expectedEntity2.Id = "urn:Id"; expectedEntity2.WithTypeAnnotation(entityType2); PayloadWriterTestDescriptor<ODataPayloadElement>[] testDescriptors = new PayloadWriterTestDescriptor<ODataPayloadElement>[] { new PayloadWriterTestDescriptor<ODataPayloadElement>(this.Settings, (ODataPayloadElement)null) { PayloadElement = entity1, Model = model, ExpectedResultCallback = (tc) => { return new PayloadWriterTestExpectedResults(this.ExpectedResultSettings) { ExpectedPayload = expectedEntity1 }; }, }, new PayloadWriterTestDescriptor<ODataPayloadElement>(this.Settings, (ODataPayloadElement)null) { PayloadElement = entity2, Model = model, ExpectedResultCallback = (tc) => { return new PayloadWriterTestExpectedResults(this.ExpectedResultSettings) { ExpectedPayload = expectedEntity2 }; }, } }; // TODO: Fix places where we've lost JsonVerbose coverage to add JsonLight this.CombinatorialEngineProvider.RunCombinations( testDescriptors, this.WriterTestConfigurationProvider.ExplicitFormatConfigurationsWithIndent.Where(tc => tc.Format == ODataFormat.Atom), (testDescriptor, testConfiguration) => { testConfiguration = testConfiguration.Clone(); testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri); testDescriptor.RunTest(testConfiguration, this.Logger); }); }
public PropertyInstance MultiValueProperty(MemberProperty memberProperty, object anonymous) { ExceptionUtilities.CheckArgumentNotNull(memberProperty, "memberProperty"); var collectionType = memberProperty.PropertyType as CollectionDataType; ExceptionUtilities.CheckObjectNotNull(collectionType, "Property '{0}' was not a collection"); var enumerable = anonymous as IEnumerable; ExceptionUtilities.CheckObjectNotNull(enumerable, "Value for property '{0}' was not enumerable"); var primitiveType = collectionType.ElementDataType as PrimitiveDataType; if (primitiveType != null) { var primitiveCollection = new PrimitiveMultiValueProperty(memberProperty.Name, new PrimitiveMultiValue(primitiveType.BuildMultiValueTypeName(), false)); foreach (var thing in enumerable) { primitiveCollection.Value.Add(this.PrimitiveProperty(new MemberProperty("temp", primitiveType), thing).Value); } return primitiveCollection; } else { var complexType = collectionType.ElementDataType as ComplexDataType; ExceptionUtilities.CheckObjectNotNull(complexType, "Collection property '{0}' did not have a primitive or complex collection type", memberProperty.Name); var complexCollection = new ComplexMultiValueProperty(memberProperty.Name, new ComplexMultiValue(complexType.BuildMultiValueTypeName(), false)); foreach (var thing in enumerable) { complexCollection.Value.Add(this.ComplexInstance(complexType.Definition, thing)); } return complexCollection; } }
/// <summary> /// Visits a payload element whose root is a ComplexMultiValueProperty. /// </summary> /// <param name="payloadElement">The root node of the payload element being visited.</param> public override void Visit(ComplexMultiValueProperty payloadElement) { base.Visit(payloadElement); if (this.CurrentElementIsRoot()) { Func<MemberProperty, bool> matchesProperty = (p) => { if (p.Name == payloadElement.Name && p.PropertyType is CollectionDataType) { var complexElementType = ((CollectionDataType)p.PropertyType).ElementDataType as ComplexDataType; return complexElementType != null && payloadElement.Value.FullTypeName == "Collection(" + complexElementType.Definition.FullName + ")"; } return false; }; Func<IEdmProperty, bool> EdmMatchesProperty = (p) => { if (p.Name == payloadElement.Name && p.DeclaringType as IEdmCollectionType != null) { var complexElementType = ((IEdmCollectionType)p.DeclaringType).ElementType as IEdmComplexType; return complexElementType != null && payloadElement.Value.FullTypeName == "Collection(" + complexElementType.FullName() + ")"; } return false; }; var valueTypeAnnotation = payloadElement.Value.Annotations.OfType<EntityModelTypeAnnotation>().SingleOrDefault(); if (valueTypeAnnotation != null) { if (valueTypeAnnotation.EdmModelType != null) { var edmEntityType = valueTypeAnnotation.EdmModelType; this.AddExpectedTypeToProperty(payloadElement, edmEntityType, EdmMatchesProperty); } } else { var edmEntityType = this.ResolvePropertyEdmDataType(payloadElement.Value.FullTypeName); this.AddExpectedTypeToProperty(payloadElement, edmEntityType, EdmMatchesProperty); } } this.AnnotateIfOpenProperty(payloadElement, payloadElement.Value); }
/// <summary> /// Visits a collection of parameters. /// </summary> /// <param name="parameters">The parameters to visit.</param> protected override ODataPayloadElement VisitParameters(ODataParameters parameters) { ExceptionUtilities.CheckArgumentNotNull(parameters, "parameters"); ComplexInstance result = new ComplexInstance(); result.IsNull = parameters.Count == 0; foreach (var parameter in parameters) { if (parameter.Value == null) { result.Add(new PrimitiveProperty(parameter.Key, null, null)); continue; } ODataComplexValue odataComplexValue = parameter.Value as ODataComplexValue; ODataCollectionStart odataCollectionStart = parameter.Value as ODataCollectionStart; if (odataCollectionStart != null) { ODataCollectionItemsObjectModelAnnotation annotation = odataCollectionStart.GetAnnotation <ODataCollectionItemsObjectModelAnnotation>(); if (annotation.OfType <ODataComplexValue>().FirstOrDefault() != null) { ComplexMultiValue complexCollection = PayloadBuilder.ComplexMultiValue(); foreach (var value in annotation) { complexCollection.Item(this.VisitComplexValue(value as ODataComplexValue) as ComplexInstance); } ComplexMultiValueProperty complexCollectionProperty = new ComplexMultiValueProperty(parameter.Key, complexCollection); result.Add(complexCollectionProperty); } else { PrimitiveMultiValue primitiveCollection = PayloadBuilder.PrimitiveMultiValue(); foreach (var value in annotation) { primitiveCollection.Item(value); } PrimitiveMultiValueProperty primitiveCollectionProperty = new PrimitiveMultiValueProperty(parameter.Key, primitiveCollection); result.Add(primitiveCollectionProperty); } } else if (odataComplexValue != null) { ComplexInstance complexInstance = PayloadBuilder.ComplexValue(odataComplexValue.TypeName); complexInstance.IsNull = false; foreach (ODataProperty odataProperty in odataComplexValue.Properties) { complexInstance.Property(odataProperty.Name, this.Visit(odataProperty.Value)); } result.Add(new ComplexProperty(parameter.Key, complexInstance)); } else { result.Add(new PrimitiveProperty(parameter.Key, null, PayloadBuilder.PrimitiveValue(parameter.Value).ClrValue)); } } return(result); }