/// <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);
        }
Exemple #4
0
        /// <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));
            }
        }
Exemple #8
0
        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));
                }
            }
        }
Exemple #10
0
            /// <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);
        }
Exemple #12
0
        /// <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>
        /// 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));
            }
        }
Exemple #17
0
        /// <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();
            }
        }
Exemple #18
0
        /// <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);
        }
Exemple #21
0
        /// <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));
        }
Exemple #25
0
        /// <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)
        {
            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);
        }
Exemple #31
0
        /// <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);
        }
Exemple #33
0
        /// <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);
        }
Exemple #36
0
            /// <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>
            /// 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);
                }
            }
            /// <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>
        /// 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));
            }
            /// <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();
                }
            }
        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;
        }
        /// <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);
            }
        }