Ejemplo n.º 1
0
        private void TestMaterialization <T>(string content, string contentType, Action <MaterializeAtom> testAction, ProjectionPlan plan = null)
        {
            content = content.Replace("##BASEURI##", ServiceUri);

            using (MaterializeAtom materializer = CreateMaterializer <T>(content, contentType, plan))
            {
                testAction(materializer);
            }
        }
Ejemplo n.º 2
0
        public void MaterializeGeographyInEntry()
        {
            XElement xel = XElement.Parse(@"<?xml version=""1.0"" encoding=""utf-8"" standalone=""yes""?>
<feed xmlns:d=""http://docs.oasis-open.org/odata/ns/data"" xmlns:m=""http://docs.oasis-open.org/odata/ns/metadata"" xmlns=""http://www.w3.org/2005/Atom"" xmlns:gml=""http://www.opengis.net/gml"">
<title type=""text"">Entities</title>
<updated>2010-01-27T18:06:26Z</updated>
<link rel=""self"" title=""Entities"" href=""Entities"" />
<entry>
    <id>http://localhost/TheTest/Entities(16584)</id>
    <title type=""text""></title>
    <updated>2009-09-30T01:44:35Z</updated>
    <author>
        <name>Foo</name>
    </author>
    <category term=""#AstoriaUnitTests.Tests.MaterializerUnitTests.SpatialEntity"" scheme=""http://docs.oasis-open.org/odata/ns/scheme"" />
    <content type=""application/xml"">
        <m:properties>
            <d:ID m:type=""Edm.Int32"">16584</d:ID>
            <d:BaseGeography m:type=""Edm.Geography"">
                    <gml:Point srsName=""http://www.opengis.net/def/crs/EPSG/0/4326"">
                        <gml:pos>49.234 -86.555</gml:pos>
                    </gml:Point>
            </d:BaseGeography>
            <d:GeoPoint m:type=""Edm.GeographyPoint"">
                    <gml:Point srsName=""http://www.opengis.net/def/crs/EPSG/0/4326"">
                        <gml:pos>45.256 -71.92</gml:pos>
                    </gml:Point>
            </d:GeoPoint>
            <d:GeoLine m:type=""Edm.GeographyPoint"">
                    <gml:LineString srsName=""http://www.opengis.net/def/crs/EPSG/0/4326"">
                        <gml:pos>45.256 -71.92</gml:pos>
                        <gml:pos>45.111 -71.222</gml:pos>
                    </gml:LineString>
            </d:GeoLine>
            <d:Data m:type=""Edm.Int32"">123</d:Data>
        </m:properties>
    </content>
</entry>
</feed>");

            MaterializeAtom m = CreateMaterializer <SpatialEntity>(new Uri("http://localhost/TheTest/Entities"), xel.ToString(), TestConstants.MimeApplicationAtom, ODataPayloadKind.Feed);

            Assert.IsTrue(m.MoveNext());
            Assert.IsNotNull(m.Current);

            SpatialEntity entity = (SpatialEntity)m.Current;

            Assert.AreEqual(16584, entity.ID);
            Assert.AreEqual(123.0, entity.Data);

            entity.BaseGeography.VerifyAsPoint(new PositionData(49.234, -86.555));
            entity.GeoPoint.VerifyAsPoint(new PositionData(45.256, -71.92));
            entity.GeoLine.VerifyAsLineString(new PositionData(45.256, -71.92), new PositionData(45.111, -71.222));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Returns the response for the request.
        /// </summary>
        /// <param name="results">materialized results for the request.</param>
        /// <param name="elementType">element type of the results.</param>
        /// <returns>returns the instance of QueryOperationResponse containing the response.</returns>
        internal QueryOperationResponse GetResponseWithType(MaterializeAtom results, Type elementType)
        {
            if (this.responseMessage != null)
            {
                HeaderCollection       headers  = new HeaderCollection(this.responseMessage);
                QueryOperationResponse response = QueryOperationResponse.GetInstance(elementType, headers, this.ServiceRequest, results);
                response.StatusCode = (int)this.responseMessage.StatusCode;
                return(response);
            }

            return(null);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Returns the response for the request.
        /// </summary>
        /// <param name="results">materialized results for the request.</param>
        /// <typeparam name="TElement">element type of the results.</typeparam>
        /// <returns>returns the instance of QueryOperationResponse containing the response.</returns>
        internal QueryOperationResponse <TElement> GetResponse <TElement>(MaterializeAtom results)
        {
            if (this.responseMessage != null)
            {
                HeaderCollection headers = new HeaderCollection(this.responseMessage);
                QueryOperationResponse <TElement> response = new QueryOperationResponse <TElement>(headers, this.ServiceRequest, results);
                response.StatusCode = (int)this.responseMessage.StatusCode;
                return(response);
            }

            return(null);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Create a parser token from xml feed
        /// </summary>
        /// <param name="reader">The xml reader</param>
        /// <remarks>The reader is expected to be placed at the beginning of the element, and after this method call, the reader will be placed
        /// at the EndElement, such that the next Element will be read in the next Read call.</remarks>
        /// <returns>token</returns>
        internal virtual PrimitiveParserToken TokenizeFromXml(XmlReader reader)
        {
            Debug.Assert(reader.NodeType == XmlNodeType.Element, "Reader at element");
            string elementString = MaterializeAtom.ReadElementString(reader, true);

            if (elementString != null)
            {
                return(new TextPrimitiveParserToken(elementString));
            }

            return(null);
        }
Ejemplo n.º 6
0
        public void TestReadNullSpatialProperty()
        {
            foreach (bool useBaseGeography in new bool[] { true, false })
            {
                string typeName = useBaseGeography ? "Edm.Geography" : "Edm.GeographyPoint";

                XElement xel = XElement.Parse(@"<?xml version=""1.0"" encoding=""utf-8"" standalone=""yes""?>
            <m:value xmlns:d=""http://docs.oasis-open.org/odata/ns/data"" xmlns:m=""http://docs.oasis-open.org/odata/ns/metadata"" xmlns:gml=""http://www.opengis.net/gml"" m:null=""true"" m:type=""" + typeName + @""">
            </m:value>");

                MaterializeAtom m = CreateMaterializer <GeographyPoint>(new Uri("http://localhost/TheTest/Entities"), xel.ToString(), TestConstants.MimeApplicationXml, ODataPayloadKind.Property);
                Assert.IsTrue(m.MoveNext());
                Assert.IsNull(m.Current);
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// loading a property from a response
        /// </summary>
        /// <returns>QueryOperationResponse instance containing information about the response.</returns>
        internal QueryOperationResponse LoadProperty()
        {
            MaterializeAtom results = null;

            DataServiceContext context = (DataServiceContext)this.Source;

            ClientEdmModel       model = context.Model;
            ClientTypeAnnotation type  = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(this.entity.GetType()));

            Debug.Assert(type.IsEntityType, "must be entity type to be contained");

            EntityDescriptor box = context.GetEntityDescriptor(this.entity);

            if (EntityStates.Added == box.State)
            {
                throw Error.InvalidOperation(Strings.Context_NoLoadWithInsertEnd);
            }

            ClientPropertyAnnotation property = type.GetProperty(this.propertyName, UndeclaredPropertyBehavior.ThrowException);
            Type elementType = property.EntityCollectionItemType ?? property.NullablePropertyType;

            try
            {
                if (type.MediaDataMember == property)
                {
                    results = this.ReadPropertyFromRawData(property);
                }
                else
                {
                    results = this.ReadPropertyFromAtom(property);
                }

                return(this.GetResponseWithType(results, elementType));
            }
            catch (InvalidOperationException ex)
            {
                QueryOperationResponse response = this.GetResponseWithType(results, elementType);
                if (response != null)
                {
                    response.Error = ex;
                    throw new DataServiceQueryException(Strings.DataServiceException_GeneralError, ex, response);
                }

                throw;
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Processes the result for successful request and produces the actual result of the request.
        /// </summary>
        /// <typeparam name="TElement">Element type of the result.</typeparam>
        /// <param name="plan">The plan to use for the projection, if available in precompiled form.</param>
        /// <returns>A instance of QueryResponseResult created on top of of the request.</returns>
        internal QueryOperationResponse <TElement> ProcessResult <TElement>(ProjectionPlan plan)
        {
            Debug.Assert(this.responseInfo != null, "The request didn't complete yet, we don't have a response info for it.");
            MaterializeAtom materializeAtom = this.CreateMaterializer(plan, this.ServiceRequest.PayloadKind);
            var             response        = this.GetResponse <TElement>(materializeAtom);

            // When query feed, the instance annotation can be materialized only when enumerating the feed.
            // So we register this action which will be called when enumerating the feed.
            materializeAtom.SetInstanceAnnotations = (instanceAnnotations) =>
            {
                if (!this.responseInfo.Context.InstanceAnnotations.ContainsKey(response) &&
                    instanceAnnotations != null && instanceAnnotations.Count > 0)
                {
                    this.responseInfo.Context.InstanceAnnotations.Add(response, instanceAnnotations);
                }
            };
            return(response);
        }
Ejemplo n.º 9
0
        private void TestMaterializeGeographyTopLevel(bool useBaseGeography)
        {
            string typeName = useBaseGeography ? "Edm.Geography" : "Edm.GeographyPoint";

            XElement xel = XElement.Parse(@"<?xml version=""1.0"" encoding=""utf-8"" standalone=""yes""?>
            <m:value xmlns:d=""http://docs.oasis-open.org/odata/ns/data"" xmlns:m=""http://docs.oasis-open.org/odata/ns/metadata"" xmlns:gml=""http://www.opengis.net/gml"" m:type=""" + typeName + @""">
                    <gml:Point srsName=""http://www.opengis.net/def/crs/EPSG/0/4326"">
                        <gml:pos>45.256 -71.92</gml:pos>
                    </gml:Point>
            </m:value>");

            MaterializeAtom m = CreateMaterializer <GeographyPoint>(new Uri("http://localhost/TheTest/Entities"), xel.ToString(), TestConstants.MimeApplicationXml, ODataPayloadKind.Property);

            Assert.IsTrue(m.MoveNext());
            Assert.IsNotNull(m.Current);

            GeographyPoint p = m.Current as GeographyPoint;

            Assert.IsNotNull(p);
            Assert.AreEqual(GeographyFactory.Point(45.256, -71.92).Build(), p);
        }
Ejemplo n.º 10
0
 /// <summary>
 /// constructor
 /// </summary>
 /// <param name="headers">HTTP headers</param>
 /// <param name="query">original query</param>
 /// <param name="results">retrieved objects</param>
 internal QueryOperationResponse(HeaderCollection headers, DataServiceRequest query, MaterializeAtom results)
     : base(headers)
 {
     this.query   = query;
     this.results = results;
 }
Ejemplo n.º 11
0
        internal static QueryOperationResponse GetInstance(Type elementType, HeaderCollection headers, DataServiceRequest query, MaterializeAtom results)
        {
            Type genericType = typeof(QueryOperationResponse <>).MakeGenericType(elementType);

#if !PORTABLELIB
            return((QueryOperationResponse)Activator.CreateInstance(
                       genericType,
                       BindingFlags.CreateInstance | BindingFlags.NonPublic | BindingFlags.Instance,
                       null,
                       new object[] { headers, query, results },
                       System.Globalization.CultureInfo.InvariantCulture));
#else
            ConstructorInfo info = genericType.GetInstanceConstructors(false /*isPublic*/).Single();
            return((QueryOperationResponse)Util.ConstructorInvoke(info, new object[] { headers, query, results }));
#endif
        }
 /// <summary>
 /// constructor
 /// </summary>
 /// <param name="headers">HTTP headers</param>
 /// <param name="query">original query</param>
 /// <param name="results">retrieved objects</param>
 internal QueryOperationResponse(HeaderCollection headers, DataServiceRequest query, MaterializeAtom results)
     : base(headers, query, results)
 {
 }
Ejemplo n.º 13
0
        /// <summary>
        /// Load property data form a raw response
        /// </summary>
        /// <param name="property">The property being loaded</param>
        /// <returns>property values as IEnumerable.</returns>
        private MaterializeAtom ReadPropertyFromRawData(ClientPropertyAnnotation property)
        {
            DataServiceContext context = (DataServiceContext)this.Source;

            bool merging = context.ApplyingChanges;

            try
            {
                context.ApplyingChanges = true;

                // if this is the data property for a media entry, what comes back
                // is the raw value (no markup)
                string   mimeType    = null;
                Encoding encoding    = null;
                Type     elementType = property.EntityCollectionItemType ?? property.NullablePropertyType;
                IList    results     = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(elementType));
                ContentTypeUtil.ReadContentType(this.ContentType, out mimeType, out encoding);

                using (Stream responseStream = this.GetResponseStream())
                {
                    // special case byte[], and for everything else let std conversion kick-in
                    if (property.PropertyType == typeof(byte[]))
                    {
                        int    total  = checked ((int)this.ContentLength);
                        byte[] buffer = null;
                        if (total >= 0)
                        {
                            buffer = LoadPropertyResult.ReadByteArrayWithContentLength(responseStream, total);
                        }
                        else
                        {
                            buffer = LoadPropertyResult.ReadByteArrayChunked(responseStream);
                        }

                        results.Add(buffer);

                        property.SetValue(this.entity, buffer, this.propertyName, false);
                    }
                    else
                    {
                        // responseStream will disposed, StreamReader doesn't need to dispose of it.
                        StreamReader reader         = new StreamReader(responseStream, encoding);
                        object       convertedValue = property.PropertyType == typeof(string) ?
                                                      reader.ReadToEnd() :
                                                      ClientConvert.ChangeType(reader.ReadToEnd(), property.PropertyType);
                        results.Add(convertedValue);

                        property.SetValue(this.entity, convertedValue, this.propertyName, false);
                    }
                }

                if (property.MimeTypeProperty != null)
                {
                    // an implication of this 3rd-arg-null is that mime type properties cannot be open props
                    property.MimeTypeProperty.SetValue(this.entity, mimeType, null, false);
                }

                return(MaterializeAtom.CreateWrapper(context, results));
            }
            finally
            {
                context.ApplyingChanges = merging;
            }
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Load property data from an ATOM response
        /// </summary>
        /// <param name="property">The property being loaded</param>
        /// <returns>property values as IEnumerable.</returns>
        private MaterializeAtom ReadPropertyFromAtom(ClientPropertyAnnotation property)
        {
            DataServiceContext context = (DataServiceContext)this.Source;
            bool merging = context.ApplyingChanges;

            try
            {
                context.ApplyingChanges = true;

                // store the results so that they can be there in the response body.
                Type  elementType = property.IsEntityCollection ? property.EntityCollectionItemType : property.NullablePropertyType;
                IList results     = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(elementType));

                DataServiceQueryContinuation continuation = null;

                // elementType.ElementType has Nullable stripped away, use nestedType for materializer
                using (MaterializeAtom materializer = this.GetMaterializer(this.plan))
                {
                    Debug.Assert(materializer != null, "materializer != null -- otherwise GetMaterializer() returned null rather than empty");

                    // when SetLink to null, we cannot get materializer because have no-content response.
                    if (materializer.IsNoContentResponse() &&
                        property.GetValue(entity) != null &&
                        context.MergeOption != MergeOption.AppendOnly &&
                        context.MergeOption != MergeOption.NoTracking)
                    {
                        property.SetValue(this.entity, null, propertyName, false);
                    }
                    else
                    {
                        foreach (object child in materializer)
                        {
                            if (property.IsEntityCollection)
                            {
                                results.Add(child);
                            }
                            else if (property.IsPrimitiveOrEnumOrComplexCollection)
                            {
                                Debug.Assert(property.PropertyType.IsAssignableFrom(child.GetType()), "Created instance for storing collection items has to be compatible with the actual one.");

                                // Collection materialization rules requires to clear the collection if not null or set the property first and then add the collection items
                                object collectionInstance = property.GetValue(this.entity);
                                if (collectionInstance == null)
                                {
                                    // type of child has been resolved as per rules for collections so it is the correct type to instantiate
                                    collectionInstance = Activator.CreateInstance(child.GetType());

                                    // allowAdd is false - we need to assign instance as the new property value
                                    property.SetValue(this.entity, collectionInstance, this.propertyName, false /* allowAdd? */);
                                }
                                else
                                {
                                    // Clear existing collection
                                    property.ClearBackingICollectionInstance(collectionInstance);
                                }

                                foreach (var collectionItem in (IEnumerable)child)
                                {
                                    Debug.Assert(property.PrimitiveOrComplexCollectionItemType.IsAssignableFrom(collectionItem.GetType()), "Type of materialized collection items have to be compatible with the type of collection items in the actual collection property.");
                                    property.AddValueToBackingICollectionInstance(collectionInstance, collectionItem);
                                }

                                results.Add(collectionInstance);
                            }
                            else
                            {
                                // it is either primitive type, complex type or 1..1 navigation property so we just allow setting the value but not adding.
                                property.SetValue(this.entity, child, this.propertyName, false);
                                results.Add(child);
                            }
                        }
                    }

                    continuation = materializer.GetContinuation(null);
                }

                return(MaterializeAtom.CreateWrapper(context, results, continuation));
            }
            finally
            {
                context.ApplyingChanges = merging;
            }
        }