コード例 #1
0
        private static ComplexInstanceCollection GetComplexInstanceCollection(IRandomNumberGenerator random, EdmModel model = null, ODataVersion version = ODataVersion.V4)
        {
            var complex      = GetComplexInstance(random, model, version);
            int numinstances = random.ChooseFrom(new[] { 0, 1, 3 });
            var payload      = new ComplexInstanceCollection(GenerateSimilarComplexInstances(random, complex, numinstances).ToArray());

            if (model != null)
            {
                var container      = model.EntityContainersAcrossModels().Single() as EdmEntityContainer;
                var collectionType = new EdmCollectionType((model.FindDeclaredType(complex.FullTypeName) as EdmComplexType).ToTypeReference());

                var function       = new EdmFunction(container.Namespace, "GetComplexInstances", collectionType.ToTypeReference());
                var functionImport = container.AddFunctionImport("GetComplexInstances", function);

                payload.AddAnnotation(new FunctionAnnotation()
                {
                    FunctionImport = functionImport
                });
                payload.AddAnnotation(new DataTypeAnnotation()
                {
                    EdmDataType = collectionType
                });
            }

            return(payload);
        }
コード例 #2
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);
        }
コード例 #3
0
        /// <summary>
        /// Visits a payload element whose root is a ComplexInstanceCollection.
        /// </summary>
        /// <param name="payloadElement">The root node of the payload element being visited.</param>
        public override void Visit(ComplexInstanceCollection payloadElement)
        {
            base.Visit(payloadElement);

            if (this.CurrentElementIsRoot())
            {
                this.AddExpectedFunctionImportToCollection(payloadElement);
            }
        }
コード例 #4
0
        /// <summary>
        /// Visits a payload element whose root is a ComplexInstanceCollection.
        /// </summary>
        /// <param name="payloadElement">The root node of the payload element being visited.</param>
        public override void Visit(ComplexInstanceCollection payloadElement)
        {
            base.Visit(payloadElement);

            if (this.CurrentElementIsRoot())
            {
                this.AddExpectedFunctionImportToCollection(payloadElement);
            }
        }
コード例 #5
0
        /// <summary>
        /// Visits a payload element whose root is an <see cref="ComplexInstanceCollection"/>.
        /// </summary>
        /// <param name="payloadElement">The root node of the payload element being visited.</param>
        public override void Visit(ComplexInstanceCollection payloadElement)
        {
            base.Visit(payloadElement);

            // Collections use a different format in JSON for V2 (and higher) payloads (in responses)
            if (!this.requestPayload)
            {
                this.AddVersionAnnotation(payloadElement);
            }
        }
        /// <summary>
        /// Visits the payload element and removes the collection name if it is present.
        /// </summary>
        /// <param name="payloadElement">The payload element to visit</param>
        public override void Visit(ComplexInstanceCollection payloadElement)
        {
            CollectionNameAnnotation collectionNameAnnotation = payloadElement.GetAnnotation<CollectionNameAnnotation>();
            if (payloadElement != null && collectionNameAnnotation != null)
            {
                collectionNameAnnotation.Name = string.Empty;
            }

            base.Visit(payloadElement);
        }
        /// <summary>
        /// Visits the payload element and removes the collection name if it is present.
        /// </summary>
        /// <param name="payloadElement">The payload element to visit</param>
        public override void Visit(ComplexInstanceCollection payloadElement)
        {
            CollectionNameAnnotation collectionNameAnnotation = payloadElement.GetAnnotation<CollectionNameAnnotation>();
            if (payloadElement != null && collectionNameAnnotation != null)
            {
                payloadElement.Annotations.Remove(collectionNameAnnotation);
            }

            base.Visit(payloadElement);
        }
コード例 #8
0
            /// <summary>
            /// Visits a payload element whose root is a ComplexInstanceCollection.
            /// </summary>
            /// <param name="expected">The root node of payload element being visited.</param>
            public void Visit(ComplexInstanceCollection expected)
            {
                ExceptionUtilities.CheckArgumentNotNull(expected, "expected");
                var observed = this.GetNextObservedElement <ComplexInstanceCollection>();

                using (this.Assert.WithMessage("Complex instance collection did not match expectation"))
                {
                    this.CompareCollection(expected, observed);
                }
            }
