Example #1
0
        /// <summary>
        /// Deserializes the payload using the JsonParser, then converts the resulting clr objects into payload element form
        /// Throws an TaupoInvalidOperationException if the json does not evaluate successfully.
        /// </summary>
        /// <param name="serialized">A raw json payload</param>
        /// <param name="payloadContext">Additional payload information to aid deserialization</param>
        /// <returns>A PayloadElement representation of the payload</returns>
        public ODataPayloadElement DeserializeFromBinary(byte[] serialized, ODataPayloadContext payloadContext)
        {
            ExceptionUtilities.CheckArgumentNotNull(serialized, "serialized");
            ExceptionUtilities.CheckArgumentNotNull(payloadContext, "payloadContext");

            string encodingName = payloadContext.EncodingName;

            ODataPayloadElement errorPayload = null;

            if (this.payloadErrorDeserializer.TryDeserializeErrorPayload(serialized, encodingName, out errorPayload))
            {
                return(errorPayload);
            }

            // Evaluate the given JSON text
            Encoding encoding = HttpUtilities.GetEncodingOrDefault(encodingName);
            string   payload  = encoding.GetString(serialized, 0, serialized.Length);

            JsonValue jsonData = null;

            using (StringReader reader = new StringReader(payload))
            {
                JsonTokenizer tokenizer = new JsonTokenizer(reader);
                JsonParser    parser    = new JsonParser(tokenizer);
                jsonData = parser.ParseValue();
            }

            // convert the deserialized JsonValue objects into payload elements
            return(this.payloadConverter.ConvertToPayloadElement(jsonData));
        }
            private TElement GetNextObservedElement <TElement>() where TElement : ODataPayloadElement
            {
                var observed = this.observedElementStack.Peek();

                this.Assert.AreEqual(ODataPayloadElement.GetElementType <TElement>(), observed.ElementType, "Unexpected element type");
                return((TElement)observed);
            }
Example #3
0
        /// <summary>
        /// Validator for collections of primitive and complex types.
        /// </summary>
        /// <param name="payloadElement">The payload element to validate.</param>
        /// <param name="testConfigLimits">The test configuration limits to modify.</param>
        public static void NonEntityCollectionValidator(ODataPayloadElement payloadElement, TestConfigurationLimits testConfigLimits)
        {
            ExceptionUtilities.Assert(payloadElement is PrimitiveMultiValue || payloadElement is ComplexMultiValue, "This validator only works on collection values.");

            // Collection values require V3.
            testConfigLimits.RaiseMinPayloadVersion(ODataVersion.V4);
        }
        /// <summary>
        /// Normalizes a workspace or resource collection's Atom title property value so that it matches the element's title annotation.
        /// </summary>
        /// <param name="payloadElement">The payload element to normalize</param>
        /// <param name="titlePropertyValue">The value of the payload element's title property</param>
        /// <param name="setPropertyValue">Delegate for setting the payload element's title property</param>
        private void NormalizeTitleValue(ODataPayloadElement payloadElement, string titlePropertyValue, Action <string> setPropertyValue)
        {
            XmlTreeAnnotation titleXmlTreeAnnotation = payloadElement.Annotations
                                                       .OfType <XmlTreeAnnotation>()
                                                       .SingleOrDefault(a => a.LocalName.Equals(TestAtomConstants.AtomTitleElementName));

            if (titlePropertyValue != null)
            {
                if (titleXmlTreeAnnotation != null)
                {
                    string titleAnnotationValue = titleXmlTreeAnnotation.PropertyValue;
                    if (titleAnnotationValue == null)
                    {
                        titleXmlTreeAnnotation.PropertyValue = titlePropertyValue;
                    }
                    else
                    {
                        ExceptionUtilities.Assert(titlePropertyValue == titleAnnotationValue, "Title in workspace or resource collection has different values : Property=" + titlePropertyValue + ", Annotation=" + titleAnnotationValue);
                    }
                }
                else
                {
                    payloadElement.AtomTitle(titlePropertyValue, TestAtomConstants.AtomTextConstructTextKind);
                }
            }
            else if (titleXmlTreeAnnotation != null)
            {
                setPropertyValue(titleXmlTreeAnnotation.PropertyValue);
            }
        }
        /// <summary>
        /// Normalizes the given payload root
        /// </summary>
        /// <param name="rootElement">The payload to normalize</param>
        /// <returns>The normalized payload</returns>
        public override ODataPayloadElement Normalize(ODataPayloadElement rootElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement");

            // TODO: convert to correct CLR type based on metadata annotations
            return(rootElement);
        }
        private void ValidateAndPrintInfoOnError(ODataUri requestUri, ODataPayloadElement rootElement, QueryValue expectedValue)
        {
            try
            {
                this.Validator.Validate(rootElement, expectedValue);
            }
            catch (DataComparisonException)
            {
                // Doing this because of unit test failures, will need to fix this later
                if (this.QueryDataSet != null)
                {
                    this.Logger.WriteLine(LogLevel.Info, "Actual Payload Entity Graph:");
                    this.Logger.WriteLine(LogLevel.Info, this.ODataPayloadElementEntityGraphPrettyPrinter.PrettyPrint(rootElement));
                    this.Logger.WriteLine(LogLevel.Info, "Expected Query Entity Graph:");
                    this.Logger.WriteLine(LogLevel.Info, this.ODataQueryValueEntityGraphPrettyPrinter.PrettyPrint(expectedValue, 10));

                    this.Logger.WriteLine(LogLevel.Info, "Query DataSet Data");
                    foreach (var entitySet in requestUri.GetAllEntitySetsIncludingExpands())
                    {
                        this.Logger.WriteLine(LogLevel.Info, entitySet.Name + " DataSet");
                        var results = this.QueryDataSet[entitySet.Name];
                        this.Logger.WriteLine(LogLevel.Info, this.ODataQueryValueEntityGraphPrettyPrinter.PrettyPrint(results, 1));
                    }
                }

                throw;
            }
        }
        /// <summary>
        /// Remove duplicate annotations that might be added
        /// </summary>
        /// <param name="payload">payload to remove duplicate annotations for</param>
        public static void RemoveEPMDuplicationAnnotations(ODataPayloadElement payload)
        {
            ODataLibPayloadElementComparer comparer = new ODataLibPayloadElementComparer();

            for (int i = 0; i < payload.Annotations.Count; i++)
            {
                var epmAnn1 = payload.Annotations[i] as XmlTreeAnnotation;
                if (epmAnn1 == null)
                {
                    continue;
                }
                for (int j = i + 1; j < payload.Annotations.Count; j++)
                {
                    var epmAnn2 = payload.Annotations[j] as XmlTreeAnnotation;
                    if (epmAnn2 == null)
                    {
                        continue;
                    }
                    if (epmAnn1.LocalName == epmAnn2.LocalName && epmAnn1.NamespaceName == epmAnn2.NamespaceName)
                    {
                        payload.Annotations.RemoveAt(j);
                    }
                }
            }
        }
        /// <summary>
        /// Applies expected result normalizers to the specified payload element.
        /// </summary>
        /// <param name="expectedResultPayloadElement">The payload element to apply the normalizers to.</param>
        /// <param name="testConfiguration">The test configuration to use.</param>
        /// <returns>The expected result after normalization.</returns>
        private ODataPayloadElement ApplyExpectedResultNormalizers(ODataPayloadElement expectedResultPayloadElement, ReaderTestConfiguration testConfiguration)
        {
            // If we have some normalizers and some of them do apply to this test configuration
            // make a copy and apply the normalizer.
            if (this.ExpectedResultNormalizers != null)
            {
                ODataPayloadElement expectedResultPayloadElementCopy = null;
                foreach (var getNormalizerFunc in this.ExpectedResultNormalizers)
                {
                    var normalizer = getNormalizerFunc(testConfiguration);
                    if (normalizer != null)
                    {
                        if (expectedResultPayloadElementCopy == null)
                        {
                            expectedResultPayloadElementCopy = expectedResultPayloadElement.DeepCopy();
                        }

                        expectedResultPayloadElementCopy = normalizer(expectedResultPayloadElementCopy);
                    }
                }

                expectedResultPayloadElement = expectedResultPayloadElementCopy ?? expectedResultPayloadElement;
            }

            return(expectedResultPayloadElement);
        }
        /// <summary>
        /// Visits the root element of the operation.
        /// </summary>
        /// <param name="operation">The operation to visit</param>
        protected override void VisitResponseOperation(HttpResponseData operation)
        {
            var responseOperation = operation as ODataResponse;

            ExceptionUtilities.CheckObjectNotNull(responseOperation, "Operation must be a response");
            ODataPayloadElement rootElement = null;
            string contentType = null;

            if (responseOperation.RootElement != null)
            {
                rootElement = responseOperation.RootElement;
                contentType = responseOperation.GetHeaderValueIfExists(Microsoft.OData.Core.ODataConstants.ContentTypeHeader);
            }

            if (rootElement != null)
            {
                ODataFormat format = null;
                if (contentType.Contains(MimeTypes.ApplicationAtomXml))
                {
                    format = ODataFormat.Atom;
                }
                else if (contentType.Contains(MimeTypes.ApplicationJson))
                {
                    format = ODataFormat.Json;
                }

                new ExpectedPayloadFixups().Fixup(rootElement, format);
            }
        }
        /// <summary>
        /// Normalizes the given payload root
        /// </summary>
        /// <param name="rootElement">The payload to normalize</param>
        /// <returns>The normalized payload</returns>
        public override ODataPayloadElement Normalize(ODataPayloadElement rootElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement");

            ExceptionUtilities.Assert(rootElement.ElementType == ODataPayloadElementType.PrimitiveValue, "Only primitive values are supported by this format. Type was: '{0}'", rootElement.ElementType);
            var primitiveValue = (PrimitiveValue)rootElement;

            // replace non-null string with deserialized instance of correct type
            var serialized = primitiveValue.ClrValue as string;

            if (serialized != null)
            {
                var dataType = primitiveValue.Annotations.OfType <DataTypeAnnotation>().Select(t => t.DataType).OfType <PrimitiveDataType>().SingleOrDefault();
                if (dataType != null)
                {
                    var clrType = dataType.GetFacetValue <PrimitiveClrTypeFacet, Type>(null);
                    if (clrType != null && clrType != typeof(string))
                    {
                        var converted = this.XmlPrimitiveConverter.DeserializePrimitive(serialized, clrType);
                        primitiveValue = primitiveValue.ReplaceWith(new PrimitiveValue(primitiveValue.FullTypeName, converted));
                    }
                }
            }

            return(primitiveValue);
        }
