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); } }
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)); }
/// <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); }
/// <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); }
/// <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); }
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); } }
/// <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; } }
/// <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); }
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); }
/// <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; }
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) { }
/// <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; } }
/// <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; } }