コード例 #9
0
        /// <summary>
        /// Visits the payload element and removes the collection name if it is present.
        /// </summary>
        /// <param name="payloadElement">The payload element to visit</param>
        public override void Visit(ComplexInstanceCollection payloadElement)
        {
            CollectionNameAnnotation collectionNameAnnotation = payloadElement.GetAnnotation <CollectionNameAnnotation>();

            if (payloadElement != null && collectionNameAnnotation != null)
            {
                payloadElement.Annotations.Remove(collectionNameAnnotation);
            }

            base.Visit(payloadElement);
        }
        /// <summary>
        /// Visits the payload element and removes the collection name if it is present.
        /// </summary>
        /// <param name="payloadElement">The payload element to visit</param>
        public override void Visit(ComplexInstanceCollection payloadElement)
        {
            CollectionNameAnnotation collectionNameAnnotation = payloadElement.GetAnnotation <CollectionNameAnnotation>();

            if (payloadElement != null && collectionNameAnnotation != null)
            {
                collectionNameAnnotation.Name = string.Empty;
            }

            base.Visit(payloadElement);
        }
コード例 #11
0
        /// <summary>
        /// Visits the children of the given payload element and replaces it with a copy if any child changes
        /// </summary>
        /// <param name="payloadElement">The payload element to potentially replace</param>
        /// <returns>The original element or a copy to replace it with</returns>
        public virtual ODataPayloadElement Visit(ComplexInstanceCollection payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
            var replaced = this.VisitCollection(payloadElement);

            if (!this.ShouldReplace(replaced, payloadElement))
            {
                return(payloadElement);
            }

            return(payloadElement.ReplaceWith(new ComplexInstanceCollection(replaced.ToArray())));
        }
コード例 #12
0
        /// <summary>
        /// Converts the ComplexInstanceCollection into an EntitySetInstance based on if the element type of the collection is entity instance
        /// </summary>
        /// <param name="payloadElement">The payload element to potentially replace</param>
        /// <returns>The original element or a copy to replace it with</returns>
        public override ODataPayloadElement Visit(ComplexInstanceCollection payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
            var replaced = (ComplexInstanceCollection)base.Visit(payloadElement);
            ExceptionUtilities.CheckObjectNotNull(replaced, "ComplexInstanceCollection Expected");
            if (replaced.All(e => e.ElementType == ODataPayloadElementType.EntityInstance) && replaced.Count > 0)
            {
                var entitySet = new EntitySetInstance(replaced.Cast<EntityInstance>().ToArray());
                return replaced.ReplaceWith(entitySet);
            }

            return replaced;
        }
コード例 #13
0
            /// <summary>
            /// Visits a payload element whose root is a ComplexInstanceCollection.
            /// </summary>
            /// <param name="payloadElement">The root node of payload element being visited.</param>
            public void Visit(ComplexInstanceCollection payloadElement)
            {
                ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
                ExceptionUtilities.Assert(this.isRootElement, "Complex collection is only supported as the root element");
                this.isRootElement = false;

                this.writer.StartArrayScope();
                foreach (var item in payloadElement)
                {
                    this.Recurse(item);
                }

                this.writer.EndScope();
            }
コード例 #14
0
        /// <summary>
        /// Converts the ComplexInstanceCollection into an EntitySetInstance based on if the element type of the collection is entity instance
        /// </summary>
        /// <param name="payloadElement">The payload element to potentially replace</param>
        /// <returns>The original element or a copy to replace it with</returns>
        public override ODataPayloadElement Visit(ComplexInstanceCollection payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
            var replaced = (ComplexInstanceCollection)base.Visit(payloadElement);

            ExceptionUtilities.CheckObjectNotNull(replaced, "ComplexInstanceCollection Expected");
            if (replaced.All(e => e.ElementType == ODataPayloadElementType.EntityInstance) && replaced.Count > 0)
            {
                var entitySet = new EntitySetInstance(replaced.Cast <EntityInstance>().ToArray());
                return(replaced.ReplaceWith(entitySet));
            }

            return(replaced);
        }
コード例 #15
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);
                }
            }