Example #11
0
        private ODataUri BuildODataUri(ODataPayloadElement payload)
        {
            var entityInstance = payload as EntityInstance;

            if (entityInstance != null)
            {
                EntityModelTypeAnnotation type = entityInstance.GetAnnotation <EntityModelTypeAnnotation>();
                ExceptionUtilities.CheckObjectNotNull(type, "Type annotation was expected");

                var entityType = ((EntityDataType)type.EntityModelType).Definition;

                // First is OK because MEST doesnt matter
                var entitySet = entityType.Model.EntityContainers.SelectMany(c => c.EntitySets).First(s => s.EntityType == entityType);
                return(new ODataUri(ODataUriBuilder.EntitySet(entitySet)));
            }
            var complexProperty = payload as ComplexProperty;

            if (complexProperty != null)
            {
                EntityModelTypeAnnotation type = entityInstance.GetAnnotation <EntityModelTypeAnnotation>();
                ExceptionUtilities.CheckObjectNotNull(type, "Type annotation was expected");

                var entityType = ((EntityDataType)type.EntityModelType).Definition;

                // First is OK because MEST doesnt matter
                var entitySet = entityType.Model.EntityContainers.SelectMany(c => c.EntitySets).First(s => s.EntityType == entityType);
                return(new ODataUri(ODataUriBuilder.EntitySet(entitySet)));
            }

            // TODO: Add support for other types
            return(null);
        }
Example #12
0
        /// <summary>
        /// For a given payload element determines its test configuration limits.
        /// </summary>
        /// <param name="payloadElement">The payload element to check.</param>
        /// <param name="validators">The collection of validators to use.</param>
        /// <returns>The test configuration limits computed.</returns>
        public static TestConfigurationLimits GetTestConfigurationLimits(ODataPayloadElement payloadElement, Validators validators)
        {
            TestConfigurationLimits testConfigLimits = new TestConfigurationLimits();

            new Visitor(validators, testConfigLimits).Visit(payloadElement);
            return(testConfigLimits);
        }
Example #13
0
        public ODataPayloadElement DeserializeFromBinary(byte[] serialized, ODataPayloadContext payloadContext)
        {
            ExceptionUtilities.CheckArgumentNotNull(serialized, "serialized");
            ExceptionUtilities.CheckArgumentNotNull(payloadContext, "payloadContext");

            string encodingName = payloadContext.EncodingName;

            ODataPayloadElement errorPayload = null;

            if (this.payloadErrorDeserializer.TryDeserializeErrorPayload(serialized, encodingName, out errorPayload))
            {
                return(errorPayload);
            }

            var encoding = HttpUtilities.GetEncodingOrDefault(encodingName);

            XDocument document = null;

            using (StreamReader reader = new StreamReader(new MemoryStream(serialized), encoding))
            {
                document = XDocument.Load(reader);
            }

            ExceptionUtilities.Assert(document != null, "Deserialized document cannot be null.");

            return(this.xmlConverter.ConvertToPayloadElement(document.Root));
        }
        /// <summary>
        /// Called to write the payload to the specified <paramref name="messageWriter"/>.
        /// </summary>
        /// <param name="messageWriter">The <see cref="ODataMessageWriterTestWrapper"/> to use for writing the payload.</param>
        /// <param name="testConfiguration">The test configuration to generate the payload for.</param>
        protected override void WritePayload(ODataMessageWriterTestWrapper messageWriter, WriterTestConfiguration testConfiguration)
        {
            ODataPayloadElement payload = this.PayloadElement.DeepCopy();

            if (testConfiguration.Format == ODataFormat.Json)
            {
                payload.Accept(new ODataPayloadJsonNormalizer());
                //Fixup added as odatalib requires ids on feeds even though it can't be represented in json
                payload.Accept(new AddFeedIDFixup());
            }
            else if (testConfiguration.Format == ODataFormat.Atom)
            {
                // TODO: Remove visitor
                payload.Accept(new ODataPayloadElementNullIDVisitor());
            }

            ODataPayloadElementToObjectModelConverter converter = new ODataPayloadElementToObjectModelConverter(!testConfiguration.IsRequest);

            if (this.PayloadKind != ODataPayloadKind.Batch)
            {
                this.settings.ObjectModelToMessageWriter.WriteMessage(messageWriter, this.PayloadKind, converter.Convert(payload));
            }
            else
            {
                TestWriterUtils.WriteBatchPayload(messageWriter,
                                                  payload,
                                                  converter,
                                                  this.settings.ObjectModelToMessageWriter,
                                                  this.Model,
                                                  this.settings.Assert,
                                                  testConfiguration,
                                                  true);
            }
        }
        /// <summary>
        /// Normalizes the given payload root
        /// </summary>
        /// <param name="rootElement">The payload to normalize</param>
        /// <returns>The normalized payload</returns>
        public override ODataPayloadElement Normalize(ODataPayloadElement rootElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement");

            // TODO: convert to correct CLR type based on metadata annotations
            return rootElement;
        }
