/// <summary>
        /// Helper method for visiting collections
        /// </summary>
        /// <param name="payloadElement">The collection to visit</param>
        protected override void VisitCollection(ODataPayloadElementCollection payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
            var enumerable = payloadElement as IEnumerable;

            if (enumerable != null)
            {
                var elements = enumerable.Cast <ODataPayloadElement>().ToList();
                if (elements.Count == 0)
                {
                    this.AddValue(EmptyData.Value);
                }
                else
                {
                    for (int i = 0; i < elements.Count; i++)
                    {
                        using (new DelegateBasedDisposable(() => this.currentPath.Pop()))
                        {
                            this.currentPath.Push(i.ToString(CultureInfo.InvariantCulture));
                            this.Recurse(elements[i]);
                        }
                    }
                }
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Helper method for visiting collections
        /// </summary>
        /// <param name="payloadElement">The collection to visit</param>
        protected override void VisitCollection(ODataPayloadElementCollection payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
            var dataType = this.MetadataStack.Peek() as CollectionDataType;

            if (dataType != null)
            {
                ExceptionUtilities.CheckObjectNotNull(dataType, "Expected collection data type, got '{0}'", this.MetadataStack.Peek());
                payloadElement.AddAnnotationIfNotExist(new DataTypeAnnotation()
                {
                    DataType = dataType
                });

                try
                {
                    this.MetadataStack.Push(dataType.ElementDataType);
                    base.VisitCollection(payloadElement);
                }
                finally
                {
                    this.MetadataStack.Pop();
                }
            }
            else
            {
                var entitySet = this.MetadataStack.Peek() as EntitySet;
                ExceptionUtilities.CheckObjectNotNull(entitySet, "Expected entity set, got '{0}'", this.MetadataStack.Peek());
                payloadElement.Add(new EntitySetAnnotation()
                {
                    EntitySet = entitySet
                });
                base.VisitCollection(payloadElement);
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Normalizes complex properties, potentially replacing them with collections if the metadata indicates the payload is from a service operation
        /// </summary>
        /// <param name="payloadElement">The payload element to potentially replace</param>
        /// <returns>The original element or a copy to replace it with</returns>
        public override ODataPayloadElement Visit(ComplexProperty payloadElement)
        {
            var replaced = base.Visit(payloadElement);

            if (replaced.ElementType == ODataPayloadElementType.ComplexProperty)
            {
                payloadElement = (ComplexProperty)replaced;

                // if the payload looks like
                //   <Foo>
                //     <element m:type="Edm.Int32">3</element>
                //   </Foo>
                // or
                //   <Foo>
                //     <element m:type="Complex">
                //       <Bar>3</Bar>
                //     </element>
                //   </Foo>
                // then it may be deserialized as a complex instance with exactly 1 property, when it should be a collection of size 1
                //
                if (this.ShouldReplaceWithCollection(payloadElement, payloadElement.Value.IsNull, payloadElement.Value.FullTypeName))
                {
                    // only replace if there is exactly 1 property
                    if (payloadElement.Value.Properties.Count() == 1)
                    {
                        // get the single property and check to see if its name is 'element'
                        var property = payloadElement.Value.Properties.Single();
                        if (property.Name == ODataConstants.CollectionItemElementName)
                        {
                            // determine whether it is a primitive or complex value based on the kind of property
                            ODataPayloadElementCollection collection = null;
                            if (property.ElementType == ODataPayloadElementType.PrimitiveProperty)
                            {
                                var primitiveProperty = (PrimitiveProperty)property;
                                collection = new PrimitiveCollection(primitiveProperty.Value);
                            }
                            else if (property.ElementType == ODataPayloadElementType.ComplexProperty)
                            {
                                var complexProperty = (ComplexProperty)property;
                                collection = new ComplexInstanceCollection(complexProperty.Value);
                            }

                            // if it was primitive or complex, replace it
                            if (collection != null)
                            {
                                return(payloadElement
                                       .ReplaceWith(collection)
                                       .WithAnnotations(new CollectionNameAnnotation()
                                {
                                    Name = payloadElement.Name
                                }));
                            }
                        }
                    }
                }
            }

            return(replaced);
        }
Esempio n. 4
0
            /// <summary>
            /// Visits a property item.
            /// </summary>
            /// <param name="property">The property to visit.</param>
            protected override ODataPayloadElement VisitProperty(ODataProperty property)
            {
                ExceptionUtilities.CheckArgumentNotNull(property, "property");

                object value = property.Value;

                if (value == null)
                {
                    return(new PrimitiveProperty()
                    {
                        Name = property.Name, Value = new PrimitiveValue(null, null)
                    });
                }
                else
                {
                    ODataComplexValue complexValue = value as ODataComplexValue;
                    if (complexValue != null)
                    {
                        return(new ComplexProperty(property.Name, (ComplexInstance)this.Visit(complexValue)));
                    }
                    else
                    {
                        ODataCollectionValue collectionValue = value as ODataCollectionValue;
                        if (collectionValue != null)
                        {
                            ODataPayloadElementCollection collection        = (ODataPayloadElementCollection)this.Visit(collectionValue);
                            ComplexMultiValue             complexCollection = collection as ComplexMultiValue;
                            if (complexCollection != null)
                            {
                                return(new ComplexMultiValueProperty(property.Name, complexCollection));
                            }
                            else
                            {
                                return(new PrimitiveMultiValueProperty(property.Name, (PrimitiveMultiValue)collection));
                            }
                        }
                        else
                        {
                            ODataStreamReferenceValue streamReferenceValue = value as ODataStreamReferenceValue;
                            if (streamReferenceValue != null)
                            {
                                NamedStreamInstance namedStream = (NamedStreamInstance)this.Visit(streamReferenceValue);
                                namedStream.Name = property.Name;
                                return(namedStream);
                            }
                            else
                            {
                                return(new PrimitiveProperty()
                                {
                                    Name = property.Name, Value = (PrimitiveValue)this.Visit(value)
                                });
                            }
                        }
                    }
                }
            }
Esempio n. 5
0
        /// <summary>
        /// Helper method for visiting collections
        /// </summary>
        /// <param name="payloadElement">The collection to visit</param>
        protected virtual void VisitCollection(ODataPayloadElementCollection payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");

            var enumerable = payloadElement as IEnumerable;

            if (enumerable != null)
            {
                this.VisitEnumerable(enumerable.Cast <ODataPayloadElement>());
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Helper method for visiting collections
        /// </summary>
        /// <param name="payloadElement">The collection to visit</param>
        protected override void VisitCollection(ODataPayloadElementCollection payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");

            var enumerable = payloadElement as IEnumerable;

            if (enumerable != null)
            {
                foreach (var element in enumerable.Cast <ODataPayloadElement>())
                {
                    this.withinCollection = true;
                    this.Recurse(element);
                }
            }
            this.withinCollection = false;
        }
        private void SerializeTypedValueCollection <T>(ODataPayloadElementCollection <T> payloadElement) where T : TypedValue
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
            ExceptionUtilities.CheckObjectNotNull(this.currentXElement, "Current XElement is not defined");

            var collectionNameAnnotation = payloadElement.Annotations.OfType <CollectionNameAnnotation>().SingleOrDefault();

            XElement collectionElement = (collectionNameAnnotation == null || collectionNameAnnotation.Name == null) ? CreateMetadataElement(this.currentXElement, AtomValueElement) : CreateDataServicesElement(this.currentXElement, collectionNameAnnotation.Name);

            foreach (var typedValue in payloadElement)
            {
                XElement valueElement = CreateMetadataElement(collectionElement, "element");
                this.VisitPayloadElement(typedValue, valueElement);
            }

            PostProcessXElement(payloadElement, collectionElement);
        }
        private void AddExpectedFunctionImportToCollection(ODataPayloadElementCollection collection)
        {
            var expectedTypeAnnotation = collection.GetAnnotation <ExpectedTypeODataPayloadElementAnnotation>();

            if (expectedTypeAnnotation == null)
            {
                expectedTypeAnnotation = new ExpectedTypeODataPayloadElementAnnotation();
                collection.Add(expectedTypeAnnotation);
            }

            if (expectedTypeAnnotation.ProductFunctionImport == null)
            {
                var typeAnnotation = collection.GetAnnotation <EntityModelTypeAnnotation>();
                var collectionType = typeAnnotation.EdmModelType;

                if (this.testDescriptor.PayloadEdmModel != null)
                {
                    EdmModel           model     = this.testDescriptor.PayloadEdmModel as EdmModel;
                    EdmEntityContainer container = model.EntityContainer as EdmEntityContainer;
                    var functionImport           = container.OperationImports().FirstOrDefault(f =>
                                                                                               { return(f.Operation.ReturnType != null && f.Operation.ReturnType == collectionType); });
                    if (functionImport == null)
                    {
                        functionImport = container.OperationImports().FirstOrDefault(f =>
                                                                                     { return(f.Operation.ReturnType != null && f.Operation.ReturnType.IsCollection()); });

                        if (functionImport == null)
                        {
                            var collectionNameAnnotation = collection.GetAnnotation <CollectionNameAnnotation>();
                            container.AddFunctionAndFunctionImport(model, collectionNameAnnotation == null ? "NewFunctionImport" : collectionNameAnnotation.Name,
                                                                   collectionType);
                            this.testDescriptor.ResetCachedModel();
                        }
                    }

                    expectedTypeAnnotation.ProductFunctionImport = functionImport as EdmOperationImport;
                }
            }
        }
 /// <summary>
 /// Helper method for visiting collections
 /// </summary>
 /// <param name="payloadElement">The collection to visit</param>
 protected override void VisitCollection(ODataPayloadElementCollection payloadElement)
 {
     ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
     this.IncreaseVersionIfTrue(payloadElement.Annotations.OfType <JsonCollectionResultWrapperAnnotation>().Any(a => a.Value), DataServiceProtocolVersion.V4);
     base.VisitCollection(payloadElement);
 }
Esempio n. 10
0
        private bool TryGetCollectionType(JsonObject jsonObject, out ODataPayloadElement elem)
        {
            string typeName = this.GetMetadataPropertyValue(jsonObject, TypeFieldName);

            elem = null;

            // if this object has a property with.Name "results" and it is of type "JsonArray"
            // Example:
            //    "results": [
            //      { ... },
            //      { ... }
            //     ]
            // if it is EntitySet or ComplexCollection
            // EntitySets have "_Count" and "_Next". So process it before retrning.
            if (jsonObject.Properties.Any(prop => prop.Name == ResultsFieldName) &&
                jsonObject.Properties.Where(prop => prop.Name == ResultsFieldName).Single().Value.JsonType == JsonValueType.JsonArray)
            {
                string nextLink   = this.GetNextLink(jsonObject);
                string countField = this.GetInlineCount(jsonObject);

                ODataPayloadElementCollection coll = this.ConvertArray((JsonArray)jsonObject.Properties.Where(p => p.Name == ResultsFieldName).Single().Value, true);

                if (coll.ElementType == ODataPayloadElementType.EntitySetInstance)
                {
                    EntitySetInstance entitySet = coll as EntitySetInstance;
                    entitySet.NextLink = nextLink;
                    if (countField == null)
                    {
                        entitySet.InlineCount = null;
                    }
                    else
                    {
                        entitySet.InlineCount = Convert.ToInt64(countField, CultureInfo.InvariantCulture);
                    }

                    elem = coll;
                }
                else if (coll.ElementType == ODataPayloadElementType.LinkCollection)
                {
                    LinkCollection linkCollection = (LinkCollection)coll;
                    linkCollection.InlineCount = Convert.ToInt64(countField, CultureInfo.InvariantCulture);
                    linkCollection.NextLink    = nextLink;
                    elem = coll;
                }
                else if (coll.ElementType == ODataPayloadElementType.PrimitiveCollection)
                {
                    if (typeName != null)
                    {
                        PrimitiveMultiValue primitiveMultiValue = new PrimitiveMultiValue(typeName, false, ((PrimitiveCollection)coll).ToArray());
                        elem = primitiveMultiValue;
                    }
                    else
                    {
                        elem = coll;
                    }
                }
                else if (coll.ElementType == ODataPayloadElementType.ComplexInstanceCollection)
                {
                    if (typeName != null)
                    {
                        ComplexMultiValue complexMultiValue = new ComplexMultiValue(typeName, false, ((ComplexInstanceCollection)coll).ToArray());
                        elem = complexMultiValue;
                    }
                    else
                    {
                        elem = coll;
                    }
                }
                else
                {
                    ExceptionUtilities.Assert(coll.ElementType == ODataPayloadElementType.EmptyUntypedCollection, "Collection type unhandled: {0}", coll.ElementType);
                    string elementTypeName;
                    if (ODataUtilities.TryGetMultiValueElementTypeName(typeName, out elementTypeName))
                    {
                        ExceptionUtilities.CheckObjectNotNull(this.PrimitiveDataTypeConverter, "Cannot infer clr type from edm type without converter");

                        if (this.PrimitiveDataTypeConverter.ToClrType(elementTypeName) != null)
                        {
                            elem = new PrimitiveMultiValue(typeName, false);
                        }
                        else
                        {
                            elem = new ComplexMultiValue(typeName, false);
                        }
                    }
                    else
                    {
                        EmptyUntypedCollection emptyCollection = (EmptyUntypedCollection)coll;
                        if (countField != null)
                        {
                            emptyCollection.InlineCount = long.Parse(countField, CultureInfo.InvariantCulture);
                        }

                        if (nextLink != null)
                        {
                            emptyCollection.NextLink = nextLink;
                        }

                        elem = emptyCollection;
                    }
                }

                return(true);
            }

            return(false);
        }
 private void CompareCollection <TElement>(ODataPayloadElementCollection <TElement> expected, ODataPayloadElementCollection <TElement> actual) where TElement : ODataPayloadElement
 {
     this.CompareAnnotations(expected.Annotations, actual.Annotations);
     this.CompareList <TElement>(expected, actual);
 }