コード例 #16
0
        /// <summary>
        /// Build QueryValue from action response payload
        /// </summary>
        /// <param name="payload">response payload element</param>
        /// <param name="queryType">query type to build</param>
        /// <returns>query value that represents the payload</returns>
        private QueryValue BuildQueryValueForActionResponse(ODataPayloadElement payload, QueryType queryType)
        {
            EntitySetInstance           entitySetInstance           = payload as EntitySetInstance;
            PrimitiveProperty           primitiveProperty           = payload as PrimitiveProperty;
            ComplexProperty             complexProperty             = payload as ComplexProperty;
            PrimitiveMultiValueProperty primitiveMultiValueProperty = payload as PrimitiveMultiValueProperty;
            ComplexMultiValueProperty   complexMultiValueProperty   = payload as ComplexMultiValueProperty;
            PrimitiveCollection         primitiveCollection         = payload as PrimitiveCollection;
            ComplexInstanceCollection   complexInstanceCollection   = payload as ComplexInstanceCollection;

            if (entitySetInstance != null)
            {
                var xmlBaseAnnotations = payload.Annotations.OfType <XmlBaseAnnotation>();
                var collectionType     = this.currentExpression.ExpressionType as QueryCollectionType;
                ExceptionUtilities.CheckObjectNotNull(collectionType, "Cannot cast expression type to QueryCollectionType.");
                var elementType = collectionType.ElementType as QueryEntityType;
                return(this.BuildFromEntitySetInstance(entitySetInstance, elementType, xmlBaseAnnotations));
            }
            else if (primitiveProperty != null)
            {
                return(this.PayloadElementToQueryValueConverter.Convert(primitiveProperty.Value, queryType));
            }
            else if (complexProperty != null)
            {
                return(this.PayloadElementToQueryValueConverter.Convert(complexProperty.Value, queryType));
            }
            else if (primitiveMultiValueProperty != null)
            {
                return(this.PayloadElementToQueryValueConverter.Convert(primitiveMultiValueProperty.Value, queryType));
            }
            else if (complexMultiValueProperty != null)
            {
                return(this.PayloadElementToQueryValueConverter.Convert(complexMultiValueProperty.Value, queryType));
            }
            else if (primitiveCollection != null)
            {
                return(this.PayloadElementToQueryValueConverter.Convert(primitiveCollection, queryType));
            }
            else if (complexInstanceCollection != null)
            {
                return(this.PayloadElementToQueryValueConverter.Convert(complexInstanceCollection, queryType));
            }
            else
            {
                ExceptionUtilities.CheckArgumentNotNull(payload as EntityInstance, "Unexpected response payload type: " + payload.ElementType + ".");
                return(this.PayloadElementToQueryValueConverter.Convert(payload, queryType));
            }
        }
コード例 #17
0
        /// <summary>
        /// Normalizes primitive properties, potentially replacing them with collections if the metadata indicates the payload is from a service operation
        /// </summary>
        /// <param name="payloadElement">The payload element to potentially replace</param>
        /// <returns>The original element or a copy to replace it with</returns>
        public override ODataPayloadElement Visit(PrimitiveProperty payloadElement)
        {
            var replaced = base.Visit(payloadElement);

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

                // if the payload looks like
                // <Foo />
                // then it will be deserialized as a primitive property, when it could be an empty collection
                //
                if (this.ShouldReplaceWithCollection(payloadElement, payloadElement.Value.IsNull, payloadElement.Value.FullTypeName))
                {
                    // if the value is an empty string
                    var stringValue = payloadElement.Value.ClrValue as string;
                    if (stringValue != null && stringValue.Length == 0)
                    {
                        // get the element data type. Note that this must succeed based on the checks performed earlier
                        var dataType = ((CollectionDataType)payloadElement.Annotations.OfType <DataTypeAnnotation>().Single().DataType).ElementDataType;

                        // determine whether to return a complex or primitive collection based on the data type
                        ODataPayloadElementCollection collection;
                        if (dataType is PrimitiveDataType)
                        {
                            collection = new PrimitiveCollection();
                        }
                        else
                        {
                            ExceptionUtilities.Assert(dataType is ComplexDataType, "Data type was neither primitive nor complex");
                            collection = new ComplexInstanceCollection();
                        }

                        // return the replacement
                        return(payloadElement
                               .ReplaceWith(collection)
                               .WithAnnotations(new CollectionNameAnnotation()
                        {
                            Name = payloadElement.Name
                        }));
                    }
                }
            }

            return(replaced);
        }
コード例 #18
0
        /// <summary>
        /// Calls the base class method to process the instance collection.
        /// </summary>
        /// <param name="payloadElement">The complex instance collection to process.</param>
        public override void Visit(ComplexInstanceCollection payloadElement)
        {
            ODataCollectionStart collectionStart = new ODataCollectionStart();

            this.items.Push(collectionStart);
            var annotation = new ODataCollectionItemsObjectModelAnnotation();

            foreach (var complex in payloadElement)
            {
                this.items.Push(new ODataComplexValue()
                {
                    TypeName = complex.FullTypeName
                });

                this.Recurse(complex);
                annotation.Add(this.items.Pop());
            }

            collectionStart.SetAnnotation <ODataCollectionItemsObjectModelAnnotation>(annotation);
        }