Example #16
0
        /// <summary>
        /// Returns the serialized batch payload
        /// </summary>
        /// <param name="batchPayload">batch payload</param>
        /// <returns>bytes representing batch payload</returns>
        private static byte[] SerializeBatchPayload(ODataPayloadElement batchPayload, PayloadReaderTestDescriptor.Settings settings)
        {
            string boundary = null;

            Byte[] bytes = null;

            Func <ODataPayloadElement, string> getBoundaryAnnotation = (batchPayloadElement) =>
            {
                var boundaryAnn = batchPayloadElement.Annotations.OfType <BatchBoundaryAnnotation>().Single();
                ExceptionUtilities.CheckObjectNotNull(boundaryAnn, "bounday annotation cannot be null");
                return(boundaryAnn.BatchBoundaryInPayload);
            };

            var batchRequestPayload = batchPayload as BatchRequestPayload;

            if (batchRequestPayload != null)
            {
                boundary = getBoundaryAnnotation(batchRequestPayload);
                bytes    = settings.BatchSerializer.SerializeBatchPayload(batchRequestPayload, boundary, Encoding.UTF8.WebName); // encoding assumed to be UTF8
            }
            else
            {
                var batchResponsePayload = batchPayload as BatchResponsePayload;
                boundary = getBoundaryAnnotation(batchResponsePayload);
                ExceptionUtilities.CheckObjectNotNull(batchResponsePayload, "the specified batch payload is neither a request payload nor a response");
                bytes = settings.BatchSerializer.SerializeBatchPayload(batchResponsePayload, boundary, Encoding.UTF8.WebName); // encoding assumed to be UTF8
            }

            return(bytes);
        }
        /// <summary>
        /// Normalizes the given payload root
        /// </summary>
        /// <param name="rootElement">The payload to normalize</param>
        /// <returns>The normalized payload</returns>
        public override ODataPayloadElement Normalize(ODataPayloadElement rootElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement");

            ExceptionUtilities.Assert(rootElement.ElementType == ODataPayloadElementType.PrimitiveValue, "Only primitive values are supported by this format. Type was: '{0}'", rootElement.ElementType);
            var primitiveValue = (PrimitiveValue)rootElement;

            // replace non-null string with deserialized instance of correct type
            var serialized = primitiveValue.ClrValue as string;
            if (serialized != null)
            {
                var dataType = primitiveValue.Annotations.OfType<DataTypeAnnotation>().Select(t => t.DataType).OfType<PrimitiveDataType>().SingleOrDefault();
                if (dataType != null)
                {
                    var clrType = dataType.GetFacetValue<PrimitiveClrTypeFacet, Type>(null);
                    if (clrType != null && clrType != typeof(string))
                    {
                        var converted = this.XmlPrimitiveConverter.DeserializePrimitive(serialized, clrType);
                        primitiveValue = primitiveValue.ReplaceWith(new PrimitiveValue(primitiveValue.FullTypeName, converted));
                    }
                }
            }

            return primitiveValue;
        }
 /// <summary>
 /// Normalizes the specified payload element.
 /// </summary>
 /// <param name="payloadElement">The payload element to normalize.</param>
 /// <returns>The normalized payload element.</returns>
 public ODataPayloadElement Normalize(ODataPayloadElement payloadElement)
 {
     // Allways make a deep copy since we will modify all the batch parts.
     payloadElement = payloadElement.DeepCopy();
     this.Recurse(payloadElement);
     return(payloadElement);
 }
        public virtual bool TryDeserializeErrorPayload(byte[] serialized, string encodingName, out ODataPayloadElement errorPayload)
        {
            ExceptionUtilities.CheckArgumentNotNull(serialized, "serialized");
            ExceptionUtilities.CheckAllRequiredDependencies(this);

            // get the encoding based on the given encoding name
            var encoding = HttpUtilities.GetEncodingOrDefault(encodingName);

            using (StreamReader streamReader = new StreamReader(new MemoryStream(serialized), encoding))
            {
                using (XmlReader reader = XmlReader.Create(streamReader))
                {
                    bool foundErrorPayload = false;

                    while (reader.Read())
                    {
                        if (reader.IsStartElement(ODataConstants.ErrorElementName, ODataConstants.DataServicesMetadataNamespaceName))
                        {
                            foundErrorPayload = true;
                            break;
                        }
                    }

                    if (!foundErrorPayload)
                    {
                        errorPayload = null;
                        return false;
                    }

                    errorPayload = this.ParseErrorFragment(reader);
                    return true;
                }
            }
        }
Example #20
0
        /// <summary>
        /// Constructs an OData request body using the given settings
        /// </summary>
        /// <param name="contentType">The content type of the body</param>
        /// <param name="uri">The request uri</param>
        /// <param name="rootElement">The root payload element</param>
        /// <returns>An OData request body</returns>
        public ODataPayloadBody BuildBody(string contentType, ODataUri uri, ODataPayloadElement rootElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(contentType, "contentType");
            ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement");
            ExceptionUtilities.CheckAllRequiredDependencies(this);

            string charset = HttpUtilities.GetContentTypeCharsetOrNull(contentType);

            byte[] serializedBody      = null;
            var    batchRequestPayload = rootElement as BatchRequestPayload;

            if (batchRequestPayload != null)
            {
                string boundary;
                ExceptionUtilities.Assert(HttpUtilities.TryGetContentTypeParameter(contentType, HttpHeaders.Boundary, out boundary), "Could not find boundary in content type for batch payload. Content type was: '{0}'", contentType);
                serializedBody = this.BatchSerializer.SerializeBatchPayload(batchRequestPayload, boundary, charset);
            }
            else
            {
                IProtocolFormatStrategy strategy = this.FormatSelector.GetStrategy(contentType, uri);
                ExceptionUtilities.CheckObjectNotNull(strategy, "Strategy selector did not return a strategy for content type '{0}'", contentType);

                IPayloadSerializer serializer = strategy.GetSerializer();
                ExceptionUtilities.CheckObjectNotNull(serializer, "Strategy returned a null serializer");

                serializedBody = serializer.SerializeToBinary(rootElement, charset);
            }

            return(new ODataPayloadBody(serializedBody, rootElement));
        }
            private void VisitProperty(PropertyInstance payloadElement, ODataPayloadElement value, Action action)
            {
                ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");

                try
                {
                    var currentType = this.typeStack.Peek();
                    ExceptionUtilities.CheckObjectNotNull(currentType, "Current type should not be null");

                    var propertyInfo = currentType.GetProperty(payloadElement.Name);
                    ExceptionUtilities.CheckObjectNotNull(propertyInfo, "Could not find property '{0}' on type '{1}'", payloadElement.Name, currentType);

                    var genericCollectionType = propertyInfo.PropertyType.GetInterfaces().Where(t => t.IsGenericType()).SingleOrDefault(t => typeof(ICollection <>) == t.GetGenericTypeDefinition());
                    if (genericCollectionType != null)
                    {
                        this.typeStack.Push(genericCollectionType.GetGenericArguments()[0]);
                    }
                    else
                    {
                        this.typeStack.Push(propertyInfo.PropertyType);
                    }

                    base.VisitProperty(payloadElement, value);

                    if (action != null)
                    {
                        action();
                    }
                }
                finally
                {
                    this.typeStack.Pop();
                }
            }
        private ODataUri BuildODataUri(ODataPayloadElement payload)
        {
            var entityInstance = payload as EntityInstance;
            if (entityInstance != null)
            {
                EntityModelTypeAnnotation type = entityInstance.GetAnnotation<EntityModelTypeAnnotation>();
                ExceptionUtilities.CheckObjectNotNull(type, "Type annotation was expected");

                var entityType = ((EntityDataType)type.EntityModelType).Definition;

                // First is OK because MEST doesnt matter
                var entitySet = entityType.Model.EntityContainers.SelectMany(c => c.EntitySets).First(s => s.EntityType == entityType);
                return new ODataUri(ODataUriBuilder.EntitySet(entitySet));
            }
            var complexProperty = payload as ComplexProperty;
            if (complexProperty != null)
            {
                EntityModelTypeAnnotation type = entityInstance.GetAnnotation<EntityModelTypeAnnotation>();
                ExceptionUtilities.CheckObjectNotNull(type, "Type annotation was expected");

                var entityType = ((EntityDataType)type.EntityModelType).Definition;

                // First is OK because MEST doesnt matter
                var entitySet = entityType.Model.EntityContainers.SelectMany(c => c.EntitySets).First(s => s.EntityType == entityType);
                return new ODataUri(ODataUriBuilder.EntitySet(entitySet));
            }

            // TODO: Add support for other types
            return null;
        }
