/// <summary> /// Converts a LinqNewExpression to a Complex Instance /// </summary> /// <param name="expression">Expression to convert to a ComplexInstance</param> /// <returns>Complex Instance</returns> internal static ComplexInstance ConvertToComplexInstance(this QueryExpression expression) { var nullConstantExpression = expression as QueryNullExpression; var queryComplexType = (QueryComplexType)expression.ExpressionType; if (nullConstantExpression != null) { return(new ComplexInstance(queryComplexType.ComplexType.FullName, true)); } var structuralExpression = expression as LinqNewInstanceExpression; var newComplexInstance = new ComplexInstance(queryComplexType.ComplexType.FullName, false); ExceptionUtilities.Assert(structuralExpression.MemberNames.Count == structuralExpression.Members.Count, "MemberNames and Members count are not equal"); for (int i = 0; i < structuralExpression.MemberNames.Count; i++) { string memberName = structuralExpression.MemberNames[i]; var memberExpression = structuralExpression.Members[i]; var memberProperty = queryComplexType.ComplexType.Properties.Single(p => p.Name == memberName); var complexDataType = memberProperty.PropertyType as ComplexDataType; var collectionDataType = memberProperty.PropertyType as CollectionDataType; if (complexDataType != null) { var childComplexInstance = memberExpression.ConvertToComplexInstance(); var complexProperty = new ComplexProperty() { Name = memberName, Value = childComplexInstance }; newComplexInstance.Add(complexProperty); } else if (collectionDataType != null) { var collectionPropertyType = memberProperty.PropertyType as CollectionDataType; var convertedValue = memberExpression.ConvertToMultiValue(collectionPropertyType.ElementDataType); if (collectionPropertyType.ElementDataType is ComplexDataType) { newComplexInstance.Add(new ComplexMultiValueProperty(memberName, convertedValue as ComplexMultiValue)); } else { var primitiveDataType = collectionPropertyType.ElementDataType as PrimitiveDataType; ExceptionUtilities.CheckObjectNotNull(primitiveDataType, "Not a primitiveDataType '{0}'", collectionPropertyType.ElementDataType); newComplexInstance.Add(new PrimitiveMultiValueProperty(memberName, convertedValue as PrimitiveMultiValue)); } } else { var primitiveDataType = memberProperty.PropertyType as PrimitiveDataType; ExceptionUtilities.CheckObjectNotNull(primitiveDataType, "Expected a PrimitiveDataType"); var primitiveValue = memberExpression.ConvertToPrimitiveValue(primitiveDataType); newComplexInstance.Add(new PrimitiveProperty(memberName, primitiveDataType.GetEdmTypeName(), primitiveValue.ClrValue)); } } return(newComplexInstance); }
private void PopulatePropertiesFromPaths(ComplexInstance instance, IEnumerable <MemberProperty> properties, string propertyPath, IEnumerable <NamedValue> namedValues) { ExceptionUtilities.CheckArgumentNotNull(instance, "instance"); ExceptionUtilities.CheckArgumentNotNull(properties, "properties"); ExceptionUtilities.CheckArgumentNotNull(namedValues, "namedValues"); foreach (MemberProperty property in properties) { string childPropertyPath = property.Name; if (propertyPath != null) { childPropertyPath = propertyPath + "." + property.Name; } CollectionDataType collectionDataType = property.PropertyType as CollectionDataType; PrimitiveDataType primitiveDataType = property.PropertyType as PrimitiveDataType; if (primitiveDataType != null) { NamedValue memberPropertyNamedValue = namedValues.SingleOrDefault(nv => nv.Name == childPropertyPath); if (memberPropertyNamedValue != null) { instance.Add(this.PrimitiveProperty(property, memberPropertyNamedValue.Value)); } } else if (collectionDataType != null) { IEnumerable <NamedValue> bagNamedValues = namedValues.Where(nv => nv.Name.StartsWith(childPropertyPath + ".", StringComparison.Ordinal)).ToList(); if (bagNamedValues.Count() > 0) { this.PopulateMultiValuePropertyFromPaths(instance, property, collectionDataType.ElementDataType, childPropertyPath, bagNamedValues); } else { this.PopulateCollectionPropertyWithNullOrEmpty(instance, property, childPropertyPath, namedValues); } } else { var complexDataType = property.PropertyType as ComplexDataType; ExceptionUtilities.CheckObjectNotNull(complexDataType, "Property '{0}' was not primitive, a collection, or complex", property.Name); IEnumerable <NamedValue> complexInstanceNamedValues = namedValues.Where(nv => nv.Name.StartsWith(childPropertyPath + ".", StringComparison.Ordinal)).ToList(); if (complexInstanceNamedValues.Count() > 0) { PropertyInstance memberPropertyInstance = this.ComplexProperty(property, childPropertyPath, complexInstanceNamedValues); instance.Add(memberPropertyInstance); } else { // Check for null case IEnumerable <NamedValue> exactMatches = namedValues.Where(nv => nv.Name == childPropertyPath).ToList(); ExceptionUtilities.Assert(exactMatches.Count() < 2, "Should only find at most one property path {0} when looking for null value", childPropertyPath); if (exactMatches.Count() == 1) { instance.Add(new ComplexProperty(property.Name, new ComplexInstance(complexDataType.Definition.FullName, true))); } } } } }
/// <summary> /// Deserialize the element as a complex instance /// </summary> /// <param name="element">The xml representing a complex instance</param> /// <returns>The deserialized complex instance</returns> private ComplexInstance DeserializeComplexInstance(XElement element) { ComplexInstance instance = new ComplexInstance(); // get the type XAttribute type = element.Attribute(MetadataType); if (type != null) { instance.FullTypeName = type.Value; } // check for the null attribute XAttribute isNull = element.Attribute(MetadataNull); if (isNull != null) { instance.IsNull = bool.Parse(isNull.Value); } else if (element.HasElements) { instance.IsNull = false; } // get the properties foreach (XElement subElement in element.Elements()) { instance.Add(this.DeserializeProperty(subElement)); } return(instance); }
/// <summary> /// Creates a new complex value. If the complex instance is part of a complex collection value /// adds the complex value to MultiValue property's items collection; otherwise sets the complex value as /// value of a complex property. /// </summary> /// <param name="payloadElement"></param> public override void Visit(ComplexInstance payloadElement) { // figure out whether the complex value is part of a collection property (of complex values) or // the value for a complex property ODataProperty currentProperty = this.currentProperties.Last(); ODataCollectionValue currentMultiValue = currentProperty.Value as ODataCollectionValue; ODataComplexValue complexValue; if (currentMultiValue != null) { // create a new complex value and add it to the MultiValue complexValue = new ODataComplexValue(); complexValue.TypeName = payloadElement.FullTypeName.Substring(11, payloadElement.FullTypeName.Length - 12);; // we construct the MultiValue so we know that the items are a list IList itemsAsList = currentMultiValue.Items as IList; itemsAsList.Add(complexValue); } else { complexValue = (ODataComplexValue)currentProperty.Value; complexValue.TypeName = payloadElement.FullTypeName; } var previousProperties = this.currentProperties; this.currentProperties = new List <ODataProperty>(); base.Visit(payloadElement); complexValue.Properties = this.currentProperties; this.currentProperties = previousProperties; }
/// <summary> /// Because the test deserializer used to parse the actual payload will not have metadata, we fix it up here. /// Note: this should probably move to happen just before comparison, rather than when generating expectations. /// </summary> /// <param name="payloadElement">The payload element</param> private void SortAndNormalizeProperties(ComplexInstance payloadElement) { var sortedProperties = payloadElement.Properties.OrderBy(p => p.Name).ToList(); foreach (var p in sortedProperties) { var property = p; payloadElement.Remove(property); // If we have a primitive property with null value, we write a type name for the null value // in V1 and V2. If not type name is available or we are in V3, we don't do that and thus expect a null property instance. var primitiveProperty = property as PrimitiveProperty; if (primitiveProperty != null && primitiveProperty.Value.IsNull && (this.dsv >= DataServiceProtocolVersion.V4 || string.IsNullOrEmpty(primitiveProperty.Value.FullTypeName))) { property = new NullPropertyInstance(property.Name, null).WithAnnotations(property.Annotations); } var complexProperty = property as ComplexProperty; if (complexProperty != null && complexProperty.Value.IsNull) { property = new NullPropertyInstance(property.Name, complexProperty.Value.FullTypeName).WithAnnotations(property.Annotations); } var complexCollectionProperty = property as ComplexMultiValueProperty; if (complexCollectionProperty != null && complexCollectionProperty.Value.Count == 0 && complexCollectionProperty.Value.FullTypeName == null) { property = new PrimitiveProperty(complexCollectionProperty.Name, complexCollectionProperty.Value.FullTypeName, string.Empty); } payloadElement.Add(property); } }
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); } }
private void PopulatePrimitiveBagPropertyFromPaths(ComplexInstance instance, MemberProperty memberProperty, string propertyPath, IEnumerable <NamedValue> namedValues, PrimitiveDataType primitiveElementDataType) { int i = 0; bool completed = false; var primitiveCollection = new PrimitiveMultiValue(primitiveElementDataType.BuildMultiValueTypeName(), false); while (!completed) { IEnumerable <NamedValue> primitiveItemNamedValues = namedValues.Where(pp => pp.Name == propertyPath + "." + i).ToList(); if (primitiveItemNamedValues.Count() == 0) { completed = true; } else { ExceptionUtilities.Assert(primitiveItemNamedValues.Count() < 2, "Should not get more than one value for a primitive Bag item for path '{0}'", propertyPath + "." + i); var value = primitiveItemNamedValues.Single(); // Do something with the value primitiveCollection.Add(PrimitiveValue(primitiveElementDataType, value.Value)); } i++; } if (i > 1) { instance.Add(new PrimitiveMultiValueProperty(memberProperty.Name, primitiveCollection)); } }
private PropertyInstance BuildProperty(IEdmProperty property) { if (property.Type.IsCollection()) { var type = (IEdmCollectionType)property.Type.Definition; if (type.ElementType.IsComplex()) { var complex = new ComplexInstance(property.Type.FullName(), false).WithTypeAnnotation(type.ElementType.Definition); foreach (var prop in ((IEdmComplexType)type.ElementType.Definition).StructuralProperties()) { complex.Add(this.BuildProperty(prop)); } return(new ComplexMultiValueProperty(property.Name, new ComplexMultiValue(property.Type.FullName(), false, complex)).WithTypeAnnotation(type)); } return(new PrimitiveMultiValueProperty(property.Name, new PrimitiveMultiValue(property.Type.FullName(), false, this.GetValue((IEdmPrimitiveTypeReference)type.ElementType))).WithTypeAnnotation(property.Type)); } if (property.IsComplex()) { var complex = new ComplexInstance(property.Type.FullName(), false); foreach (var prop in ((IEdmComplexType)property.Type.Definition).StructuralProperties()) { complex.Add(this.BuildProperty(prop)); } return(new ComplexProperty(property.Name, complex).WithTypeAnnotation(property.Type)); } return(new PrimitiveProperty((property.Name), this.GetValue((IEdmPrimitiveTypeReference)property.Type)).WithTypeAnnotation(property.Type)); }
private void PopulatePropertiesFromObject(ComplexInstance instance, IEnumerable <MemberProperty> properties, object anonymous) { ExceptionUtilities.CheckArgumentNotNull(instance, "instance"); ExceptionUtilities.CheckArgumentNotNull(properties, "properties"); ExceptionUtilities.CheckArgumentNotNull(anonymous, "anonymous"); Type anonymousType = anonymous.GetType(); foreach (PropertyInfo info in anonymousType.GetProperties()) { object value = info.GetValue(anonymous, null); MemberProperty property = properties.SingleOrDefault(p => p.Name == info.Name); if (property == null) { instance.Add(this.DynamicProperty(info.Name, info.PropertyType, value)); } else if (property.PropertyType is ComplexDataType) { instance.Add(this.ComplexProperty(property, value)); } else if (property.PropertyType is CollectionDataType) { instance.Add(this.MultiValueProperty(property, value)); } else { instance.Add(this.PrimitiveProperty(property, value)); } } }
/// <summary> /// Visits a payload element whose root is a ComplexInstance. /// </summary> /// <param name="payloadElement">The root node of payload element being visited.</param> public void Visit(ComplexInstance payloadElement) { this.isRootElement = false; ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); if (payloadElement.IsNull) { this.writer.WriteNull(); } else { this.writer.StartObjectScope(); if (payloadElement.FullTypeName != null) { this.writer.WriteName("__metadata"); this.writer.StartObjectScope(); this.writer.WriteName("type"); this.writer.WriteString(payloadElement.FullTypeName); this.writer.EndScope(); } foreach (var property in payloadElement.Properties) { this.Recurse(property); } this.writer.EndScope(); } }
/// <summary> /// Visits a payload element whose root is an ComplexInstance. /// </summary> /// <param name="payloadElement">The root node of the payload element being visited.</param> public override ODataPayloadElement Visit(ComplexInstance payloadElement) { ComplexInstance complexInstance = (ComplexInstance)base.Visit(payloadElement); ReorderProperties(complexInstance); return(complexInstance); }
/// <summary> /// Normalizes complex value. /// </summary> /// <param name="payloadElement">The payload element to normalize.</param> public override void Visit(ComplexInstance payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); // First recurse to children so that we get those normalized and then normalize the parent entity. base.Visit(payloadElement); this.DeduplicateProperties(payloadElement); }
/// <summary> /// Builds a complex type instance of the given type out of the given anonymous object /// </summary> /// <param name="complexType">The metadata type information for the complex type</param> /// <param name="anonymous">The data as an anonymous type</param> /// <returns>An entity instance with the given values</returns> public ComplexInstance ComplexInstance(ComplexType complexType, object anonymous) { ComplexInstance instance = new ComplexInstance(complexType.FullName, anonymous == null); if (anonymous != null) { this.PopulatePropertiesFromObject(instance, complexType.Properties, anonymous); } return instance; }
/// <summary> /// Visits a payload element whose root is a ComplexInstance. /// </summary> /// <param name="expected">The root node of payload element being visited.</param> public void Visit(ComplexInstance expected) { ExceptionUtilities.CheckArgumentNotNull(expected, "expected"); var observed = this.GetNextObservedElement <ComplexInstance>(); using (this.Assert.WithMessage("Complex instance did not match expectation")) { this.CompareComplexInstance(expected, observed); } }
private void PopulateCollectionPropertyWithNullOrEmpty(ComplexInstance instance, MemberProperty memberProperty, string propertyPath, IEnumerable <NamedValue> namedValues) { IEnumerable <NamedValue> exactMatches = namedValues.Where(nv => nv.Name == propertyPath).ToList(); ExceptionUtilities.Assert(exactMatches.Count() < 2, "Should only find at most one property path {0} when looking for null value", propertyPath); if (exactMatches.Count() == 1) { instance.Add(this.MultiValuePropertyEmptyOrNull(memberProperty, exactMatches.Single().Value)); } }
/// <summary> /// Creates a new complex value. If the complex instance is part of a complex collection value /// adds the complex value to MultiValue property's items collection; otherwise sets the complex value as /// value of a complex property. /// </summary> /// <param name="payloadElement"></param> public override void Visit(ComplexInstance payloadElement) { // figure out whether the complex value is part of a collection property (of complex values), // the value for a complex property, or top level object parent = null; if (this.items.Any()) { parent = this.items.Peek(); } ODataComplexValue complexValue = null; if (parent != null) { var currentMultiValue = parent as ODataCollectionValue; if (currentMultiValue != null) { // create a new complex value and add it to the MultiValue complexValue = new ODataComplexValue() { TypeName = payloadElement.FullTypeName, Properties = new List <ODataProperty>() }; // we construct the MultiValue so we know that the items are a list IList itemsAsList = currentMultiValue.Items as IList; itemsAsList.Add(complexValue); } var currentComplex = parent as ODataComplexValue; if (currentComplex != null) { complexValue = currentComplex; } } else { complexValue = new ODataComplexValue() { TypeName = payloadElement.FullTypeName, Properties = new List <ODataProperty>() }; } this.items.Push(complexValue); base.Visit(payloadElement); //if parent exists if (parent != null) { this.items.Pop(); } }
/// <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> /// Reorders payloadElement properties. /// </summary> /// <param name="complexInstance">The payloadElement for which properties need to be reordered.</param> /// <returns>PayloadElement with reordered properties.</returns> private ODataPayloadElement ReorderProperties(ComplexInstance complexInstance) { ComplexInstance instance = (ComplexInstance)ODataPayloadElementDeepCopyingVisitor.DeepCopy(complexInstance); if (instance != null) { ((List <PropertyInstance>)instance.Properties).Reverse(); } return(complexInstance); }
/// <summary> /// Visits the payload element /// </summary> /// <param name="payloadElement">The payload element to visit</param> public override void Visit(ComplexInstance payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); if (this.withinCollection) { payloadElement.FullTypeName = null; } this.withinCollection = false; base.Visit(payloadElement); }
/// <summary> /// Builds a complex type instance of the given type out of the given anonymous object /// </summary> /// <param name="complexType">The metadata type information for the complex type</param> /// <param name="anonymous">The data as an anonymous type</param> /// <returns>An entity instance with the given values</returns> public ComplexInstance ComplexInstance(ComplexType complexType, object anonymous) { ComplexInstance instance = new ComplexInstance(complexType.FullName, anonymous == null); if (anonymous != null) { this.PopulatePropertiesFromObject(instance, complexType.Properties, anonymous); } return(instance); }
/// <summary> /// Visits the payload element /// </summary> /// <param name="payloadElement">The payload element to visit</param> public override void Visit(ComplexInstance payloadElement) { if (payloadElement.IsNull) { // TODO: null or uninitializeddata? this.AddValue((object)null); } else { base.Visit(payloadElement); } }
/// <summary> /// Generates the specified number of similar complex instances /// </summary> /// <param name="random">Random number generator for generating instance property values.</param> /// <param name="currentInstance">Instance to copy.</param> /// <param name="numberOfInstances">Number of similar instances to generate.</param> /// <param name="randomizePropertyValues">If this is false it will copy the instance without changing it otherwise the property values will be randomized.</param> /// <returns>A set of similar instances.</returns> public static IEnumerable<ComplexInstance> GenerateSimilarComplexInstances( IRandomNumberGenerator random, ComplexInstance currentInstance, int numberOfInstances, bool randomizePropertyValues = false) { ExceptionUtilities.CheckArgumentNotNull(random, "random"); ExceptionUtilities.CheckArgumentNotNull(currentInstance, "currentInstance"); ExceptionUtilities.CheckArgumentNotNull(numberOfInstances, "numberOfInstance"); return Enumerable.Range(0, numberOfInstances).Select(x => GenerateSimilarComplexInstance(random, currentInstance)); }
/// <summary> /// Visits the payload element /// </summary> /// <param name="payloadElement">The payload element to visit</param> public override void Visit(ComplexInstance payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); if (this.withinCollection) { var annotation = payloadElement.Annotations.Where(a => a is SerializationTypeNameTestAnnotation).SingleOrDefault(); payloadElement.Annotations.Remove(annotation); } this.withinCollection = false; base.Visit(payloadElement); }
/// <summary> /// Converts the complex instance into an entity instance based on the metadata /// </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(ComplexInstance payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); if (payloadElement.Annotations.OfType<EntitySetAnnotation>().Any()) { var entityInstance = new EntityInstance(payloadElement.FullTypeName, payloadElement.IsNull); entityInstance.Properties = this.VisitCollection(payloadElement.Properties); return payloadElement.ReplaceWith(entityInstance); } return base.Visit(payloadElement); }
/// <summary> /// Visits a complex instance, clears its type name, and sorts/normalizes its properties /// </summary> /// <param name="payloadElement">The complex instance</param> public override void Visit(ComplexInstance payloadElement) { base.Visit(payloadElement); payloadElement.FullTypeName = null; if (this.contextData.ResolveName != null && !payloadElement.IsNull) { payloadElement.FullTypeName = this.contextData.ResolveName(this.typeStack.Peek()); } this.SortAndNormalizeProperties(payloadElement); }
/// <summary> /// Converts the complex instance into an entity instance based on the metadata /// </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(ComplexInstance payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); if (payloadElement.Annotations.OfType <EntitySetAnnotation>().Any()) { var entityInstance = new EntityInstance(payloadElement.FullTypeName, payloadElement.IsNull); entityInstance.Properties = this.VisitCollection(payloadElement.Properties); return(payloadElement.ReplaceWith(entityInstance)); } return(base.Visit(payloadElement)); }
/// <summary> /// Generates the specified number of similar complex instances /// </summary> /// <param name="random">Random number generator for generating instance property values.</param> /// <param name="currentInstance">Instance to copy.</param> /// <param name="numberOfInstances">Number of similar instances to generate.</param> /// <param name="randomizePropertyValues">If this is false it will copy the instance without changing it otherwise the property values will be randomized.</param> /// <returns>A set of similar instances.</returns> public static IEnumerable <ComplexInstance> GenerateSimilarComplexInstances( IRandomNumberGenerator random, ComplexInstance currentInstance, int numberOfInstances, bool randomizePropertyValues = false) { ExceptionUtilities.CheckArgumentNotNull(random, "random"); ExceptionUtilities.CheckArgumentNotNull(currentInstance, "currentInstance"); ExceptionUtilities.CheckArgumentNotNull(numberOfInstances, "numberOfInstance"); return(Enumerable.Range(0, numberOfInstances).Select(x => GenerateSimilarComplexInstance(random, currentInstance))); }
/// <summary> /// Visits the payload element /// </summary> /// <param name="payloadElement">The payload element to visit</param> public override void Visit(ComplexInstance payloadElement) { if (!payloadElement.IsNull) { EntityModelTypeAnnotation typeAnnotation = payloadElement.GetAnnotation <EntityModelTypeAnnotation>(); if (payloadElement.FullTypeName == null && typeAnnotation != null) { payloadElement.FullTypeName = ((IEdmComplexTypeReference)typeAnnotation.EdmModelType).FullName(); } } base.Visit(payloadElement); }
/// <summary> /// Visits the payload element /// </summary> /// <param name="payloadElement">The payload element to visit</param> public override void Visit(ComplexInstance payloadElement) { if (!payloadElement.IsNull) { EntityModelTypeAnnotation typeAnnotation = payloadElement.GetAnnotation<EntityModelTypeAnnotation>(); if (payloadElement.FullTypeName == null && typeAnnotation != null) { payloadElement.FullTypeName = ((IEdmComplexTypeReference)typeAnnotation.EdmModelType).FullName(); } } base.Visit(payloadElement); }
/// <summary> /// Visits the payload element /// </summary> /// <param name="payloadElement">The payload element to visit</param> public override void Visit(ComplexInstance payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); var annotation = payloadElement.Annotations.Where(a => a is DataTypeAnnotation).SingleOrDefault(); payloadElement.Annotations.Remove(annotation); foreach (var propertyInstance in payloadElement.Properties) { this.Recurse(propertyInstance); } }
/// <summary> /// Constructs a complex instance with the given property values /// </summary> /// <param name="type">The metadata for the complex type</param> /// <param name="propertyPath">Property Path to the ComplexInstance</param> /// <param name="namedValues">The property values. Keys are expected to be '.' delimited property paths.</param> /// <returns>A complex instance with the given values</returns> private ComplexInstance ComplexInstance(ComplexType type, string propertyPath, IEnumerable <NamedValue> namedValues) { ExceptionUtilities.CheckArgumentNotNull(type, "type"); ComplexInstance instance = new ComplexInstance(type.FullName, namedValues == null); if (namedValues != null) { this.PopulatePropertiesFromPaths(instance, type.Properties, propertyPath, namedValues); } return(instance); }
private static ComplexMultiValue GenerateSimilarComplexMultiValue(IRandomNumberGenerator random, ComplexMultiValue currentInstance) { ComplexMultiValue instance = ((ComplexMultiValue)currentInstance.DeepCopy()); if (instance.Count != 0) { ComplexInstance val = instance.First(); int numItems = random.NextFromRange(1, 3); var newItems = Enumerable.Range(0, numItems).Select(x => GenerateSimilarComplexInstance(random, val)); instance = new ComplexMultiValue(val.FullTypeName, false, newItems.ToArray()); } return(instance); }
/// <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> /// Converts a queryExpression to a payload where applicable, returns null if not required /// </summary> /// <param name="expression">Expression to convert</param> /// <returns>OData Payload</returns> public ODataPayloadElement ComputePayload(QueryExpression expression) { LinqToAstoriaProcedureExpressionLocatorVisitor visitor = new LinqToAstoriaProcedureExpressionLocatorVisitor(); var procedureExpression = visitor.FindProcedure(expression); if (procedureExpression == null) { return(null); } var actionAnnotation = procedureExpression.Function.Annotations.OfType <ServiceOperationAnnotation>().SingleOrDefault(); ExceptionUtilities.CheckObjectNotNull(actionAnnotation, "Should have an action annotation"); ExceptionUtilities.Assert(procedureExpression.Function.IsAction(), "Visitor did not find a procedure"); var nonboundArguments = procedureExpression.GetNonBoundFunctionArgments(); var parameterKeyValues = procedureExpression.Function.ConvertActionArgumentsToTypedValues(actionAnnotation, nonboundArguments); var complexInstance = new ComplexInstance(null, false); foreach (var parameterKeyValuePair in parameterKeyValues) { var parameterPrimitiveValue = parameterKeyValuePair.Value as PrimitiveValue; var primitiveMultiValue = parameterKeyValuePair.Value as PrimitiveMultiValue; var complexMultiValue = parameterKeyValuePair.Value as ComplexMultiValue; if (parameterPrimitiveValue != null) { complexInstance.Add(new PrimitiveProperty(parameterKeyValuePair.Key, parameterPrimitiveValue.FullTypeName, parameterPrimitiveValue.ClrValue)); } else if (primitiveMultiValue != null) { complexInstance.Add(new PrimitiveMultiValueProperty(parameterKeyValuePair.Key, primitiveMultiValue)); } else if (complexMultiValue != null) { complexInstance.Add(new ComplexMultiValueProperty(parameterKeyValuePair.Key, complexMultiValue)); } else { var parameterComplexInstance = parameterKeyValuePair.Value as ComplexInstance; ExceptionUtilities.CheckObjectNotNull(parameterComplexInstance, "Unsupported type"); complexInstance.Add(new ComplexProperty(parameterKeyValuePair.Key, parameterComplexInstance)); } } return(complexInstance); }
/// <summary> /// Converts a queryExpression to a payload where applicable, returns null if not required /// </summary> /// <param name="expression">Expression to convert</param> /// <returns>OData Payload</returns> public ODataPayloadElement ComputePayload(QueryExpression expression) { LinqToAstoriaProcedureExpressionLocatorVisitor visitor = new LinqToAstoriaProcedureExpressionLocatorVisitor(); var procedureExpression = visitor.FindProcedure(expression); if (procedureExpression == null) { return null; } var actionAnnotation = procedureExpression.Function.Annotations.OfType<ServiceOperationAnnotation>().SingleOrDefault(); ExceptionUtilities.CheckObjectNotNull(actionAnnotation, "Should have an action annotation"); ExceptionUtilities.Assert(procedureExpression.Function.IsAction(), "Visitor did not find a procedure"); var nonboundArguments = procedureExpression.GetNonBoundFunctionArgments(); var parameterKeyValues = procedureExpression.Function.ConvertActionArgumentsToTypedValues(actionAnnotation, nonboundArguments); var complexInstance = new ComplexInstance(null, false); foreach (var parameterKeyValuePair in parameterKeyValues) { var parameterPrimitiveValue = parameterKeyValuePair.Value as PrimitiveValue; var primitiveMultiValue = parameterKeyValuePair.Value as PrimitiveMultiValue; var complexMultiValue = parameterKeyValuePair.Value as ComplexMultiValue; if (parameterPrimitiveValue != null) { complexInstance.Add(new PrimitiveProperty(parameterKeyValuePair.Key, parameterPrimitiveValue.FullTypeName, parameterPrimitiveValue.ClrValue)); } else if (primitiveMultiValue != null) { complexInstance.Add(new PrimitiveMultiValueProperty(parameterKeyValuePair.Key, primitiveMultiValue)); } else if (complexMultiValue != null) { complexInstance.Add(new ComplexMultiValueProperty(parameterKeyValuePair.Key, complexMultiValue)); } else { var parameterComplexInstance = parameterKeyValuePair.Value as ComplexInstance; ExceptionUtilities.CheckObjectNotNull(parameterComplexInstance, "Unsupported type"); complexInstance.Add(new ComplexProperty(parameterKeyValuePair.Key, parameterComplexInstance)); } } return complexInstance; }
/// <summary> /// Removes duplicate properties from the specified complex or entity value. /// </summary> /// <param name="payloadElement"></param> private void DeduplicateProperties(ComplexInstance payloadElement) { Dictionary<string, PropertyInstance> properties = new Dictionary<string, PropertyInstance>(); foreach (PropertyInstance propertyInstance in payloadElement.Properties.ToList()) { PropertyInstance firstPropertyInstance; if (properties.TryGetValue(propertyInstance.Name, out firstPropertyInstance)) { payloadElement.Remove(propertyInstance); payloadElement.Replace(firstPropertyInstance, propertyInstance); properties[propertyInstance.Name] = propertyInstance; } else { properties.Add(propertyInstance.Name, propertyInstance); } } }
/// <summary> /// Converts a Payload that contains the action parameters into QueryValues /// </summary> /// <param name="parametersPayload">Parameter Payload</param> /// <param name="action">Function that has the parameters that will be converted to a QueryValue</param> /// <returns>A Lookup of parameter names and QueryValues</returns> public IDictionary<string, QueryValue> Convert(ComplexInstance parametersPayload, Function action) { var parametersLookup = new Dictionary<string, QueryValue>(); foreach (var property in parametersPayload.Properties) { var functionParameter = action.Parameters.Single(p => p.Name == property.Name); var functionParameterQueryType = this.QueryTypeLibrary.GetDefaultQueryType(functionParameter.DataType); QueryValue parameterValue = null; if (property.ElementType == ODataPayloadElementType.ComplexMultiValueProperty) { var complexMultValueProperty = property as ComplexMultiValueProperty; parameterValue = this.PayloadElementToQueryValueConverter.Convert(complexMultValueProperty.Value, functionParameterQueryType); } else if (property.ElementType == ODataPayloadElementType.ComplexProperty) { var complexProperty = property as ComplexProperty; parameterValue = this.PayloadElementToQueryValueConverter.Convert(complexProperty.Value, functionParameterQueryType); } else if (property.ElementType == ODataPayloadElementType.PrimitiveMultiValueProperty) { var derivedProperty = property as PrimitiveMultiValueProperty; parameterValue = this.PayloadElementToQueryValueConverter.Convert(derivedProperty.Value, functionParameterQueryType); } else if (property.ElementType == ODataPayloadElementType.PrimitiveProperty) { var derivedProperty = property as PrimitiveProperty; parameterValue = this.PayloadElementToQueryValueConverter.Convert(derivedProperty.Value, functionParameterQueryType); } ExceptionUtilities.CheckObjectNotNull(parameterValue, "Cannot convert to query value parameter for Action that is of type {0} and has a payload like {1}", property.ElementType, property); parametersLookup.Add(property.Name, parameterValue); } return parametersLookup; }
private void PopulatePrimitiveBagPropertyFromPaths(ComplexInstance instance, MemberProperty memberProperty, string propertyPath, IEnumerable<NamedValue> namedValues, PrimitiveDataType primitiveElementDataType) { int i = 0; bool completed = false; var primitiveCollection = new PrimitiveMultiValue(primitiveElementDataType.BuildMultiValueTypeName(), false); while (!completed) { IEnumerable<NamedValue> primitiveItemNamedValues = namedValues.Where(pp => pp.Name == propertyPath + "." + i).ToList(); if (primitiveItemNamedValues.Count() == 0) { completed = true; } else { ExceptionUtilities.Assert(primitiveItemNamedValues.Count() < 2, "Should not get more than one value for a primitive Bag item for path '{0}'", propertyPath + "." + i); var value = primitiveItemNamedValues.Single(); // Do something with the value primitiveCollection.Add(PrimitiveValue(primitiveElementDataType, value.Value)); } i++; } if (i > 1) { instance.Add(new PrimitiveMultiValueProperty(memberProperty.Name, primitiveCollection)); } }
/// <summary> /// Creates a new complex value. If the complex instance is part of a complex collection value /// adds the complex value to MultiValue property's items collection; otherwise sets the complex value as /// value of a complex property. /// </summary> /// <param name="payloadElement"></param> public override void Visit(ComplexInstance payloadElement) { // figure out whether the complex value is part of a collection property (of complex values) or // the value for a complex property ODataProperty currentProperty = this.currentProperties.Last(); ODataCollectionValue currentMultiValue = currentProperty.Value as ODataCollectionValue; ODataComplexValue complexValue; if (currentMultiValue != null) { // create a new complex value and add it to the MultiValue complexValue = new ODataComplexValue(); complexValue.TypeName = payloadElement.FullTypeName.Substring(11, payloadElement.FullTypeName.Length - 12); ; // we construct the MultiValue so we know that the items are a list IList itemsAsList = currentMultiValue.Items as IList; itemsAsList.Add(complexValue); } else { complexValue = (ODataComplexValue)currentProperty.Value; complexValue.TypeName = payloadElement.FullTypeName; } var previousProperties = this.currentProperties; this.currentProperties = new List<ODataProperty>(); base.Visit(payloadElement); complexValue.Properties = this.currentProperties; this.currentProperties = previousProperties; }
private void VisitMemberProperties(ComplexInstance payloadElement, IEnumerable<MemberProperty> properties) { foreach (var propertyInstance in payloadElement.Properties) { var nextProperty = properties.SingleOrDefault(p => p.Name == propertyInstance.Name); if (nextProperty != null) { try { this.MetadataStack.Push(nextProperty); this.Recurse(propertyInstance); } finally { this.MetadataStack.Pop(); } } } }
internal static void FixupAddingResultWrappers(string actionContentType, ComplexInstance procedurePayload) { if (actionContentType.Contains("odata.metadata=verbose")) { // Fixup to ensure payload is as expected for actions foreach (var primitiveMultiValueProperty in procedurePayload.Properties.OfType<PrimitiveMultiValueProperty>()) { primitiveMultiValueProperty.Value.Annotations.Add(new JsonCollectionResultWrapperAnnotation(false)); primitiveMultiValueProperty.Value.FullTypeName = null; } foreach (var complexMultiValueProperty in procedurePayload.Properties.OfType<ComplexMultiValueProperty>()) { complexMultiValueProperty.Value.Annotations.Add(new JsonCollectionResultWrapperAnnotation(false)); complexMultiValueProperty.Value.FullTypeName = null; } } }
/// <summary> /// Creates a new complex value. If the complex instance is part of a complex collection value /// adds the complex value to MultiValue property's items collection; otherwise sets the complex value as /// value of a complex property. /// </summary> /// <param name="payloadElement"></param> public override void Visit(ComplexInstance payloadElement) { // figure out whether the complex value is part of a collection property (of complex values), // the value for a complex property, or top level object parent = null; if (this.items.Any()) { parent = this.items.Peek(); } ODataComplexValue complexValue = null; if (parent != null) { var currentMultiValue = parent as ODataCollectionValue; if (currentMultiValue != null) { // create a new complex value and add it to the MultiValue complexValue = new ODataComplexValue() { TypeName = payloadElement.FullTypeName, Properties = new List<ODataProperty>() }; // we construct the MultiValue so we know that the items are a list IList itemsAsList = currentMultiValue.Items as IList; itemsAsList.Add(complexValue); } var currentComplex = parent as ODataComplexValue; if (currentComplex != null) { complexValue = currentComplex; } } else { complexValue = new ODataComplexValue() { TypeName = payloadElement.FullTypeName, Properties = new List<ODataProperty>() }; } this.items.Push(complexValue); base.Visit(payloadElement); //if parent exists if (parent != null) { this.items.Pop(); } }
private static ODataPayloadElement CreatePayloadElement(IEdmModel model, ODataPayloadKind payloadKind, ReaderTestConfiguration testConfig) { IEdmEntitySet citySet = model.EntityContainer.FindEntitySet("Cities"); IEdmEntityType cityType = model.EntityTypes().Single(e => e.Name == "CityType"); IEdmProperty cityNameProperty = cityType.Properties().Single(e => e.Name == "Name"); IEdmNavigationProperty policeStationNavProp = cityType.NavigationProperties().Single(e => e.Name == "PoliceStation"); IEdmOperationImport primitiveCollectionResultOperation = model.EntityContainer.FindOperationImports("PrimitiveCollectionResultOperation").Single(); IEdmOperationImport serviceOp1 = model.EntityContainer.FindOperationImports("ServiceOperation1").Single(); bool isRequest = testConfig.IsRequest; bool isJsonLightRequest = isRequest && testConfig.Format == ODataFormat.Json; switch (payloadKind) { case ODataPayloadKind.Feed: { return PayloadBuilder.EntitySet().WithTypeAnnotation(cityType).ExpectedEntityType(cityType, citySet); } case ODataPayloadKind.Entry: { return PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).WithTypeAnnotation(cityType).ExpectedEntityType(cityType, citySet); } case ODataPayloadKind.Property: return PayloadBuilder.PrimitiveProperty(isJsonLightRequest ? string.Empty : null, "SomeCityValue").ExpectedProperty(cityType, "Name"); case ODataPayloadKind.EntityReferenceLink: return PayloadBuilder.DeferredLink("http://odata.org/entityreferencelink").ExpectedNavigationProperty(citySet, cityType, "PoliceStation"); case ODataPayloadKind.EntityReferenceLinks: return PayloadBuilder.LinkCollection().Item(PayloadBuilder.DeferredLink("http://odata.org/entityreferencelink")).ExpectedNavigationProperty((EdmEntitySet)citySet, (EdmEntityType)cityType, "CityHall"); case ODataPayloadKind.Value: return PayloadBuilder.PrimitiveValue("PrimitiveValue"); case ODataPayloadKind.BinaryValue: return PayloadBuilder.PrimitiveValue(new byte[] { 0, 0, 1, 1 }); case ODataPayloadKind.Collection: return PayloadBuilder.PrimitiveCollection().CollectionName(null).ExpectedFunctionImport((EdmOperationImport)primitiveCollectionResultOperation); case ODataPayloadKind.ServiceDocument: Debug.Assert(!isRequest, "Not supported in requests."); return new ServiceDocumentInstance().Workspace(PayloadBuilder.Workspace()); case ODataPayloadKind.MetadataDocument: Debug.Assert(!isRequest, "Not supported in requests."); throw new NotImplementedException(); case ODataPayloadKind.Error: Debug.Assert(!isRequest, "Not supported in requests."); return PayloadBuilder.Error("ErrorCode"); case ODataPayloadKind.Parameter: // build parameter payload based on model definition var parameterPayload = new ComplexInstance(null, false); ODataPayloadElement a = PayloadBuilder.PrimitiveValue(123).WithTypeAnnotation(EdmCoreModel.Instance.GetInt32(false)); ODataPayloadElement b = PayloadBuilder.PrimitiveValue("stringvalue").WithTypeAnnotation(EdmCoreModel.Instance.GetString(false)); PrimitiveProperty parametera = new PrimitiveProperty("a", "Edm.Integer", ((PrimitiveValue)a).ClrValue); PrimitiveProperty parameterb = new PrimitiveProperty("b", "Edm.String", ((PrimitiveValue)b).ClrValue); parameterPayload.Add(parametera); parameterPayload.Add(parameterb); parameterPayload.ExpectedFunctionImport((EdmOperationImport)serviceOp1); return parameterPayload; case ODataPayloadKind.Unsupported: // fall through default: throw new NotSupportedException(); } }
/// <summary> /// Visits the payload element and annotates it with metadata /// </summary> /// <param name="payloadElement">The payload element to visit</param> public override void Visit(ComplexInstance payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); this.VisitComplexOrEntityInstance(payloadElement); }
/// <summary> /// Visits a payload element whose root is a ComplexInstance. /// </summary> /// <param name="payloadElement">The root node of payload element being visited.</param> public void Visit(ComplexInstance payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); var current = this.expectedValueStack.Peek(); var value = current as QueryStructuralValue; ExceptionUtilities.CheckObjectNotNull(value, "Value was not a structural instance. Value was: '{0}'", current.ToString()); this.VisitStructuralInstance(payloadElement, value); }
private static void SetToNull(ComplexInstance complexInstance, string propertyName) { PropertyInstance nullProperty = PayloadBuilder.PrimitiveProperty(propertyName, null); complexInstance.Properties = complexInstance.Properties.ToList().Select(p => p.Name == propertyName ? nullProperty : p); }
/// <summary> /// Deserialize the element as a complex instance /// </summary> /// <param name="element">The xml representing a complex instance</param> /// <returns>The deserialized complex instance</returns> private ComplexInstance DeserializeComplexInstance(XElement element) { ComplexInstance instance = new ComplexInstance(); // get the type XAttribute type = element.Attribute(MetadataType); if (type != null) { instance.FullTypeName = type.Value; } // check for the null attribute XAttribute isNull = element.Attribute(MetadataNull); if (isNull != null) { instance.IsNull = bool.Parse(isNull.Value); } else if (element.HasElements) { instance.IsNull = false; } // get the properties foreach (XElement subElement in element.Elements()) { instance.Add(this.DeserializeProperty(subElement)); } return instance; }
private void VisitStructuralInstance(ComplexInstance payloadElement, QueryStructuralValue value) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); ExceptionUtilities.CheckArgumentNotNull(value, "value"); var entityType = value.Type as QueryEntityType; var complexType = value.Type as QueryComplexType; ExceptionUtilities.Assert(entityType != null || complexType != null, "Value was neither an entity type nor a complex type"); bool isEntity = entityType != null; string errorType = isEntity ? "Entity" : "Complex"; if (value.IsNull) { this.parent.Assert.IsTrue(payloadElement.IsNull, errorType + " instance unexpectedly non-null"); return; } else { this.parent.Assert.IsFalse(payloadElement.IsNull, errorType + " instance unexpectedly null"); this.VerifyTypeName(value, payloadElement.FullTypeName, errorType + " instance type name did not match expectation."); } // get all the payload properties, and remove them as we go to detect any extras var payloadProperties = payloadElement.Properties.ToList(); // this is data-driven to deal with open types, but we need to skip over the 'default stream' property if it exists foreach (var propertyName in value.MemberNames.Where(m => m != AstoriaQueryStreamType.DefaultStreamPropertyName)) { var propertyInstance = payloadProperties.SingleOrDefault(p => p.Name == propertyName); this.parent.Assert.IsNotNull(propertyInstance, string.Format(CultureInfo.InvariantCulture, "Could not find property '{0}' in payload", propertyName)); payloadProperties.Remove(propertyInstance); var propertyValue = value.GetValue(propertyName); this.RecurseWithMessage(propertyInstance, propertyValue, "{0} instance did not match expectation", errorType); } string extraPropertyNames = string.Join(", ", payloadProperties.Select(p => '\'' + p.Name + '\'').ToArray()); this.parent.Assert.IsTrue(payloadProperties.Count == 0, string.Format(CultureInfo.InvariantCulture, "{0} instance contained unexpected properties: {1}", errorType, extraPropertyNames)); }
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); } }
private void PopulatePropertiesFromPaths(ComplexInstance instance, IEnumerable<MemberProperty> properties, string propertyPath, IEnumerable<NamedValue> namedValues) { ExceptionUtilities.CheckArgumentNotNull(instance, "instance"); ExceptionUtilities.CheckArgumentNotNull(properties, "properties"); ExceptionUtilities.CheckArgumentNotNull(namedValues, "namedValues"); foreach (MemberProperty property in properties) { string childPropertyPath = property.Name; if (propertyPath != null) { childPropertyPath = propertyPath + "." + property.Name; } CollectionDataType collectionDataType = property.PropertyType as CollectionDataType; PrimitiveDataType primitiveDataType = property.PropertyType as PrimitiveDataType; if (primitiveDataType != null) { NamedValue memberPropertyNamedValue = namedValues.SingleOrDefault(nv => nv.Name == childPropertyPath); if (memberPropertyNamedValue != null) { instance.Add(this.PrimitiveProperty(property, memberPropertyNamedValue.Value)); } } else if (collectionDataType != null) { IEnumerable<NamedValue> bagNamedValues = namedValues.Where(nv => nv.Name.StartsWith(childPropertyPath + ".", StringComparison.Ordinal)).ToList(); if (bagNamedValues.Count() > 0) { this.PopulateMultiValuePropertyFromPaths(instance, property, collectionDataType.ElementDataType, childPropertyPath, bagNamedValues); } else { this.PopulateCollectionPropertyWithNullOrEmpty(instance, property, childPropertyPath, namedValues); } } else { var complexDataType = property.PropertyType as ComplexDataType; ExceptionUtilities.CheckObjectNotNull(complexDataType, "Property '{0}' was not primitive, a collection, or complex", property.Name); IEnumerable<NamedValue> complexInstanceNamedValues = namedValues.Where(nv => nv.Name.StartsWith(childPropertyPath + ".", StringComparison.Ordinal)).ToList(); if (complexInstanceNamedValues.Count() > 0) { PropertyInstance memberPropertyInstance = this.ComplexProperty(property, childPropertyPath, complexInstanceNamedValues); instance.Add(memberPropertyInstance); } else { // Check for null case IEnumerable<NamedValue> exactMatches = namedValues.Where(nv => nv.Name == childPropertyPath).ToList(); ExceptionUtilities.Assert(exactMatches.Count() < 2, "Should only find at most one property path {0} when looking for null value", childPropertyPath); if (exactMatches.Count() == 1) { instance.Add(new ComplexProperty(property.Name, new ComplexInstance(complexDataType.Definition.FullName, true))); } } } } }
private void PopulateCollectionPropertyWithNullOrEmpty(ComplexInstance instance, MemberProperty memberProperty, string propertyPath, IEnumerable<NamedValue> namedValues) { IEnumerable<NamedValue> exactMatches = namedValues.Where(nv => nv.Name == propertyPath).ToList(); ExceptionUtilities.Assert(exactMatches.Count() < 2, "Should only find at most one property path {0} when looking for null value", propertyPath); if (exactMatches.Count() == 1) { instance.Add(this.MultiValuePropertyEmptyOrNull(memberProperty, exactMatches.Single().Value)); } }
private void VisitComplexOrEntityInstance(ComplexInstance payloadElement) { var entitySet = this.MetadataStack.Peek() as EntitySet; if (entitySet != null) { payloadElement.AddAnnotationIfNotExist(new EntitySetAnnotation() { EntitySet = entitySet }); // start with the entity type from the set var entityType = entitySet.EntityType; // if the payload has a type name in it, and its different from the entity type on the set... if (payloadElement.FullTypeName != null && payloadElement.FullTypeName != entityType.FullName) { // ... then go find the more specific type in the model and use that instead (if it exists) var specificEntityType = entitySet.Container.Model.EntityTypes.SingleOrDefault(t => t.IsKindOf(entityType) && t.FullName == payloadElement.FullTypeName); if (specificEntityType != null) { entityType = specificEntityType; } } if (entityType != null) { payloadElement.AddAnnotationIfNotExist(new DataTypeAnnotation() { DataType = DataTypes.EntityType.WithDefinition(entityType) }); this.VisitMemberProperties(payloadElement, entityType.AllProperties); this.VisitNavigationProperties(payloadElement.Properties, entityType.AllNavigationProperties); } } else { var dataType = this.MetadataStack.Peek() as ComplexDataType; ExceptionUtilities.CheckObjectNotNull(dataType, "Expected complex data type, got '{0}'", this.MetadataStack.Peek()); payloadElement.AddAnnotationIfNotExist(new DataTypeAnnotation() { DataType = dataType }); this.VisitMemberProperties(payloadElement, dataType.Definition.Properties); } }
/// <summary> /// Converts a LinqNewExpression to a Complex Instance /// </summary> /// <param name="expression">Expression to convert to a ComplexInstance</param> /// <returns>Complex Instance</returns> internal static ComplexInstance ConvertToComplexInstance(this QueryExpression expression) { var nullConstantExpression = expression as QueryNullExpression; var queryComplexType = (QueryComplexType)expression.ExpressionType; if (nullConstantExpression != null) { return new ComplexInstance(queryComplexType.ComplexType.FullName, true); } var structuralExpression = expression as LinqNewInstanceExpression; var newComplexInstance = new ComplexInstance(queryComplexType.ComplexType.FullName, false); ExceptionUtilities.Assert(structuralExpression.MemberNames.Count == structuralExpression.Members.Count, "MemberNames and Members count are not equal"); for (int i = 0; i < structuralExpression.MemberNames.Count; i++) { string memberName = structuralExpression.MemberNames[i]; var memberExpression = structuralExpression.Members[i]; var memberProperty = queryComplexType.ComplexType.Properties.Single(p => p.Name == memberName); var complexDataType = memberProperty.PropertyType as ComplexDataType; var collectionDataType = memberProperty.PropertyType as CollectionDataType; if (complexDataType != null) { var childComplexInstance = memberExpression.ConvertToComplexInstance(); var complexProperty = new ComplexProperty() { Name = memberName, Value = childComplexInstance }; newComplexInstance.Add(complexProperty); } else if (collectionDataType != null) { var collectionPropertyType = memberProperty.PropertyType as CollectionDataType; var convertedValue = memberExpression.ConvertToMultiValue(collectionPropertyType.ElementDataType); if (collectionPropertyType.ElementDataType is ComplexDataType) { newComplexInstance.Add(new ComplexMultiValueProperty(memberName, convertedValue as ComplexMultiValue)); } else { var primitiveDataType = collectionPropertyType.ElementDataType as PrimitiveDataType; ExceptionUtilities.CheckObjectNotNull(primitiveDataType, "Not a primitiveDataType '{0}'", collectionPropertyType.ElementDataType); newComplexInstance.Add(new PrimitiveMultiValueProperty(memberName, convertedValue as PrimitiveMultiValue)); } } else { var primitiveDataType = memberProperty.PropertyType as PrimitiveDataType; ExceptionUtilities.CheckObjectNotNull(primitiveDataType, "Expected a PrimitiveDataType"); var primitiveValue = memberExpression.ConvertToPrimitiveValue(primitiveDataType); newComplexInstance.Add(new PrimitiveProperty(memberName, primitiveDataType.GetEdmTypeName(), primitiveValue.ClrValue)); } } return newComplexInstance; }