コード例 #19
0
        /// <summary>
        /// Converts the given payload into a series of named value pairs
        /// </summary>
        /// <param name="element">The payload to convert</param>
        /// <param name="queryTypeToBuild">Query Type to build</param>
        /// <returns>The queryValue that represents the ODataPayload</returns>
        public QueryValue Convert(ODataPayloadElement element, QueryType queryTypeToBuild)
        {
            var typedValue = element as ITypedValue;

            if (typedValue != null && typedValue.IsNull)
            {
                return(queryTypeToBuild.NullValue);
            }

            var queryCollectionType = queryTypeToBuild as QueryCollectionType;

            // return empty QueryCollectionValue for all types of empty collections
            PrimitiveCollection       primitiveCollection       = element as PrimitiveCollection;
            ComplexInstanceCollection complexInstanceCollection = element as ComplexInstanceCollection;
            PrimitiveMultiValue       primitiveMultiValue       = element as PrimitiveMultiValue;
            ComplexMultiValue         complexMultiValue         = element as ComplexMultiValue;

            if ((primitiveCollection != null && primitiveCollection.Count == 0) ||
                (complexInstanceCollection != null && complexInstanceCollection.Count == 0) ||
                (primitiveMultiValue != null && primitiveMultiValue.Count == 0) ||
                (complexMultiValue != null && complexMultiValue.Count == 0))
            {
                return(queryCollectionType.CreateCollectionWithValues(new QueryValue[] { }));
            }

            if (element.ElementType == ODataPayloadElementType.PrimitiveValue)
            {
                return(CreateQueryScalarValue(element, queryTypeToBuild));
            }
            else if (queryCollectionType != null && element.ElementType == ODataPayloadElementType.PrimitiveMultiValue)
            {
                return(queryCollectionType.CreateCollectionWithValues(primitiveMultiValue.Select(p => CreateQueryScalarValue(p, queryCollectionType.ElementType))));
            }

            var namedValues = this.PayloadElementToNamedValuesConverter.ConvertToNamedValues(element);

            return(this.NamedValueToQueryValueConverter.Convert(namedValues, queryTypeToBuild));
        }
コード例 #20
0
        /// <summary>
        /// Visits a payload element whose root is an <see cref="ComplexInstanceCollection"/>.
        /// </summary>
        /// <param name="payloadElement">The root node of the payload element being visited.</param>
        public override void Visit(ComplexInstanceCollection payloadElement)
        {
            base.Visit(payloadElement);

            // Collections use a different format in JSON for V2 (and higher) payloads (in responses)
            if (!this.requestPayload)
            {
                this.AddVersionAnnotation(payloadElement);
            }
        }