Example #23
0
        /// <summary>
        /// Annotates the given payload based on the metadata in the given uri
        /// </summary>
        /// <param name="rootElement">The payload to annotate with metadata information</param>
        /// <param name="uri">The uri that corresponds to the given payload</param>
        public void ResolveMetadata(ODataPayloadElement rootElement, ODataUri uri)
        {
            ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement");
            ExceptionUtilities.CheckArgumentNotNull(uri, "uri");

            this.InitializeMetadataStack(uri);
            this.InitialStackSize = this.MetadataStack.Count;

            rootElement.Add(new ExpectedPayloadElementTypeAnnotation()
            {
                ExpectedType = uri.GetExpectedPayloadType()
            });

            // if the uri did not contain any metadata, do nothing
            if (this.InitialStackSize > 0)
            {
                // if this is the result of service operation or action, the root element needs to have the function itself and its return type
                var serviceOperation = this.MetadataStack.OfType <Function>().FirstOrDefault();
                if (serviceOperation != null)
                {
                    rootElement.AddAnnotationIfNotExist(new FunctionAnnotation()
                    {
                        Function = serviceOperation
                    });
                    rootElement.AddAnnotationIfNotExist(new DataTypeAnnotation()
                    {
                        DataType = serviceOperation.ReturnType
                    });
                }

                this.Recurse(rootElement);
            }
        }
        /// <summary>
        /// Compares the two payload elements
        /// </summary>
        /// <param name="expected">The expected element</param>
        /// <param name="actual">The actual element</param>
        public void Compare(ODataPayloadElement expected, ODataPayloadElement actual)
        {
            var comparingVisitor = new PayloadComparingVisitor(this.BatchComparer, this.ignoreOrder, this.expectMetadataToBeComputedByConvention);

            comparingVisitor.Assert = this.Assert;
            comparingVisitor.Compare(expected, actual);
        }
        /// <summary>
        /// Called to get the expected result of the test.
        /// </summary>
        /// <param name="testConfiguration">The test configuration to use.</param>
        /// <returns>The expected result.</returns>
        protected override ReaderTestExpectedResult GetExpectedResult(ReaderTestConfiguration testConfiguration)
        {
            ReaderTestExpectedResult expectedResult = base.GetExpectedResult(testConfiguration);

            if (expectedResult == null)
            {
                IEdmModel      model          = this.GetMetadataProvider(testConfiguration);
                ReaderMetadata readerMetadata = new ReaderMetadata(model, this.PayloadElement);

                // First use the input payload as the expected result.
                ODataPayloadElement expectedResultPayloadElement = this.PayloadElement;

                // If we have an override specifically for expected result, use that instead.
                if (this.ExpectedResultPayloadElement != null)
                {
                    expectedResultPayloadElement = this.ExpectedResultPayloadElement(testConfiguration);
                }

                if (expectedResultPayloadElement.ElementType == ODataPayloadElementType.BatchRequestPayload || expectedResultPayloadElement.ElementType == ODataPayloadElementType.BatchResponsePayload)
                {
                    if (this.ExpectedResultNormalizers.Count > 0)
                    {
                        expectedResultPayloadElement = new BatchPayloadExpectedResultNormalizer(
                            testConfiguration,
                            this.ApplyExpectedResultNormalizers).Normalize(expectedResultPayloadElement);
                    }

                    IEdmModel payloadModel = this.GetMetadataProvider(testConfiguration);
                    return(new BatchReaderTestExpectedResult(this.settings.BatchExpectedResultSettings)
                    {
                        ExpectedBatchPayload = expectedResultPayloadElement,
                        PayloadModel = payloadModel,
                        ExpectedException = this.ExpectedException,
                    });
                }
                else
                {
                    expectedResultPayloadElement = this.ApplyExpectedResultNormalizers(expectedResultPayloadElement, testConfiguration);
                }

                return(new PayloadReaderTestExpectedResult(this.settings.ExpectedResultSettings)
                {
                    ExpectedPayloadElement = expectedResultPayloadElement,
                    ExpectedException = this.ExpectedException,
                    ReaderMetadata = readerMetadata,
                    IgnorePropertyOrder = this.IgnorePropertyOrder,
                });
            }
            else
            {
                PayloadReaderTestExpectedResult payloadReaderTestExpectedResult = expectedResult as PayloadReaderTestExpectedResult;
                if (payloadReaderTestExpectedResult != null && payloadReaderTestExpectedResult.ReaderMetadata == null)
                {
                    IEdmModel model = this.GetMetadataProvider(testConfiguration);
                    payloadReaderTestExpectedResult.ReaderMetadata = new ReaderMetadata(model, this.PayloadElement);
                }

                return(expectedResult);
            }
        }
