blob: 6391d870777b192f20e807a03fb84ba0d3c61df3 [file] [log] [blame]
/// <summary>
/// Class used to parse the Content section of the feed to return the properties data and metadata
/// </summary>
namespace DataJS.Tests
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.ServiceModel.Syndication;
using System.Spatial;
using System.Xml;
using System.Xml.Linq;
public static class AtomReader
{
const string atomXmlNs = "http://www.w3.org/2005/Atom";
const string gmlXmlNs = "http://www.opengis.net/gml";
const string odataRelatedPrefix = "http://schemas.microsoft.com/ado/2007/08/dataservices/related";
const string odataRelatedLinksPrefix = "http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks";
const string odataXmlNs = "http://schemas.microsoft.com/ado/2007/08/dataservices";
const string odataMetaXmlNs = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata";
const string odataEditMediaPrefix = "http://schemas.microsoft.com/ado/2007/08/dataservices/edit-media";
const string odataMediaResourcePrefix = "http://schemas.microsoft.com/ado/2007/08/dataservices/mediaresource";
const string hrefAttribute = "href";
const string titleElement = "title";
const string workspaceElement = "workspace";
const string workspacesProperty = "workspaces";
const string collectionElement = "collection";
const string collectionsProperty = "collections";
const string extensionsProperty = "extensions";
static string baseUri = string.Empty;
/// <summary>
/// Creates a service document object
/// </summary>
/// <param name="container">The XML container</param>
/// <param name="uri">Uri to append to the href value</param>
/// <returns>The service document JsonObject</returns>
public static JsonObject ReadServiceDocument(TextReader payload, string baseUri)
{
JsonObject jsonObject = new JsonObject();
XElement container = XElement.Load(payload);
if (container != null && container.HasElements)
{
jsonObject["workspaces"] =
container
.Elements()
.Where(element => element.Name.LocalName.Equals(workspaceElement))
.Select(element => ReadWorkspaceObject(element, baseUri))
.ToArray();
jsonObject["extensions"] =
container
.Elements()
.Where(element => !element.Name.LocalName.Equals(workspaceElement))
.Select(element => ReadExtensionElement(element))
.ToArray();
}
return jsonObject;
}
public static JsonObject ReadEntry(TextReader payload)
{
SyndicationItem item = SyndicationItem.Load(XmlReader.Create(payload));
return ReadEntry(item);
}
public static JsonObject ReadFeed(TextReader payload)
{
SyndicationFeed feed = SyndicationFeed.Load(XmlReader.Create(payload));
JsonObject feedData = new JsonObject();
JsonObject feedMetadata = new JsonObject();
feedData["results"] = feed.Items.Select(item => ReadEntry(item)).ToArray();
feedData["__metadata"] = feedMetadata;
feedMetadata["feed_extensions"] = feed.AttributeExtensions.Select(pair => ReadExtension(pair)).ToArray();
if (feed.Id != null)
{
feedMetadata["uri"] = feed.Id;
feedMetadata["uri_extensions"] = new JsonObject[] { };
}
if (feed.Title != null)
{
feedMetadata["title"] = feed.Title.Text;
feedMetadata["title_extensions"] = GetTitleExtensions(feed.Title);
}
SyndicationLink feedSelfLink = GetLink("self", feed.Links);
if (feedSelfLink != null)
{
feedMetadata["self"] = feedSelfLink.GetAbsoluteUri().AbsoluteUri;
feedMetadata["self_extensions"] = GetLinkExtensions(feedSelfLink);
}
long? count = GetInlineCount(feed);
if (count.HasValue)
{
feedData["__count"] = count.Value;
}
SyndicationLink feedNextLink = GetLink("next", feed.Links);
if (feedNextLink != null)
{
feedData["__next"] = feedNextLink.GetAbsoluteUri().AbsoluteUri;
feedMetadata["next_extensions"] = GetLinkExtensions(feedNextLink);
}
return feedData;
}
private static JsonObject ReadEntry(SyndicationItem item)
{
SyndicationLink entryEditLink = GetLink("edit", item.Links);
SyndicationCategory entryCategory = item.Categories.FirstOrDefault();
XElement propertiesElement = GetPropertiesElement(item);
JsonObject entryData = ReadObject(propertiesElement);
entryData = JsonObject.Merge(entryData, ReadNavigationProperties(item));
entryData = JsonObject.Merge(entryData, ReadNamedStreams(item));
JsonObject propertiesMetadata = ReadPropertiesMetadata(propertiesElement);
propertiesMetadata = JsonObject.Merge(propertiesMetadata, ReadNavigationPropertiesMetadata(item));
propertiesMetadata = JsonObject.Merge(propertiesMetadata, ReadNamedStreamMetadata(item));
JsonObject entryMetadata = new JsonObject();
entryData["__metadata"] = entryMetadata;
entryMetadata["properties"] = propertiesMetadata;
if (item.Id != null)
{
entryMetadata["uri"] = item.Id;
entryMetadata["uri_extensions"] = new JsonObject[] { };
}
if (entryCategory != null)
{
entryMetadata["type"] = entryCategory.Name;
entryMetadata["type_extensions"] = new JsonObject[] { };
}
if (entryEditLink != null)
{
entryMetadata["edit"] = entryEditLink.GetAbsoluteUri().AbsoluteUri;
entryMetadata["edit_link_extensions"] = GetLinkExtensions(entryEditLink);
}
return entryData;
}
private static JsonObject ReadExtension(KeyValuePair<XmlQualifiedName, string> pair)
{
return ReaderUtils.CreateExtension(pair.Key.Name, pair.Key.Namespace, pair.Value);
}
private static string GetCollectionType(string type)
{
if (type != null && type.StartsWith("Collection("))
{
int start = 11;
int end = type.IndexOf(")") - 11;
return type.Substring(start, end);
}
return null;
}
/// <summary>
/// Find the m:properties element within a feed entry
/// </summary>
/// <param name="item">The feed entry</param>
/// <returns>The m:properties element</returns>
private static XElement GetPropertiesElement(SyndicationItem item)
{
// Check if the m:properties element is within the content element
XmlSyndicationContent xmlContent = item.Content as XmlSyndicationContent;
if (xmlContent != null)
{
XElement contentElement = XElement.Load(xmlContent.GetReaderAtContent());
return contentElement.Elements().FirstOrDefault(e => e.Name == XName.Get("properties", odataMetaXmlNs));
}
// If we're here, then we are dealing with a feed that has an MLE
// i.e. the m:properties element is a peer of the content element, and shows up
// in the elementExtensions instead
SyndicationElementExtension propertiesElementExtension = item.ElementExtensions.FirstOrDefault(e => e.OuterName.Equals("properties"));
if (propertiesElementExtension != null)
{
XNode propertiesElement = XNode.ReadFrom(propertiesElementExtension.GetReader());
return (XElement)propertiesElement;
}
throw new NotSupportedException("Unsupported feed entry format");
}
/// <summary>
/// Gets the inline count within a feed
/// </summary>
/// <param name="feed">The feed</param>
/// <returns>The inline count, or null if none exists</returns>
private static long? GetInlineCount(SyndicationFeed feed)
{
SyndicationElementExtension countElementExtension = feed.ElementExtensions.SingleOrDefault(extension =>
extension.OuterName.Equals("count", StringComparison.OrdinalIgnoreCase) &&
extension.OuterNamespace.Equals(odataMetaXmlNs));
if (countElementExtension != null)
{
XElement countElement = (XElement)XNode.ReadFrom(countElementExtension.GetReader());
return XmlConvert.ToInt64(countElement.Value);
}
else
{
return null;
}
}
/// <summary>
/// Gets the link with the specified relationship type
/// </summary>
/// <param name="rel">Relationship type</param>
/// <param name="links">The set of links to search from</param>
/// <returns>The link with the specified relationship type, or null if none exists</returns>
private static SyndicationLink GetLink(string rel, IEnumerable<SyndicationLink> links)
{
return links.SingleOrDefault(link => link.RelationshipType.Equals(rel, StringComparison.InvariantCultureIgnoreCase));
}
private static IEnumerable<SyndicationLink> GetLinks(string rel, IEnumerable<SyndicationLink> links)
{
return links.Where(link => link.RelationshipType.StartsWith(rel, StringComparison.Ordinal));
}
//TODO refactor the extraction of extensions into extension elements and extension attribute methods.
private static JsonObject[] GetLinkExtensions(SyndicationLink link)
{
List<JsonObject> extensions = new List<JsonObject>();
//TODO: fix the inclusion of title as extension. Title attribute is not required in the link element and its
//inclusion as an extension should be tested for the precesence of the attribute in the xml element. Unfortunately,
//SyndicationLink doesn't allow for accessing the underlying XML document.. perhaps using an AtomFormatter10??
extensions.Add(ReaderUtils.CreateExtension("title", null, link.Title));
extensions.AddRange(link.AttributeExtensions.Select(pair => ReadExtension(pair)));
return extensions.ToArray();
}
private static JsonObject[] GetTitleExtensions(TextSyndicationContent title)
{
List<JsonObject> extensions = new List<JsonObject>();
extensions.Add(ReaderUtils.CreateExtension("type", null, title.Type));
extensions.AddRange(title.AttributeExtensions.Select(pair => ReadExtension(pair)));
return extensions.ToArray();
}
/// <summary>
/// Gets the "type" value from a property element
/// </summary>
/// <param name="propertyElement">The property element</param>
/// <returns>The "type" value, or default (Edm.String) if none specified</returns>
private static string GetTypeAttribute(XElement propertyElement)
{
XAttribute typeAttribute = propertyElement.Attribute(XName.Get("type", odataMetaXmlNs));
if (typeAttribute == null)
{
if (propertyElement.HasElements)
{
return null;
}
return "Edm.String";
}
return typeAttribute.Value;
}
private static bool HasTypeAttribute(XElement propertyElement)
{
return propertyElement.Attribute(XName.Get("type", odataMetaXmlNs)) != null;
}
private static bool IsCollectionProperty(XElement propertyElement)
{
string type = GetTypeAttribute(propertyElement);
if (type != null && type.StartsWith("Collection("))
{
return true;
}
return propertyElement.Elements().Count(pe => pe.Name == XName.Get("element", odataXmlNs)) > 1;
}
private static JsonObject ReadWorkspaceObject(XElement container, string baseUri)
{
JsonObject jsonObject = new JsonObject();
jsonObject["collections"] =
container
.Elements()
.Where(element => element.Name.LocalName.Equals("collection"))
.Select(element => ReadWorkspaceCollections(element, baseUri))
.ToArray();
jsonObject["extensions"] =
container
.Elements()
.Where(element =>
!(element.Name.LocalName.Equals("collection") ||
element.Name.LocalName.Equals("title")))
.Select(element => ReadExtensionElement(element))
.ToArray();
jsonObject["title"] =
container
.Elements()
.Where(element => element.Name.LocalName.Equals("title"))
.First()
.Value;
return jsonObject;
}
private static JsonObject ReadWorkspaceCollections(XElement container, string baseUri)
{
JsonObject jsonObject = new JsonObject();
string title = string.Empty;
jsonObject["extensions"] =
container
.Elements()
.Where(element =>
!(element.Name.LocalName.Equals(collectionElement) ||
element.Name.LocalName.Equals(titleElement)))
.Select(element => ReadExtensionElement(element))
.ToArray();
jsonObject["title"] =
container
.Elements()
.Where(element => element.Name.LocalName.Equals("title"))
.First()
.Value;
IEnumerable<XAttribute> hrefAttributes =
container
.Attributes()
.Where(element => element.Name.LocalName.Equals("href"));
jsonObject["href"] = baseUri + hrefAttributes.First().Value;
return jsonObject;
}
private static JsonObject ReadExtensionElement(XElement element)
{
JsonObject jsonObject = ReaderUtils.CreateExtension(element.Name.LocalName, element.BaseUri, null);
jsonObject.Remove("value");
jsonObject["attributes"] = ReadExtensionAttributes(element);
jsonObject["children"] = element.Elements().Select(child => ReadExtensionElement(element)).ToArray();
return jsonObject;
}
private static JsonObject ReadExtensionAttribute(XAttribute attribute)
{
return ReaderUtils.CreateExtension(attribute.Name.LocalName, attribute.BaseUri, attribute.Value);
}
private static JsonObject[] ReadExtensionAttributes(XElement container)
{
List<JsonObject> attributes = new List<JsonObject>();
foreach (XAttribute attribute in container.Attributes())
{
attributes.Add(ReadExtensionAttribute(attribute));
}
return attributes.ToArray();
}
private static JsonObject ReadNamedStreamMetadata(SyndicationItem item)
{
JsonObject propertiesMetadata = new JsonObject();
JsonObject streamMetadata;
string propertyName;
foreach (SyndicationLink link in GetLinks(odataEditMediaPrefix, item.Links))
{
streamMetadata = new JsonObject();
streamMetadata["edit_media_extensions"] = GetLinkExtensions(link);
streamMetadata["media_src_extensions"] = new JsonObject[0];
propertyName = link.RelationshipType.Substring(odataEditMediaPrefix.Length + 1);
propertiesMetadata[propertyName] = streamMetadata;
}
foreach (SyndicationLink link in GetLinks(odataMediaResourcePrefix, item.Links))
{
streamMetadata = new JsonObject();
streamMetadata["media_src_extensions"] = GetLinkExtensions(link);
propertyName = link.RelationshipType.Substring(odataMediaResourcePrefix.Length + 1);
if (propertiesMetadata.ContainsKey(propertyName))
{
streamMetadata = JsonObject.Merge((JsonObject)propertiesMetadata[propertyName], streamMetadata);
}
propertiesMetadata[propertyName] = streamMetadata;
}
return propertiesMetadata;
}
private static JsonObject ReadNamedStreams(SyndicationItem item)
{
// Not very elegant, but quick and easy, do it in two passes.
JsonObject streams = new JsonObject();
JsonObject streamValue;
JsonObject mediaResource;
string propertyName;
foreach (SyndicationLink link in GetLinks(odataEditMediaPrefix, item.Links))
{
propertyName = link.RelationshipType.Substring(odataEditMediaPrefix.Length + 1);
streamValue = new JsonObject();
mediaResource = new JsonObject();
streams[propertyName] = streamValue;
streamValue["__mediaresource"] = mediaResource;
mediaResource["edit_media"] = link.GetAbsoluteUri().AbsoluteUri;
mediaResource["content_type"] = link.MediaType;
mediaResource["media_src"] = link.GetAbsoluteUri().AbsoluteUri;
var etagAttributeName = new XmlQualifiedName("etag", odataMetaXmlNs);
if (link.AttributeExtensions.ContainsKey(etagAttributeName))
{
mediaResource["media_etag"] = link.AttributeExtensions[etagAttributeName];
link.AttributeExtensions.Remove(etagAttributeName);
}
}
foreach (SyndicationLink link in GetLinks(odataMediaResourcePrefix, item.Links))
{
propertyName = link.RelationshipType.Substring(odataMediaResourcePrefix.Length + 1);
mediaResource = new JsonObject();
mediaResource["content_type"] = link.MediaType;
mediaResource["media_src"] = link.GetAbsoluteUri().AbsoluteUri;
if (streams.ContainsKey(propertyName))
{
streamValue = streams[propertyName] as JsonObject;
mediaResource = JsonObject.Merge(streamValue["__mediaresource"] as JsonObject, mediaResource);
}
else
{
streamValue = new JsonObject();
}
streamValue["__mediaresource"] = mediaResource;
streams[propertyName] = streamValue;
}
return streams;
}
private static JsonObject ReadNavigationProperties(SyndicationItem item)
{
JsonObject navProperties = new JsonObject();
SyndicationElementExtension inline;
string propertyName;
JsonObject propertyValue = null;
foreach (SyndicationLink link in GetLinks(odataRelatedPrefix, item.Links))
{
propertyName = link.RelationshipType.Substring(odataRelatedPrefix.Length + 1);
inline = link.ElementExtensions.SingleOrDefault(e =>
odataMetaXmlNs.Equals(e.OuterNamespace, StringComparison.Ordinal) &&
e.OuterName.Equals("inline", StringComparison.Ordinal));
if (inline != null)
{
XElement inlineElement = (XElement)XNode.ReadFrom(inline.GetReader());
XElement innerElement = inlineElement.Elements().FirstOrDefault();
if (innerElement != null)
{
// By default the inner feed/entry does not have the xml:base attribute, so we need to
// add it so that the parsed SyndicationFeed or SyndicationItem retains the baseUri
if (link.BaseUri != null)
{
innerElement.SetAttributeValue(XNamespace.Xml + "base", link.BaseUri.OriginalString);
}
// We are converting to a string before creating the reader to strip out extra indenting,
// otherwise the reader creates extra XmlText nodes that SyndicationFeed/SyndicationItem cannot handle
try
{
propertyValue = ReadFeed(new StringReader(innerElement.ToString()));
}
catch (XmlException)
{
// Try with entry instead ..
propertyValue = ReadEntry(new StringReader(innerElement.ToString()));
}
}
}
else
{
JsonObject deferred = new JsonObject();
deferred["uri"] = link.GetAbsoluteUri().AbsoluteUri;
propertyValue = new JsonObject();
propertyValue["__deferred"] = deferred;
}
navProperties[propertyName] = propertyValue;
}
return navProperties;
}
private static JsonObject ReadNavigationPropertiesMetadata(SyndicationItem item)
{
JsonObject propertiesMetadata = new JsonObject();
JsonObject navMetadata;
string propertyName;
foreach (SyndicationLink link in GetLinks(odataRelatedPrefix, item.Links))
{
navMetadata = new JsonObject();
navMetadata["extensions"] = GetLinkExtensions(link).Where(e =>
!(string.Equals(e["name"] as string, "inline", StringComparison.Ordinal) &&
string.Equals(e["namespaceURI"] as string, odataMetaXmlNs, StringComparison.Ordinal))
).ToArray();
propertyName = link.RelationshipType.Substring(odataRelatedPrefix.Length + 1);
propertiesMetadata[propertyName] = navMetadata;
}
foreach (SyndicationLink link in GetLinks(odataRelatedLinksPrefix, item.Links))
{
navMetadata = new JsonObject();
navMetadata["associationuri"] = link.GetAbsoluteUri().AbsoluteUri;
navMetadata["associationuri_extensions"] = link.GetAbsoluteUri().AbsoluteUri;
propertyName = link.RelationshipType.Substring(odataRelatedLinksPrefix.Length + 1);
if (propertiesMetadata.ContainsKey(propertyName))
{
navMetadata = JsonObject.Merge(propertiesMetadata[propertyName] as JsonObject, navMetadata);
}
propertiesMetadata[propertyName] = navMetadata;
}
return propertiesMetadata;
}
private static JsonObject ReadPropertiesMetadata(XElement container)
{
JsonObject json = null;
if (container != null && container.Elements().Any(e => e.Name.NamespaceName == odataXmlNs))
{
json = new JsonObject();
foreach (XElement propertyElement in container.Elements())
{
json[propertyElement.Name.LocalName] = ReadPropertyMetadata(propertyElement);
}
}
return json;
}
private static JsonObject ReadPropertyMetadata(XElement property)
{
var metadata = ReaderUtils.CreateEntryPropertyMetadata(GetTypeAttribute(property));
if (IsCollectionProperty(property))
{
string collectionType = GetCollectionType(GetTypeAttribute(property));
if (collectionType == null)
{
metadata["type"] = "Collection()";
}
List<JsonObject> elements = new List<JsonObject>();
foreach (XElement item in property.Elements(XName.Get("element", odataXmlNs)))
{
string itemType =
HasTypeAttribute(item) ? GetTypeAttribute(item) :
IsCollectionProperty(item) ? "Collection()" : collectionType;
var itemMetadata = ReaderUtils.CreateEntryPropertyMetadata(itemType);
if (item.Elements().Any(e => e.Name.NamespaceName == odataXmlNs))
{
itemMetadata["properties"] = ReadPropertiesMetadata(item);
}
elements.Add(itemMetadata);
}
metadata["elements"] = elements.ToArray();
}
else if (property != null && property.Elements().Any(e => e.Name.NamespaceName == odataXmlNs))
{
metadata["properties"] = ReadPropertiesMetadata(property);
}
return metadata;
}
/// <summary>
/// Creates a JsonObject from an XML container element (e.g. the m:properties element) of an OData ATOM feed entry.
/// </summary>
/// <param name="container">The XML container</param>
/// <param name="buildValue">Function that builds a value from a property element</param>
/// <returns>The JsonObject containing the name-value pairs</returns>
private static JsonObject ReadObject(XElement container)
{
if (container == null)
{
return null;
}
var json = new JsonObject();
foreach (XElement propertyElement in container.Elements())
{
json[propertyElement.Name.LocalName] = ReadDataItem(propertyElement);
}
return json;
}
private static JsonObject ReadCollectionProperty(XElement property, string typeName)
{
var collectionType = GetCollectionType(typeName);
var json = new JsonObject();
var results = new List<object>();
foreach (XElement item in property.Elements())
{
object resultItem = ReadDataItem(item);
results.Add(resultItem);
JsonObject complexValue = resultItem as JsonObject;
if (complexValue != null)
{
var metadata = complexValue["__metadata"] as JsonObject;
if (!string.IsNullOrEmpty(collectionType) && metadata["type"] == null)
{
metadata["type"] = collectionType;
}
}
}
json["results"] = results;
json["__metadata"] = ReaderUtils.CreateEntryPropertyMetadata(typeName, false);
return json;
}
private static JsonObject ReadComplexProperty(XElement container, string typeName)
{
JsonObject json = ReadObject(container);
json["__metadata"] = ReaderUtils.CreateEntryPropertyMetadata(GetTypeAttribute(container), false);
return json;
}
private static JsonObject ReadJsonSpatialProperty(XElement container, XElement gmlValue, bool isGeography)
{
GmlFormatter gmlFormatter = GmlFormatter.Create();
GeoJsonObjectFormatter jsonformatter = GeoJsonObjectFormatter.Create();
bool ignoreCrc = !gmlValue.Attributes().Any(a => a.Name.LocalName == "srsName");
ISpatial spatialValue;
if (isGeography)
{
spatialValue = gmlFormatter.Read<Geography>(gmlValue.CreateReader());
}
else
{
spatialValue = gmlFormatter.Read<Geometry>(gmlValue.CreateReader());
}
IDictionary<string, object> geoJsonData = jsonformatter.Write(spatialValue);
JsonObject json = new JsonObject();
Queue<object> geoJsonScopes = new Queue<object>();
Queue<object> jsonScopes = new Queue<object>();
geoJsonScopes.Enqueue(geoJsonData);
jsonScopes.Enqueue(json);
Func<object, object> convertScope = (scope) =>
{
object newScope =
scope is List<object> || scope is object[] ? (object)new List<Object>() :
scope is IDictionary<string, object> ? (object)new JsonObject() :
null;
if (newScope != null)
{
geoJsonScopes.Enqueue(scope);
jsonScopes.Enqueue(newScope);
}
return newScope ?? scope;
};
while (jsonScopes.Count > 0)
{
if (jsonScopes.Peek() is JsonObject)
{
var currentGeoJson = (IDictionary<string, object>)geoJsonScopes.Dequeue();
var currentJson = (JsonObject)jsonScopes.Dequeue();
foreach (var item in currentGeoJson)
{
if (!ignoreCrc || item.Key != "crs")
{
currentJson[item.Key] = convertScope(item.Value);
}
}
}
else
{
var currentGeoJson = (IEnumerable<object>)geoJsonScopes.Dequeue();
var currentJson = (List<object>)jsonScopes.Dequeue();
foreach (var item in currentGeoJson)
{
currentJson.Add(convertScope(item));
}
}
}
json["__metadata"] = ReaderUtils.CreateEntryPropertyMetadata(GetTypeAttribute(container), false);
return json;
}
public static object ReadDataItem(XElement item)
{
string typeName = GetTypeAttribute(item);
XElement gmlRoot = item.Elements().SingleOrDefault(e => e.Name.NamespaceName == gmlXmlNs);
if (gmlRoot != null)
{
bool isGeography = typeName.StartsWith("Edm.Geography");
return ReadJsonSpatialProperty(item, gmlRoot, isGeography);
}
bool isCollection = IsCollectionProperty(item);
if (item.HasElements || isCollection)
{
// Complex type, Collection Type: parse recursively
return isCollection ? ReadCollectionProperty(item, typeName) : ReadComplexProperty(item, typeName);
}
// Primitive type: null value
XNamespace mNamespace = item.GetNamespaceOfPrefix("m");
XAttribute nullAttribute = mNamespace == null ? null : item.Attribute(mNamespace.GetName("null"));
if (nullAttribute != null && nullAttribute.Value.Equals("true", StringComparison.InvariantCultureIgnoreCase))
{
return null;
}
// Primitive type: check type and parse value accordingly
string value = item.Value;
switch (typeName)
{
case "Edm.Byte":
return XmlConvert.ToByte(value);
case "Edm.Int16":
return XmlConvert.ToInt16(value);
case "Edm.Int32":
return XmlConvert.ToInt32(value);
case "Edm.SByte":
return XmlConvert.ToSByte(value);
case "Edm.Boolean":
return XmlConvert.ToBoolean(value);
case "Edm.Double":
return XmlConvert.ToDouble(value);
case "Edm.Single":
return XmlConvert.ToSingle(value);
case "Edm.Guid":
return XmlConvert.ToGuid(value);
case "Edm.DateTime":
return new JsDate(XmlConvert.ToDateTime(value, XmlDateTimeSerializationMode.Utc));
case "Edm.DateTimeOffset":
return new JsDate(XmlConvert.ToDateTimeOffset(value));
case "Edm.Time":
throw new NotSupportedException(typeName + " is not supported");
// Decimal and Int64 values are sent as strings over the wire. This is the same behavior as WCF Data Services JSON serializer.
case "Edm.Decimal":
case "Edm.Int64":
case "":
default:
return value;
}
}
}
}