コード例 #21
0
ファイル: TestValues.cs プロジェクト: AlineGuan/odata.net
        /// <summary>
        /// Creates a set of interesting homogeneous collection values with primitive and complex items.
        /// </summary>
        /// <param name="model">The model to add complex types to.</param>
        /// <param name="withTypeNames">true if the collection and complex value payloads should specify type names.</param>
        /// <param name="withExpectedType">true if an expected type annotation should be added to the generated payload element; otherwise false.</param>
        /// <param name="withcollectionName">true if the collection is not in the top level, otherwise false</param>
        /// <param name="fullSet">true if all available collection values should be returned, false if only the most interesting subset should be returned.</param>
        /// <returns>List of interesting collection values.</returns>
        public static IEnumerable<ODataPayloadElementCollection> CreateHomogeneousCollectionValues(
            EdmModel model,
            bool withTypeNames,
            bool withExpectedType,
            bool withcollectionName,
            bool fullset = true)
        {
            IEdmTypeReference itemTypeAnnotationType = null;
            IEdmTypeReference collectionTypeAnnotationType = null;
            EdmOperationImport primitiveCollectionFunctionImport = null;
            EdmEntityContainer defaultContainer = null;

            if (model != null)
            {
                defaultContainer = model.FindEntityContainer("TestModel.TestContainer") as EdmEntityContainer;
                if (defaultContainer == null)
                {
                    defaultContainer = new EdmEntityContainer("TestModel", "TestContainer");
                    model.AddElement(defaultContainer);
                }

                itemTypeAnnotationType = EdmCoreModel.Instance.GetString(true);
                collectionTypeAnnotationType = EdmCoreModel.GetCollection(itemTypeAnnotationType);

                var function = new EdmFunction("TestModel", "PrimitiveCollectionFunctionImport", collectionTypeAnnotationType);
                model.AddElement(function);
                primitiveCollectionFunctionImport = defaultContainer.AddFunctionImport("PrimitiveCollectionFunctionImport", function);
            }

            // primitive collection with single null item
            yield return new PrimitiveCollection(PayloadBuilder.PrimitiveValue(null).WithTypeAnnotation(itemTypeAnnotationType))
                .WithTypeAnnotation(collectionTypeAnnotationType)
                .ExpectedCollectionItemType(withExpectedType ? itemTypeAnnotationType : null)
                .ExpectedFunctionImport(withExpectedType ? primitiveCollectionFunctionImport : null)
                .CollectionName(withcollectionName ? "PrimitiveCollectionFunctionImport" : null);

            // primitive collection with multiple items (same type)
            yield return new PrimitiveCollection(
                PayloadBuilder.PrimitiveValue("Vienna").WithTypeAnnotation(itemTypeAnnotationType),
                PayloadBuilder.PrimitiveValue("Prague").WithTypeAnnotation(itemTypeAnnotationType),
                PayloadBuilder.PrimitiveValue("Redmond").WithTypeAnnotation(itemTypeAnnotationType)
                )
                .WithTypeAnnotation(collectionTypeAnnotationType)
                .ExpectedCollectionItemType(withExpectedType ? itemTypeAnnotationType : null)
                .ExpectedFunctionImport(withExpectedType ? primitiveCollectionFunctionImport : null)
                .CollectionName(withcollectionName ? "PrimitiveCollectionFunctionImport" : null);

            if (fullset)
            {
                // empty primitive collection
                yield return new PrimitiveCollection()
                    .WithTypeAnnotation(collectionTypeAnnotationType)
                    .ExpectedCollectionItemType(withExpectedType ? itemTypeAnnotationType : null)
                    .ExpectedFunctionImport(withExpectedType ? primitiveCollectionFunctionImport : null)
                    .CollectionName(withcollectionName ? "PrimitiveCollectionFunctionImport" : null);

                // primitive collection with a single item
                yield return new PrimitiveCollection(
                    PayloadBuilder.PrimitiveValue("Vienna").WithTypeAnnotation(itemTypeAnnotationType)
                    ).WithTypeAnnotation(collectionTypeAnnotationType)
                    .ExpectedCollectionItemType(withExpectedType ? itemTypeAnnotationType : null)
                    .ExpectedFunctionImport(withExpectedType ? primitiveCollectionFunctionImport : null)
                    .CollectionName(withcollectionName ? "PrimitiveCollectionFunctionImport" : null);

                // primitive collection with multiple null items
                yield return new PrimitiveCollection(
                    PayloadBuilder.PrimitiveValue(null).WithTypeAnnotation(itemTypeAnnotationType),
                    PayloadBuilder.PrimitiveValue(null).WithTypeAnnotation(itemTypeAnnotationType),
                    PayloadBuilder.PrimitiveValue(null).WithTypeAnnotation(itemTypeAnnotationType)
                    ).WithTypeAnnotation(collectionTypeAnnotationType)
                    .ExpectedCollectionItemType(withExpectedType ? itemTypeAnnotationType : null)
                    .ExpectedFunctionImport(withExpectedType ? primitiveCollectionFunctionImport : null)
                    .CollectionName(withcollectionName ? "PrimitiveCollectionFunctionImport" : null);
            }

            string localPersonTypeName = "ComplexCollectionPersonItemType";
            string personTypeName = GetFullTypeName(localPersonTypeName);
            EdmOperationImport complexCollectionFunctionImport = null;
            if (model != null)
            {
                EdmComplexType complexItemType = model.FindDeclaredType(personTypeName) as EdmComplexType;
                if (complexItemType == null)
                {
                    complexItemType = new EdmComplexType(NamespaceName, localPersonTypeName);
                    complexItemType.AddStructuralProperty("FirstName", EdmCoreModel.Instance.GetString(true));
                    complexItemType.AddStructuralProperty("LastName", EdmCoreModel.Instance.GetString(true));
                    model.AddElement(complexItemType);
                }

                itemTypeAnnotationType = complexItemType.ToTypeReference();
                collectionTypeAnnotationType = EdmCoreModel.GetCollection(itemTypeAnnotationType);
                complexCollectionFunctionImport = defaultContainer.FindOperationImports("ComplexCollectionFunctionImport").SingleOrDefault() as EdmOperationImport;
                if (complexCollectionFunctionImport == null)
                {
                    var complexCollectionFunction = new EdmFunction("TestModel", "ComplexCollectionFunctionImport", collectionTypeAnnotationType);
                    model.AddElement(complexCollectionFunction);
                    complexCollectionFunctionImport = defaultContainer.AddFunctionImport("ComplexCollectionFunctionImport", complexCollectionFunction);
                }
            }

            // complex collection with multiple complex values
            var complexInstance1 = PayloadBuilder.ComplexValue(withTypeNames ? personTypeName : null).Property("FirstName", PayloadBuilder.PrimitiveValue("Clemens")).Property("LastName", PayloadBuilder.PrimitiveValue("Kerer")).WithTypeAnnotation(itemTypeAnnotationType);
            var complexInstance2 = PayloadBuilder.ComplexValue(withTypeNames ? personTypeName : null).Property("FirstName", PayloadBuilder.PrimitiveValue("Vitek")).Property("LastName", PayloadBuilder.PrimitiveValue("Karas")).WithTypeAnnotation(itemTypeAnnotationType);
            if (!withTypeNames && model != null)
            {
                complexInstance1.AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null });
                complexInstance2.AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null });
            }
            var complexInstanceCollection = new ComplexInstanceCollection(
                complexInstance1,
                complexInstance2
                ).WithTypeAnnotation(collectionTypeAnnotationType)
                .ExpectedCollectionItemType(withExpectedType ? itemTypeAnnotationType : null)
                .ExpectedFunctionImport(withExpectedType ? complexCollectionFunctionImport : null)
                .CollectionName(withcollectionName ? "ComplexCollectionFunctionImport" : null);

            yield return complexInstanceCollection;

            if (fullset)
            {
                // complex collection with a single complex value
                complexInstance1 = PayloadBuilder.ComplexValue(withTypeNames ? personTypeName : null)
                    .Property("FirstName", PayloadBuilder.PrimitiveValue("Clemens"))
                    .Property("LastName", PayloadBuilder.PrimitiveValue("Kerer"))
                    .WithTypeAnnotation(itemTypeAnnotationType);
                if (!withTypeNames && model != null)
                {
                    complexInstance1.AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null });
                }

                yield return new ComplexInstanceCollection(
                    complexInstance1
                    ).WithTypeAnnotation(collectionTypeAnnotationType)
                    .ExpectedCollectionItemType(withExpectedType ? itemTypeAnnotationType : null)
                    .ExpectedFunctionImport(withExpectedType ? complexCollectionFunctionImport : null)
                    .CollectionName(withcollectionName ? "ComplexCollectionFunctionImport" : null);

                string localCityTypeName = "ComplexCollectionCityItemType";
                IEdmTypeReference cityItemTypeAnnotation = null;
                if (model != null)
                {
                    EdmComplexType complexItemType = model.FindDeclaredType(GetFullTypeName(localCityTypeName)) as EdmComplexType;
                    if (complexItemType == null)
                    {
                        complexItemType = new EdmComplexType(NamespaceName, localCityTypeName);
                        complexItemType.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(true));
                        model.AddElement(complexItemType);
                    }
                    cityItemTypeAnnotation = complexItemType.ToTypeReference();
                }
            }
        }