Example #26
0
        private ODataPayloadElement ConvertRootObject(JsonObject jsonObject)
        {
            JsonValue toConvert;

            if (!this.TryGetSecurityPropertyValue(jsonObject, out toConvert))
            {
                toConvert = jsonObject;
            }
            else if (toConvert.JsonType == JsonValueType.JsonObject)
            {
                // If toConvert is a json object it means it has already been unwrapped of the d: wrapper.
                // This is done to update the jsonObject to be the unwrapped version of the payload.
                jsonObject = (JsonObject)toConvert;
            }

            ODataPayloadElement converted = this.ConvertValue(toConvert);

            // an untyped root-level complex instance with one property should be 'unwrapped'
            if (converted.ElementType == ODataPayloadElementType.ComplexInstance)
            {
                var complex = (ComplexInstance)converted;

                // if there are multiple properties or any type information/metadata, do not unwrap it
                if (complex.Properties.Count() == 1 && jsonObject.Properties.Count() == 1)
                {
                    converted = complex.Properties.Single();
                }
            }

            return(converted);
        }
        protected override void VisitRequestOperation(IHttpRequest operation)
        {
            var requestOperation = operation as ODataRequest;

            ExceptionUtilities.CheckObjectNotNull(requestOperation, "Operation must be request");
            ODataPayloadElement rootElement = null;
            string contentType = null;

            if (requestOperation.Body != null && requestOperation.Body.RootElement != null)
            {
                rootElement = requestOperation.Body.RootElement;
                contentType = requestOperation.GetHeaderValueIfExists(Microsoft.OData.ODataConstants.ContentTypeHeader);
            }

            if (rootElement != null)
            {
                ODataFormat format = null;
                if (contentType.Contains(MimeTypes.ApplicationJson))
                {
                    format = ODataFormat.Json;
                }

                new ExpectedPayloadFixups().Fixup(rootElement, format);
            }
        }
        /// <summary>
        /// Called to write the payload to the specified <paramref name="messageWriter"/>.
        /// </summary>
        /// <param name="messageWriter">The <see cref="ODataMessageWriterTestWrapper"/> to use for writing the payload.</param>
        /// <param name="testConfiguration">The test configuration to generate the payload for.</param>
        protected override void WritePayload(ODataMessageWriterTestWrapper messageWriter, WriterTestConfiguration testConfiguration)
        {
            Debug.Assert(this.messageStream != null, "Streaming test stream must have been created.");
            TestMessage testMessage = this.CreateInputMessageFromStream((TestStream)this.messageStream, testConfiguration, this.PayloadKind, string.Empty, this.UrlResolver);

            testMessage.SetContentType(testConfiguration.Format, this.PayloadKind);

            Exception exception = TestExceptionUtils.RunCatching(() =>
            {
                ODataMessageReaderSettings readerSettings  = this.settings.MessageReaderSettings.Clone();
                readerSettings.EnableMessageStreamDisposal = testConfiguration.MessageWriterSettings.EnableMessageStreamDisposal;

                ReaderTestConfiguration readerConfig = new ReaderTestConfiguration(
                    testConfiguration.Format,
                    readerSettings,
                    testConfiguration.IsRequest,
                    testConfiguration.Synchronous);

                IEdmModel model = this.GetMetadataProvider();
                using (ODataMessageReaderTestWrapper messageReaderWrapper = TestReaderUtils.CreateMessageReader(testMessage, model, readerConfig))
                {
                    ODataPayloadElementToObjectModelConverter payloadElementToOMConverter = new ODataPayloadElementToObjectModelConverter(!testConfiguration.IsRequest);
                    ObjectModelToPayloadElementConverter reverseConverter = new ObjectModelToPayloadElementConverter();
                    ObjectModelWriteReadStreamer streamer = new ObjectModelWriteReadStreamer();

                    this.readObject = reverseConverter.Convert(streamer.WriteMessage(messageWriter, messageReaderWrapper, this.PayloadKind, payloadElementToOMConverter.Convert(this.PayloadElement)), !testConfiguration.IsRequest);
                }
            });
        }
        private static QueryValue CreateQueryScalarValue(ODataPayloadElement payload, QueryType queryTypeToBuild)
        {
            var primitiveValue = payload as PrimitiveValue;
            var queryScalarType = queryTypeToBuild as QueryScalarType;
            ExceptionUtilities.CheckObjectNotNull(queryScalarType, "payload is a primitive type so queryType must be as well");

            return queryScalarType.CreateValue(primitiveValue.ClrValue);
        }
 /// <summary>
 /// Wrapper for recursively visiting the given element. Used with the callback property to make unit tests easier.
 /// </summary>
 /// <param name="element">The element to visit</param>
 protected override void Recurse(ODataPayloadElement element)
 {
     // only recurse if we haven't yet found an error
     if (this.expectedError == null)
     {
         base.Recurse(element);
     }
 }
Example #31
0
        /// <summary>
        /// Returns the type from the entity model type annotation for this payload element.
        /// </summary>
        /// <param name="payloadElement">The payload element to return the type for.</param>
        /// <returns>The type from the annotation or null if none was present.</returns>
        private static IEdmTypeReference GetEdmTypeFromEntityModelTypeAnnotation(ODataPayloadElement payloadElement)
        {
            Debug.Assert(payloadElement != null, "payloadElement != null");

            EntityModelTypeAnnotation typeAnnotation = payloadElement.GetAnnotation <EntityModelTypeAnnotation>();

            return(typeAnnotation == null ? null : typeAnnotation.EdmModelType);
        }
 /// <summary>
 /// Helper method for visiting properties
 /// </summary>
 /// <param name="payloadElement">The property to visit</param>
 /// <param name="value">The value of the property</param>
 protected override void VisitProperty(PropertyInstance payloadElement, ODataPayloadElement value)
 {
     using (new DelegateBasedDisposable(() => this.currentPath.Pop()))
     {
         this.currentPath.Push(payloadElement.Name);
         base.VisitProperty(payloadElement, value);
     }
 }
