private static void SnapExpandedEntry(List <DeltaSnapshotEntry> results, object element, IEdmNavigationSource edmParent, IEnumerable <ExpandedNavigationSelectItem> expandedNavigationItems, string parentId) { foreach (var navigationProperty in ((IEdmEntityType)EdmClrTypeUtils.GetEdmType(DataSourceManager.GetCurrentDataSource().Model, element)).NavigationProperties()) { var expandedNavigationItem = GetExpandedNavigationItem(expandedNavigationItems, navigationProperty.Name); if (expandedNavigationItem != null) { bool isCollection = navigationProperty.Type.IsCollection(); ExpandSelectItemHandler expandItemHandler = new ExpandSelectItemHandler(element); expandedNavigationItem.HandleWith(expandItemHandler); var propertyValue = expandItemHandler.ExpandedChildElement; if (propertyValue != null) { IEdmNavigationSource targetSource = edmParent.FindNavigationTarget(navigationProperty); if (isCollection) { SnapResults(results, propertyValue as IEnumerable, targetSource as IEdmEntitySetBase, expandedNavigationItem.SelectAndExpand, parentId, navigationProperty.Name); } else { SnapResult(results, propertyValue, targetSource, expandedNavigationItem.SelectAndExpand, parentId, navigationProperty.Name); } } } } }
/// <summary> /// Converts an item from the data store into an ODataEntityReferenceLink. /// </summary> /// <param name="element">The item to convert.</param> /// <param name="navigationSource">The navigation source that the item belongs to.</param> /// <param name="targetVersion">The OData version this segment is targeting.</param> /// <returns>The converted ODataEntityReferenceLink represent with ODataEntry.</returns> public static ODataResource ConvertToODataEntityReferenceLink(object element, IEdmNavigationSource entitySource, ODataVersion targetVersion) { IEdmStructuredType entityType = EdmClrTypeUtils.GetEdmType(DataSourceManager.GetCurrentDataSource().Model, element) as IEdmStructuredType; if (entityType == null) { throw new InvalidOperationException("Can not create an entry for " + entitySource.Name); } var link = new ODataResource(); if (!string.IsNullOrEmpty(((ClrObject)element).EntitySetName) && entitySource is IEdmEntitySet && entityType is IEdmEntityType) { entitySource = new EdmEntitySet(((IEdmEntitySet)entitySource).Container, ((ClrObject)element).EntitySetName, (IEdmEntityType)entityType); } if (!(entitySource is IEdmContainedEntitySet)) { Uri Url = BuildEntryUri(element, entitySource, targetVersion); link.Id = Url; } // This is workaround now to make Photo/$ref works or it will fail validation as it is MediaEntity but no stream if (Utility.IsMediaEntity(element.GetType())) { var streamProvider = DataSourceManager.GetCurrentDataSource().StreamProvider; link.MediaResource = new ODataStreamReferenceValue() { ContentType = streamProvider.GetContentType(element), ETag = streamProvider.GetETag(element), }; } return(link); }
private static void WriteNavigationLinks(ODataWriter writer, object element, Uri parentEntryUri, IEdmNavigationSource edmParent, ODataVersion targetVersion, IEnumerable <ExpandedNavigationSelectItem> expandedNavigationItems) { foreach (var navigationProperty in ((IEdmEntityType)EdmClrTypeUtils.GetEdmType(DataSourceManager.GetCurrentDataSource().Model, element)).NavigationProperties()) { var expandedNavigationItem = GetExpandedNavigationItem(expandedNavigationItems, navigationProperty.Name); // For Atom, we always manually write out the links for the navigation properties off of the entity type // Or if the navigation is expanded, we manually write out the links for the navigation properties along with the expanded entries if (writer.GetType().Name != "ODataJsonLightWriter" || expandedNavigationItem != null) { bool isCollection = navigationProperty.Type.IsCollection(); var navigationLink = new ODataNavigationLink { IsCollection = isCollection, Name = navigationProperty.Name, }; if (writer.GetType().Name == "ODataAtomWriter") { //If the passed in parentEntryUri is null then exception will be thrown, to avoid this, create a relative 'potato' Uri. navigationLink.Url = (parentEntryUri == null) ? new Uri("potato", UriKind.Relative) : new Uri(new Uri(parentEntryUri.AbsoluteUri + "/"), navigationProperty.Name); } writer.WriteStart(navigationLink); if (expandedNavigationItem != null) { ExpandSelectItemHandler expandItemHandler = new ExpandSelectItemHandler(element); expandedNavigationItem.HandleWith(expandItemHandler); var propertyValue = expandItemHandler.ExpandedChildElement; if (propertyValue != null) { IEdmNavigationSource targetSource = edmParent.FindNavigationTarget(navigationProperty); if (isCollection) { long?count = null; var collectionValue = propertyValue as IEnumerable; if (collectionValue != null && expandedNavigationItem.CountOption == true) { count = collectionValue.Cast <object>().LongCount(); } WriteFeed(writer, collectionValue, targetSource as IEdmEntitySetBase, targetVersion, expandedNavigationItem.SelectAndExpand, count, null, null); } else { WriteEntry(writer, propertyValue, targetSource, targetVersion, expandedNavigationItem.SelectAndExpand); } } } writer.WriteEnd(); } } }
/// <summary> /// Converts an item from the data store into an ODataEntityReferenceLink. /// </summary> /// <param name="element">The item to convert.</param> /// <param name="navigationSource">The navigation source that the item belongs to.</param> /// <param name="targetVersion">The OData version this segment is targeting.</param> /// <returns>The converted ODataEntityReferenceLink represent with ODataEntry.</returns> public static ODataEntry ConvertToODataEntityReferenceLink(object element, IEdmNavigationSource entitySource, ODataVersion targetVersion) { IEdmStructuredType entityType = EdmClrTypeUtils.GetEdmType(DataSourceManager.GetCurrentDataSource().Model, element) as IEdmStructuredType; if (entityType == null) { throw new InvalidOperationException("Can not create an entry for " + entitySource.Name); } var link = new ODataEntry(); if (!string.IsNullOrEmpty(((ClrObject)element).EntitySetName) && entitySource is IEdmEntitySet && entityType is IEdmEntityType) { entitySource = new EdmEntitySet(((IEdmEntitySet)entitySource).Container, ((ClrObject)element).EntitySetName, (IEdmEntityType)entityType); } if (!(entitySource is IEdmContainedEntitySet)) { Uri Url = BuildEntryUri(element, entitySource, targetVersion); link.Id = Url; } return(link); }
/// <summary> /// Converts an item from the data store into an ODataEntry. /// </summary> /// <param name="element">The item to convert.</param> /// <param name="navigationSource">The navigation source that the item belongs to.</param> /// <param name="targetVersion">The OData version this segment is targeting.</param> /// <returns>The converted ODataEntry.</returns> public static ODataResourceWrapper ConvertToODataEntry(object element, IEdmNavigationSource entitySource, ODataVersion targetVersion) { IEdmStructuredType entityType = EdmClrTypeUtils.GetEdmType(DataSourceManager.GetCurrentDataSource().Model, element) as IEdmStructuredType; if (entityType == null) { throw new InvalidOperationException("Can not create an entry for " + entitySource.Name); } var propertiesOrNestedResourceInfos = GetPropertiesOrNestedResourceInfos(element, entityType); var entry = new ODataResource { Properties = propertiesOrNestedResourceInfos.OfType <ODataProperty>(), }; var resourceWrapper = new ODataResourceWrapper() { Resource = entry, NestedResourceInfoWrappers = propertiesOrNestedResourceInfos.OfType <ODataNestedResourceInfoWrapper>().ToList(), }; // Add Annotation in Entity Level if (((ClrObject)element).Annotations != null) { foreach (InstanceAnnotationType annotation in ((ClrObject)element).Annotations) { if (string.IsNullOrEmpty(annotation.Target)) { entry.InstanceAnnotations.Add(new ODataInstanceAnnotation(annotation.Name, annotation.ConvertValueToODataValue())); } } } // Work around for entities from different entity set. if (!string.IsNullOrEmpty(((ClrObject)element).EntitySetName) && entitySource is IEdmEntitySet && entityType is IEdmEntityType) { entitySource = new EdmEntitySet(((IEdmEntitySet)entitySource).Container, ((ClrObject)element).EntitySetName, (IEdmEntityType)entityType); } string typeName; if (entityType is IEdmEntityType) { typeName = (entityType as IEdmEntityType).Name; } else if (entityType is IEdmComplexType) { typeName = (entityType as IEdmComplexType).Name; } else { throw new InvalidOperationException("Not Supported Edmtype to convert to OData Entry."); } entry.TypeName = element.GetType().Namespace + "." + typeName; // TODO: work around for now if (entitySource != null && !(entitySource is IEdmContainedEntitySet)) { Uri entryUri = BuildEntryUri(element, entitySource, targetVersion); if (element.GetType().BaseType != null && entitySource.EntityType().Name != typeName) { var editLink = new Uri(entryUri.AbsoluteUri.TrimEnd('/') + "/" + entry.TypeName); entry.EditLink = editLink; entry.ReadLink = editLink; } else { entry.EditLink = entryUri; entry.ReadLink = entryUri; } entry.Id = entryUri; } if (Utility.IsMediaEntity(element.GetType())) { var streamProvider = DataSourceManager.GetCurrentDataSource().StreamProvider; entry.MediaResource = new ODataStreamReferenceValue() { ContentType = streamProvider.GetContentType(element), ETag = streamProvider.GetETag(element), }; } return(resourceWrapper); }
public static object CreateODataValue(object value) { if (value != null) { Type t = value.GetType(); if (t.IsGenericType) { // Build a collection type property string itemTypeName = t.GetGenericArguments().First().FullName; if (itemTypeName == "System.UInt16" || itemTypeName == "System.UInt32" || itemTypeName == "System.UInt64") { string modelNS = DataSourceManager.GetCurrentDataSource().Model.DeclaredNamespaces.First(); itemTypeName = itemTypeName.Replace("System", modelNS); } else if (itemTypeName == "System.TimeSpan") { itemTypeName = "Edm.Duration"; } else { itemTypeName = itemTypeName.Replace("System.", "Edm."); } var genericTypeName = "Collection(" + itemTypeName + ")"; ICollection <object> tmp = new Collection <object>(); foreach (var o in (value as IEnumerable)) { tmp.Add(CreateODataValue(o)); } return(new ODataCollectionValue() { TypeName = genericTypeName, Items = tmp }); } else if (t.Namespace != "System" && !t.Namespace.StartsWith("Microsoft.Data.Spatial") && !t.Namespace.StartsWith("Microsoft.OData.Edm.Library")) { if (t.IsEnum == true) { return(new ODataEnumValue(value.ToString(), t.FullName)); } else { // Build a complex type property. We consider type t to be primitive if t.Namespace is "System" or if t is spatial type. List <ODataProperty> properties = new List <ODataProperty>(); IEdmStructuredType structuredType = (IEdmStructuredType)EdmClrTypeUtils.GetEdmType(DataSourceManager.GetCurrentDataSource().Model, value); foreach (var p in GetProperties(value, structuredType)) { if (t.GetProperty(p.Name) != null) { properties.Add(p); } else if (structuredType.IsOpen) { var instance = value as OpenClrObject; properties.Add(CreateODataProperty(instance.OpenProperties[p.Name], p.Name)); } } var complexValue = new ODataComplexValue() { TypeName = t.FullName, Properties = properties, }; // Add Annotation in complex level if (((ClrObject)value).Annotations != null) { foreach (InstanceAnnotationType annotation in ((ClrObject)value).Annotations) { if (string.IsNullOrEmpty(annotation.Target)) { complexValue.InstanceAnnotations.Add(new ODataInstanceAnnotation(annotation.Name, annotation.ConvertValueToODataValue())); } } } return(complexValue); } } } return(value); }