コード例 #22
0
 /// <summary>
 /// Calls the base class method to process the instance collection.
 /// </summary>
 /// <param name="payloadElement">The complex instance collection to process.</param>
 public override void Visit(ComplexInstanceCollection payloadElement)
 {
     base.Visit(payloadElement);
 }
コード例 #23
0
        /// <summary>
        /// Converts the given name/value pair into a property element.
        /// And infers the type of property from the converted value.
        /// </summary>
        /// <param name="jsonProperty">the property value</param>
        /// <returns>the converted property</returns>
        private PropertyInstance ConvertProperty(JsonProperty jsonProperty)
        {
            if (jsonProperty.Value.JsonType == JsonValueType.JsonPrimitiveValue && ((JsonPrimitiveValue)jsonProperty.Value).Value == null)
            {
                return(new NullPropertyInstance()
                {
                    Name = jsonProperty.Name
                });
            }
            else
            {
                ODataPayloadElement elem = this.ConvertValue(jsonProperty.Value);
                ExceptionUtilities.CheckObjectNotNull(elem, "Converted property value was null");

                if (elem.ElementType == ODataPayloadElementType.PrimitiveValue)
                {
                    return(new PrimitiveProperty(jsonProperty.Name, (PrimitiveValue)elem));
                }
                else if (elem.ElementType == ODataPayloadElementType.ComplexInstance)
                {
                    return(new ComplexProperty(jsonProperty.Name, (ComplexInstance)elem));
                }
                else if (elem.ElementType == ODataPayloadElementType.EntityInstance)
                {
                    return(new NavigationPropertyInstance(jsonProperty.Name, new ExpandedLink(elem)));
                }
                else if (elem.ElementType == ODataPayloadElementType.DeferredLink)
                {
                    DeferredLink deferredLink = (DeferredLink)elem;
                    return(new NavigationPropertyInstance(jsonProperty.Name, deferredLink));
                }
                else if (elem.ElementType == ODataPayloadElementType.EntitySetInstance)
                {
                    return(new NavigationPropertyInstance(jsonProperty.Name, elem));
                }
                else if (elem.ElementType == ODataPayloadElementType.ComplexMultiValue)
                {
                    ComplexMultiValue complexMultiValue = (ComplexMultiValue)elem;
                    return(new ComplexMultiValueProperty(jsonProperty.Name, complexMultiValue));
                }
                else if (elem.ElementType == ODataPayloadElementType.PrimitiveMultiValue)
                {
                    PrimitiveMultiValue primitiveMultiValue = (PrimitiveMultiValue)elem;
                    return(new PrimitiveMultiValueProperty(jsonProperty.Name, primitiveMultiValue));
                }
                else if (elem.ElementType == ODataPayloadElementType.ComplexInstanceCollection)
                {
                    ComplexInstanceCollection complexCollection = (ComplexInstanceCollection)elem;
                    return(new ComplexMultiValueProperty(jsonProperty.Name, new ComplexMultiValue(null, false, complexCollection.ToArray())));
                }
                else if (elem.ElementType == ODataPayloadElementType.PrimitiveCollection)
                {
                    PrimitiveCollection primitiveCollection = (PrimitiveCollection)elem;
                    return(new PrimitiveMultiValueProperty(jsonProperty.Name, new PrimitiveMultiValue(null, false, primitiveCollection.ToArray())));
                }
                else if (elem.ElementType == ODataPayloadElementType.NamedStreamInstance)
                {
                    NamedStreamInstance nsi = (NamedStreamInstance)elem;
                    nsi.Name = jsonProperty.Name;
                    return(nsi);
                }
                else
                {
                    ExceptionUtilities.Assert(elem.ElementType == ODataPayloadElementType.EmptyUntypedCollection, "Do not know how to handle element of type" + elem.ElementType);
                    return(new EmptyCollectionProperty(jsonProperty.Name, (EmptyUntypedCollection)elem));
                }
            }
        }