Example #33
0
        /// <summary>
        /// Helper method for visiting properties
        /// </summary>
        /// <param name="payloadElement">The property to visit</param>
        /// <param name="value">The value of the property</param>
        protected override void VisitProperty(PropertyInstance payloadElement, ODataPayloadElement value)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
            var property = this.MetadataStack.Peek() as MemberProperty;

            if (property != null)
            {
                ExceptionUtilities.Assert(payloadElement.Name == property.Name, "Property name mismatch");
                payloadElement.AddAnnotationIfNotExist(new MemberPropertyAnnotation()
                {
                    Property = property
                });

                try
                {
                    this.MetadataStack.Push(property.PropertyType);
                    base.VisitProperty(payloadElement, value);
                }
                finally
                {
                    this.MetadataStack.Pop();
                }
            }
            else
            {
                var navprop = this.MetadataStack.Peek() as NavigationProperty;
                if (navprop != null)
                {
                    ExceptionUtilities.Assert(payloadElement.Name == navprop.Name, "Property name mismatch");
                    try
                    {
                        this.MetadataStack.Push(this.CurrentEntitySet.GetRelatedEntitySet(navprop));
                        base.VisitProperty(payloadElement, value);
                    }
                    finally
                    {
                        this.MetadataStack.Pop();
                    }
                }
                else
                {
                    var serviceOperation = this.MetadataStack.OfType <Function>().SingleOrDefault(f => f.Name.Equals(payloadElement.Name, StringComparison.Ordinal));
                    if (payloadElement.Name.Contains('.'))
                    {
                        // if the action has a name collision with a property in the entity, it will have the <container name>.<action name> in the payload
                        // split the payloadElement.Name and get the last token which will match the function name
                        string lastToken = payloadElement.Name.Split('.').Last();
                        serviceOperation = this.MetadataStack.OfType <Function>().SingleOrDefault(f => f.Name.Equals(lastToken, StringComparison.Ordinal));
                    }

                    ExceptionUtilities.CheckObjectNotNull(serviceOperation, "Expected property, got " + this.MetadataStack.Peek().ToString());

                    // Non-entity values returned from a service operation call appear identical to member properties,
                    // with the operation name as the property name
                    base.VisitProperty(payloadElement, value);
                }
            }
        }
        /// <summary>
        /// Serializes the given root element to a binary representation
        /// </summary>
        /// <param name="rootElement">The root element, must be a primitive value</param>
        /// <param name="encodingName">Optional name of an encoding to use if it is relevant to the current format. May be null if no character-set information was known.</param>
        /// <returns>The serialized value</returns>
        public override byte[] SerializeToBinary(ODataPayloadElement rootElement, string encodingName)
        {
            ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement");
            ExceptionUtilities.Assert(rootElement.ElementType == ODataPayloadElementType.PrimitiveValue, "Only primitive values can be serialized as raw values. Type was: {0}", rootElement.ElementType);

            var value = (rootElement as PrimitiveValue).ClrValue;
            var encoding = HttpUtilities.GetEncodingOrDefault(encodingName);
            return encoding.GetBytes(this.XmlPrimitiveConverter.SerializePrimitive(value));
        }
        /// <summary>
        /// Visit the collection payload element and updates the collection name to an empty string (if it is present).
        /// </summary>
        /// <param name="payloadElement">The root of the payload element tree to visit.</param>
        /// <remarks>This method will modify the input payload element, so if there is a need to 
        /// preserve the actual input payload element it should be cloned.
        /// </remarks>
        public static ODataPayloadElement Visit(ODataPayloadElement payloadElement)
        {
            if (payloadElement != null)
            {
                new RemoveCollectionNameAnnotationForCollectionPayloadElementVisitor().Recurse(payloadElement);
            }

            return payloadElement;
        }
        /// <summary>
        /// Visit the payload element and removes UriString value from ExpandedLinks.
        /// </summary>
        /// <param name="payloadElement">The root of the payload element tree to visit.</param>
        /// <remarks>This method will modify the input payload element, so if there is a need to 
        /// preserve the actual input payload element it should be cloned.
        /// </remarks>
        public static ODataPayloadElement Visit(ODataPayloadElement payloadElement)
        {
            if (payloadElement != null)
            {
                new RemoveExpandedLinkUriStringVisitor().Recurse(payloadElement);
            }

            return payloadElement;
        }
        private void RunMessageSizeLimitTests(
            IEnumerable <ReaderTestConfiguration> testConfigurations,
            EdmModel model,
            ODataPayloadElement payload,
            MessageSizeLimitTestCase[] testCases,
            Func <ReaderTestConfiguration, bool> skipTestConfigurationFunc = null)
        {
            var transformScope = this.Settings.PayloadTransformFactory.EmptyScope();

            using (transformScope.Apply())
            {
                this.CombinatorialEngineProvider.RunCombinations(
                    testCases,
                    testConfigurations,
                    (testCase, testConfiguration) =>
                {
                    int size = -1;
                    if (testConfiguration.Format == ODataFormat.Atom && testCase.AtomSizes != null)
                    {
                        size = testConfiguration.IsRequest ? testCase.AtomSizes.RequestSize : testCase.AtomSizes.ResponseSize;
                    }
                    else if (testConfiguration.Format == ODataFormat.Json && testCase.JsonLightSizes != null)
                    {
                        size = testConfiguration.IsRequest ? testCase.JsonLightSizes.RequestSize : testCase.JsonLightSizes.ResponseSize;
                    }
                    else if (testCase.RawSizes != null)
                    {
                        size = testConfiguration.IsRequest ? testCase.RawSizes.RequestSize : testCase.RawSizes.ResponseSize;
                    }

                    int maxSize = testCase.MaxMessageSize >= 0 ? testCase.MaxMessageSize : 1024 * 1024;
                    ExpectedException expectedException = size < 0
                            ? null
                            : ODataExpectedExceptions.ODataException("MessageStreamWrappingStream_ByteLimitExceeded", size.ToString(), maxSize.ToString());

                    var testDescriptor = new PayloadReaderTestDescriptor(this.Settings)
                    {
                        PayloadEdmModel             = model,
                        PayloadElement              = payload.DeepCopy(),
                        ExpectedException           = expectedException,
                        SkipTestConfiguration       = skipTestConfigurationFunc,
                        ApplyPayloadTransformations = false,
                    };

                    testDescriptor.ExpectedResultNormalizers.Add(
                        tc => (Func <ODataPayloadElement, ODataPayloadElement>)null);

                    if (testCase.MaxMessageSize > 0)
                    {
                        testConfiguration = new ReaderTestConfiguration(testConfiguration);
                        testConfiguration.MessageReaderSettings.MessageQuotas.MaxReceivedMessageSize = testCase.MaxMessageSize;
                    }

                    testDescriptor.RunTest(testConfiguration);
                });
            }
        }
        /// <summary>
        /// Visit the collection payload element and updates the collection name to an empty string (if it is present).
        /// </summary>
        /// <param name="payloadElement">The root of the payload element tree to visit.</param>
        /// <remarks>This method will modify the input payload element, so if there is a need to
        /// preserve the actual input payload element it should be cloned.
        /// </remarks>
        public static ODataPayloadElement Visit(ODataPayloadElement payloadElement)
        {
            if (payloadElement != null)
            {
                new EmptyCollectionNameForCollectionPayloadElementVisitor().Recurse(payloadElement);
            }

            return(payloadElement);
        }
        /// <summary>
        /// Prints an entity graph
        /// </summary>
        /// <param name="rootElement">The root element of the payload</param>
        /// <returns> an entity graph to visualize</returns>
        public string PrettyPrint(ODataPayloadElement rootElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement");
            ExceptionUtilities.CheckAllRequiredDependencies(this);

            this.builder = new StringBuilder();
            this.currentDepth = 0;
            this.Recurse(rootElement);
            return this.builder.ToString();
        }
        /// <summary>
        /// Validates a payload with the given root element against the given expected value
        /// </summary>
        /// <param name="rootElement">The root element of the payload</param>
        /// <param name="expectedValue">The expected value</param>
        public void Validate(ODataPayloadElement rootElement, QueryValue expectedValue)
        {
            ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement");
            ExceptionUtilities.CheckArgumentNotNull(expectedValue, "expectedValue");
            ExceptionUtilities.CheckAllRequiredDependencies(this);

            this.Assert.IsNull(expectedValue.EvaluationError, string.Format(CultureInfo.InvariantCulture, "Query evaluation error: {0}", expectedValue.EvaluationError));

            var visitor = new PayloadDataValidatingVisitor(this);
            visitor.Validate(rootElement, expectedValue);
        }
        /// <summary>
        /// Annotates payload with version as appropriate.
        /// </summary>
        /// <param name="payloadElement">The root of the payload to annotate.</param>
        /// <param name="version">The format version to annotate with.</param>
        /// <param name="requestPayload">true if the payload should represent a request payload, false if it's a response payload.</param>
        public static void AnnotateVerboseJson(ODataPayloadElement payloadElement, DataServiceProtocolVersion version, bool requestPayload)
        {
            PayloadFormatVersionAnnotatingVisitor visitor = new PayloadFormatVersionAnnotatingVisitor(version, requestPayload);
            visitor.Recurse(payloadElement);

            // Add the version/response annotation to the root if it's a response.
            if (!requestPayload && !(payloadElement is ODataErrorPayload))
            {
                payloadElement.SetAnnotation(new PayloadFormatVersionAnnotation() { Version = version, Response = true, ResponseWrapper = true });
            }
        }
        /// <summary>
        /// Converts the given payload element into an Json representation.
        /// </summary>
        /// <param name="rootElement">The root payload element to convert.</param>        
        /// <returns>The Json representation of the payload.</returns>
        public string ConvertToJson(ODataPayloadElement rootElement)
        {
            StringBuilder builder = new StringBuilder();
            using (StringWriter strWriter = new StringWriter(builder, CultureInfo.CurrentCulture))
            {
                this.writer = new JsonWriter(strWriter);
                this.Serialize(rootElement);
                this.Dispose();
            }

            return builder.ToString();
        }
 public byte[] SerializeToBinary(ODataPayloadElement rootElement, string encodingName)
 {
     string json = this.payloadElementToStringConverter(rootElement);
     
     var encoding = HttpUtilities.GetEncodingOrDefault(encodingName);
     using (var writer = new StreamWriter(new MemoryStream(), encoding))
     {
         writer.Write(json);
         writer.Flush();
         return ((MemoryStream)writer.BaseStream).ToArray();
     }
 }
 /// <summary>
 /// Write the <paramref name="element"/> payload element to the <paramref name="writer"/> OData writer.
 /// </summary>
 /// <param name="writer">The OData writer to write to.</param>
 /// <param name="element">The element to write.</param>
 public void WritePayload(ODataWriter writer, ODataPayloadElement element)
 {
     this.writer = writer;
     try
     {
         base.Recurse(element);
         this.writer.Flush();
     }
     finally
     {
         this.writer = null;
     }
 }
        /// <summary>
        /// The base for recursing a property to write a property using ODataMessageWriter
        /// </summary>
        /// <param name="writer">The message writer to use for writing the property</param>
        /// <param name="payload">The payload to be written as a property</param>
        public void WriteProperty(ODataMessageWriter writer, ODataPayloadElement payload)
        {
            this.writer = writer;
            payload.Accept(this);
            ExceptionUtilities.CheckObjectNotNull(this.odataProperties, "ODataProperty cannot be null");
            ExceptionUtilities.Assert(this.odataProperties.Count == 1, "There can be only one property left when writing the result");
#if SILVERLIGHT 
            this.writer.WriteProperty(this.odataProperties.First());
#else
            this.writer.WritePropertyAsync(this.odataProperties.First()).Wait();
#endif
            this.odataProperties.Clear();
        }
 private string AtomFixup(ODataPayloadElement payload)
 {
     // We have removed all the annotations except for Self Link which also we can remove since it shows up as ID and 
     // convert primitives to expected JSON representations
     // TODO: Remove visitor
     payload.Accept(new ODataPayloadElementNullIDVisitor());
     payload.Accept(new AddExpandedLinkMetadata());
     payload.Accept(new ODataPayloadElementAddDefaultAtomMetadata());
     payload.Accept(new ODataPayloadElementNullTypenameVisitor());
     payload.Accept(new NullStringTypenameFixup());
     payload.Accept(new RemoveAnnotations());
     return MimeTypes.ApplicationAtomXml;
 }
        /// <summary>
        /// Calculates the Protocol Version based on the payloadElement provided
        /// </summary>
        /// <param name="payloadElement">Payload Element</param>
        /// <param name="contentType">Content Type</param>
        /// <param name="maxProtocolVersion">The max protocol version</param>
        /// <param name="maxDataServiceVersion">The max data service version of the request</param>
        /// <returns>Data Service protocol version</returns>
        public DataServiceProtocolVersion CalculateProtocolVersion(ODataPayloadElement payloadElement, string contentType, DataServiceProtocolVersion maxProtocolVersion, DataServiceProtocolVersion maxDataServiceVersion)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
            ExceptionUtilities.CheckArgumentNotNull(contentType, "contentType");
            ExceptionUtilities.Assert(maxProtocolVersion != DataServiceProtocolVersion.Unspecified, "Max protocol version cannot be unspecified");

            this.responseContentType = contentType;
            this.version = DataServiceProtocolVersion.V4;
            this.currentMaxProtocolVersion = maxProtocolVersion;
            this.currentMaxDataServiceVersion = maxDataServiceVersion;

            payloadElement.Accept(this);
            return this.version;
        }
 private string JsonFixup(ODataPayloadElement payload)
 {
     // We have removed all the annotations except for Self Link which also we can remove since it shows up as ID and 
     // convert primitives to expected JSON representations
     payload.Accept(new ODataPayloadJsonNormalizer());
     payload.Accept(new RemoveFeedIDFixup());
     payload.Accept(new ReorderProperties());
     payload.Accept(new ODataPayloadElementNullTypenameVisitor());
     payload.Accept(new RemoveMLEAnnotation());
     payload.Accept(new RemoveAnnotations());
     payload.Accept(new JsonSelfLinkToEditLinkFixup());
     payload.Accept(new RemoveExpandedLinkUriStringVisitor());
     return MimeTypes.ApplicationJson;
 }
        /// <summary>
        /// Converts the given payload into a series of named value pairs
        /// </summary>
        /// <param name="payload">The payload to convert</param>
        /// <returns>The named-value pairs represented by the given payload</returns>
        public IEnumerable<NamedValue> ConvertToNamedValues(ODataPayloadElement payload)
        {
            ExceptionUtilities.CheckArgumentNotNull(payload, "payload");
            ExceptionUtilities.Assert(this.currentPath.Count == 0, "Stack was not empty");
            ExceptionUtilities.CheckAllRequiredDependencies(this);
            
            this.orderedNames.Clear();
            this.valuesByName.Clear();
            
            this.Recurse(payload);

            ExceptionUtilities.Assert(this.orderedNames.Count == this.valuesByName.Count, "Number of names does not match number of values");
            return this.orderedNames.Select(n => this.valuesByName[n]);
        }
        /// <summary>
        /// Fixes up payload based on format
        /// </summary>
        /// <param name="payloadElement">The payload element to fix.</param>
        /// <param name="format">The format to fix up for.</param>
        public string Fixup(ODataPayloadElement payload, ODataFormat format)
        {
            if (format == ODataFormat.Json)
            {
                return this.JsonFixup(payload);
            }
            else if (format == ODataFormat.Atom)
            {
                return this.AtomFixup(payload);
            }
            else if (format == null && (payload is BatchRequestPayload || payload is BatchResponsePayload))
            {
                return this.DefaultFixup(payload);
            }

            return MimeTypes.ApplicationXml;
        }
        /// <summary>
        /// Serializes the given root element to a binary representation
        /// </summary>
        /// <param name="rootElement">The root element, must be a primitive value with either a null or binary value</param>
        /// <param name="encodingName">Optional name of an encoding to use if it is relevant to the current format. May be null if no character-set information was known.</param>
        /// <returns>The serialized value</returns>
        public override byte[] SerializeToBinary(ODataPayloadElement rootElement, string encodingName)
        {
            ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement");
            ExceptionUtilities.Assert(rootElement.ElementType == ODataPayloadElementType.PrimitiveValue, "Only primitive values can be serialized as raw values. Type was: {0}", rootElement.ElementType);

            var value = (rootElement as PrimitiveValue).ClrValue;

            if (value == null)
            {
                return new byte[0];
            }

            var binary = value as byte[];
            ExceptionUtilities.CheckObjectNotNull(binary, "Payload element was not a binary value");

            return binary;
        }
        /// <summary>
        /// Serializes the given root element to a binary representation
        /// </summary>
        /// <param name="rootElement">The root element</param>
        /// <param name="encodingName">Optional name of an encoding to use if it is relevant to the current format</param>
        /// <returns>The serialized value</returns>
        public override byte[] SerializeToBinary(ODataPayloadElement rootElement, string encodingName)
        {
            ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement");
            ExceptionUtilities.Assert(rootElement.ElementType == ODataPayloadElementType.ComplexInstance, "Only complex instances form values can be serialized as html forms. Type was: {0}", rootElement.ElementType);

            var complexInstance = (ComplexInstance)rootElement;

            var queryOpions = new List<KeyValuePair<string, string>>();

            foreach (var property in complexInstance.Properties)
            {
                string value;
                if (property.ElementType == ODataPayloadElementType.PrimitiveProperty)
                {
                    value = this.LiteralConverter.SerializePrimitive(((PrimitiveProperty)property).Value.ClrValue);
                }
                else if (property.ElementType == ODataPayloadElementType.ComplexProperty)
                {
                    value = this.JsonConverter.ConvertToJson(((ComplexProperty)property).Value);
                }
                else if (property.ElementType == ODataPayloadElementType.PrimitiveMultiValueProperty)
                {
                    value = this.JsonConverter.ConvertToJson(((PrimitiveMultiValueProperty)property).Value);
                }
                else
                {
                    ExceptionUtilities.Assert(property.ElementType == ODataPayloadElementType.ComplexMultiValueProperty, "Only primitive, complex, and multi-value properties are supported");
                    value = this.JsonConverter.ConvertToJson(((ComplexMultiValueProperty)property).Value);
                }

                var option = new KeyValuePair<string, string>(property.Name, value);
                queryOpions.Add(option);
            }

            StringBuilder builder = new StringBuilder();
            UriHelpers.ConcatenateQueryOptions(builder, queryOpions);

            var encoding = HttpUtilities.GetEncodingOrDefault(encodingName);
            return encoding.GetBytes(builder.ToString());
        }
        /// <summary>
        /// Deserializes the given html payload a error payload or returns null
        /// </summary>
        /// <param name="serialized">The payload that was sent over HTTP</param>
        /// <param name="encodingName">Optional name of an encoding to use if it is relevant to the current format. May be null if no character-set information was known.</param>
        /// <param name="errorPayload">Error payload that is found</param>
        /// <returns>True if it finds and error, false if not</returns>
        public bool TryDeserializeErrorPayload(byte[] serialized, string encodingName, out ODataPayloadElement errorPayload)
        {
            Encoding encoding = HttpUtilities.GetEncodingOrDefault(encodingName);
            string payload = encoding.GetString(serialized, 0, serialized.Length);
            errorPayload = null;

            // <html>
            //  <body>
            //      <div id="content">
            //          <p class="heading1">Request Error</p>
            //           <p>Error message goes here</p>
            //           <p>Stack trace goes here</p>
            //      </div>
            //  <body>
            // </html>
            // The server encountered an error processing the request. The exception message is '
            // trim the html to only contain the <body> </body> section of the HTML.
            if (payload.Contains("<html"))
            {
                errorPayload = new HtmlErrorPayload();
                var htmlPayload = errorPayload as HtmlErrorPayload;

                payload = payload.Substring(payload.IndexOf("<body>", StringComparison.OrdinalIgnoreCase)).Replace("</html>", string.Empty);
                payload = payload.Replace("The server encountered an error processing the request. The exception message is '", string.Empty);
                payload = payload.Replace("'. See server logs for more details. The exception stack trace is: ", string.Empty);
                XDocument errorDocument = XDocument.Parse(payload);
                XElement body = errorDocument.Element(XName.Get("body"));
                XElement errorContent = body.Element(XName.Get("div"));
                XElement errorMessage = errorContent.Elements(XName.Get("p")).Skip(1).First();
                XElement stackTrace = errorContent.Elements(XName.Get("p")).Skip(2).First();

                htmlPayload.Message = errorMessage.Value;
                htmlPayload.StackTrace = stackTrace.Value;

                return true;
            }

            return false;
        }
        public byte[] SerializeToBinary(ODataPayloadElement rootElement, string encodingName)
        {
            bool omitDeclaration = false;

            SerializationEncodingNameAnnotation encodingNameAnnotation = (SerializationEncodingNameAnnotation)rootElement.GetAnnotation(typeof(SerializationEncodingNameAnnotation));
            if (encodingNameAnnotation != null)
            {
                encodingName = encodingNameAnnotation.EncodingName;
                omitDeclaration = encodingNameAnnotation.OmitDeclaration;
            }

            var encoding = HttpUtilities.GetEncodingOrDefault(encodingName);

            XDocument document = new XDocument(this.payloadElementConverter.ConvertToXml(rootElement));

            if (!omitDeclaration)
            {
                document.Declaration = new XDeclaration("1.0", encoding.WebName, "yes");
            }

            // settings taken from server
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Encoding = encoding;
            settings.OmitXmlDeclaration = omitDeclaration;
            settings.Indent = true;
            settings.NewLineHandling = NewLineHandling.Entitize;
            settings.NamespaceHandling = NamespaceHandling.OmitDuplicates;

            using (MemoryStream stream = new MemoryStream())
            {
                using (XmlWriter writer = XmlWriter.Create(stream, settings))
                {
                    document.Save(writer);
                    writer.Flush();

                    return stream.ToArray();
                }
            }
        }
 /// <summary>
 /// Remove duplicate annotations that might be added
 /// </summary>
 /// <param name="payload">payload to remove duplicate annotations for</param>
 public static void RemoveEPMDuplicationAnnotations(ODataPayloadElement payload)
 {
     ODataLibPayloadElementComparer comparer = new ODataLibPayloadElementComparer();
     for (int i = 0; i < payload.Annotations.Count; i++)
     {
         var epmAnn1 = payload.Annotations[i] as XmlTreeAnnotation;
         if (epmAnn1 == null)
         {
             continue;
         }
         for (int j = i + 1; j < payload.Annotations.Count; j++)
         {
             var epmAnn2 = payload.Annotations[j] as XmlTreeAnnotation;
             if (epmAnn2 == null)
             {
                 continue;
             }
             if (epmAnn1.LocalName == epmAnn2.LocalName && epmAnn1.NamespaceName == epmAnn2.NamespaceName)
             {
                 payload.Annotations.RemoveAt(j);
             }
         }
     }
 }
        /// <summary>
        /// Annotates the given payload based on the metadata in the given uri
        /// </summary>
        /// <param name="rootElement">The payload to annotate with metadata information</param>
        /// <param name="uri">The uri that corresponds to the given payload</param>
        public void ResolveMetadata(ODataPayloadElement rootElement, ODataUri uri)
        {
            ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement");
            ExceptionUtilities.CheckArgumentNotNull(uri, "uri");

            this.InitializeMetadataStack(uri);
            this.InitialStackSize = this.MetadataStack.Count;

            rootElement.Add(new ExpectedPayloadElementTypeAnnotation() { ExpectedType = uri.GetExpectedPayloadType() });

            // if the uri did not contain any metadata, do nothing
            if (this.InitialStackSize > 0)
            {
                // if this is the result of service operation or action, the root element needs to have the function itself and its return type
                var serviceOperation = this.MetadataStack.OfType<Function>().FirstOrDefault();
                if (serviceOperation != null)
                {
                    rootElement.AddAnnotationIfNotExist(new FunctionAnnotation() { Function = serviceOperation });
                    rootElement.AddAnnotationIfNotExist(new DataTypeAnnotation() { DataType = serviceOperation.ReturnType });
                }

                this.Recurse(rootElement);
            }
        }
        /// <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);
        }
 /// <summary>
 /// Normalizes the payload for WCF DS Server mode.
 /// </summary>
 /// <param name="payloadElement">The payload element to normalize.</param>
 /// <param name="format">The format ot use.</param>
 /// <returns>The normalized payload element.</returns>
 public static ODataPayloadElement Normalize(ODataFormat format, EdmModel payloadEdmModel, ODataPayloadElement payloadElement)
 {
     new WcfDsServerPayloadElementNormalizer(format, payloadEdmModel).Recurse(payloadElement);
     return payloadElement;
 }
 /// <summary>
 /// Visit the payload element and replace null error messages.
 /// </summary>
 /// <param name="payloadElement">The root of the payload element tree to visit.</param>
 /// <returns>The <paramref name="payloadElement"/> after it has been visited.</returns>
 public static ODataPayloadElement Visit(ODataPayloadElement payloadElement)
 {
     new ErrorMessageNormalizer().Recurse(payloadElement);
     return payloadElement;
 }
        private static ODataPayloadElement ConvertToStringPayloadElement(ODataPayloadElement binaryPayload)
        {
            Debug.Assert(binaryPayload != null && binaryPayload.ElementType == ODataPayloadElementType.PrimitiveValue, "Expected non-null, primitive value as payload");

            PrimitiveValue primitiveValue = (PrimitiveValue)binaryPayload;
            Debug.Assert(primitiveValue.ClrValue.GetType() == typeof(byte[]), "Only expect byte[] primitive values.");

            byte[] bytes = (byte[])primitiveValue.ClrValue;

            return PayloadBuilder.PrimitiveValue(System.Text.Encoding.UTF8.GetString(bytes, 0, bytes.Length));
        }