コード例 #24
0
        private static ComplexInstanceCollection GetComplexInstanceCollection(IRandomNumberGenerator random, EdmModel model = null, ODataVersion version = ODataVersion.V4)
        {
            var complex = GetComplexInstance(random, model, version);
            int numinstances = random.ChooseFrom(new[] { 0, 1, 3 });
            var payload = new ComplexInstanceCollection(GenerateSimilarComplexInstances(random, complex, numinstances).ToArray());
            if (model != null)
            {
                var container = model.EntityContainersAcrossModels().Single() as EdmEntityContainer;
                var collectionType = new EdmCollectionType((model.FindDeclaredType(complex.FullTypeName) as EdmComplexType).ToTypeReference());

                var function = new EdmFunction(container.Namespace, "GetComplexInstances", collectionType.ToTypeReference());
                var functionImport = container.AddFunctionImport("GetComplexInstances", function);

                payload.AddAnnotation(new FunctionAnnotation() { FunctionImport = functionImport });
                payload.AddAnnotation(new DataTypeAnnotation() { EdmDataType = collectionType });
            }

            return payload;
        }
コード例 #25
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;
        }
コード例 #26
0
            /// <summary>
            /// Visits the payload element.
            /// </summary>
            /// <param name="payloadElement">The payload element to visit.</param>
            public override void Visit(ComplexInstanceCollection payloadElement)
            {
                var observed = this.GetNextObservedElement <ComplexInstanceCollection>();

                this.VisitEnumerable(payloadElement, observed);
            }
コード例 #27
0
 /// <summary>
 /// Calls the base class method to process the instance collection.
 /// </summary>
 /// <param name="payloadElement">The complex instance collection to process.</param>
 public override void Visit(ComplexInstanceCollection payloadElement)
 {
     base.Visit(payloadElement);
 }
コード例 #28
0
            /// <summary>
            /// Visits a payload element whose root is a ComplexInstanceCollection.
            /// </summary>
            /// <param name="payloadElement">The root node of payload element being visited.</param>
            public void Visit(ComplexInstanceCollection payloadElement)
            {
                ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");

                var current = this.expectedValueStack.Peek();
                var value = current as QueryCollectionValue;
                ExceptionUtilities.CheckObjectNotNull(value, "Value was not a collection. Value was: '{0}'", current.ToString());

                this.parent.Assert.AreEqual(value.Elements.Count, payloadElement.Count, "Complex instance collection count did not match expectation");
                for (int i = 0; i < value.Elements.Count; i++)
                {
                    this.RecurseWithMessage(payloadElement[i], value.Elements[i], "Complex instance at position {0} did not match expectation", i + 1);
                }
            }
 /// <summary>
 /// Visits the payload element and removes the collection name if it is present.
 /// </summary>
 /// <param name="payloadElement">The payload element to visit</param>
 public override void Visit(ComplexInstanceCollection payloadElement)
 {
     payloadElement.RemoveAnnotations(typeof(CollectionNameAnnotation));
     base.Visit(payloadElement);
 }
コード例 #30
0
 /// <summary>
 /// Visits the payload element
 /// </summary>
 /// <param name="payloadElement">The payload element to visit</param>
 public virtual void Visit(ComplexInstanceCollection payloadElement)
 {
     this.VisitCollection(payloadElement);
 }
コード例 #31
0
            /// <summary>
            /// Visits a payload element whose root is a ComplexInstanceCollection.
            /// </summary>
            /// <param name="payloadElement">The root node of payload element being visited.</param>
            public void Visit(ComplexInstanceCollection payloadElement)
            {
                ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
                ExceptionUtilities.Assert(this.isRootElement, "Complex collection is only supported as the root element");
                this.isRootElement = false;

                this.writer.StartArrayScope();
                foreach (var item in payloadElement)
                {
                    this.Recurse(item);
                }

                this.writer.EndScope();
            }
コード例 #32
0
        /// <summary>
        /// Calls the base class method to process the instance collection.
        /// </summary>
        /// <param name="payloadElement">The complex instance collection to process.</param>
        public override void Visit(ComplexInstanceCollection payloadElement)
        {
            ODataCollectionStart collectionStart = new ODataCollectionStart();
            this.items.Push(collectionStart);
            var annotation = new ODataCollectionItemsObjectModelAnnotation();
            foreach (var complex in payloadElement)
            {
                this.items.Push(new ODataComplexValue()
                {
                    TypeName = complex.FullTypeName
                });

                this.Recurse(complex);
                annotation.Add(this.items.Pop());
            }

            collectionStart.SetAnnotation<ODataCollectionItemsObjectModelAnnotation>(annotation);
        }
コード例 #33
0
 /// <summary>
 /// Visits a payload element whose root is a ComplexInstanceCollection.
 /// </summary>
 /// <param name="payloadElement">The root node of payload element being visited.</param>
 public override void Visit(ComplexInstanceCollection payloadElement)
 {
     RemoveChangeAnnotations(payloadElement);
     base.Visit(payloadElement);
 }
 /// <summary>
 /// Visits the payload element and removes the collection name if it is present.
 /// </summary>
 /// <param name="payloadElement">The payload element to visit</param>
 public override void Visit(ComplexInstanceCollection payloadElement)
 {
     payloadElement.RemoveAnnotations(typeof(CollectionNameAnnotation));
     base.Visit(payloadElement);
 }
コード例 #35
0
 /// <summary>
 /// Visits the payload element
 /// </summary>
 /// <param name="payloadElement">The payload element to visit</param>
 public override void Visit(ComplexInstanceCollection payloadElement)
 {
     this.SerializeTypedValueCollection(payloadElement);
 }
コード例 #36
0
        /// <summary>
        /// Normalizes primitive properties, potentially replacing them with collections if the metadata indicates the payload is from a service operation
        /// </summary>
        /// <param name="payloadElement">The payload element to potentially replace</param>
        /// <returns>The original element or a copy to replace it with</returns>
        public override ODataPayloadElement Visit(PrimitiveProperty payloadElement)
        {
            var replaced = base.Visit(payloadElement);
            if (replaced.ElementType == ODataPayloadElementType.PrimitiveProperty)
            {
                payloadElement = (PrimitiveProperty)replaced;

                // if the payload looks like
                // <Foo />
                // then it will be deserialized as a primitive property, when it could be an empty collection
                //
                if (this.ShouldReplaceWithCollection(payloadElement, payloadElement.Value.IsNull, payloadElement.Value.FullTypeName))
                {
                    // if the value is an empty string
                    var stringValue = payloadElement.Value.ClrValue as string;
                    if (stringValue != null && stringValue.Length == 0)
                    {
                        // get the element data type. Note that this must succeed based on the checks performed earlier
                        var dataType = ((CollectionDataType)payloadElement.Annotations.OfType<DataTypeAnnotation>().Single().DataType).ElementDataType;

                        // determine whether to return a complex or primitive collection based on the data type
                        ODataPayloadElementCollection collection;
                        if (dataType is PrimitiveDataType)
                        {
                            collection = new PrimitiveCollection();
                        }
                        else
                        {
                            ExceptionUtilities.Assert(dataType is ComplexDataType, "Data type was neither primitive nor complex");
                            collection = new ComplexInstanceCollection();
                        }

                        // return the replacement
                        return payloadElement
                            .ReplaceWith(collection)
                            .WithAnnotations(new CollectionNameAnnotation() { Name = payloadElement.Name });
                    }
                }
            }

            return replaced;
        }