private static void AddNavigationBindings(EdmTypeMap edmMap, NavigationSourceConfiguration navigationSourceConfiguration, EdmNavigationSource navigationSource, NavigationSourceLinkBuilderAnnotation linkBuilder, Dictionary <string, EdmNavigationSource> edmNavigationSourceMap) { foreach (var binding in navigationSourceConfiguration.Bindings) { NavigationPropertyConfiguration navigationProperty = binding.NavigationProperty; bool isContained = navigationProperty.ContainsTarget; IEdmType edmType = edmMap.EdmTypes[navigationProperty.DeclaringType.ClrType]; IEdmStructuredType structuraType = edmType as IEdmStructuredType; IEdmNavigationProperty edmNavigationProperty = structuraType.NavigationProperties() .Single(np => np.Name == navigationProperty.Name); string bindingPath = ConvertBindingPath(edmMap, binding); if (!isContained) { // calculate the binding path navigationSource.AddNavigationTarget( edmNavigationProperty, edmNavigationSourceMap[binding.TargetNavigationSource.Name], new EdmPathExpression(bindingPath)); } NavigationLinkBuilder linkBuilderFunc = navigationSourceConfiguration.GetNavigationPropertyLink(navigationProperty); if (linkBuilderFunc != null) { linkBuilder.AddNavigationPropertyLinkBuilder(edmNavigationProperty, linkBuilderFunc); } } }
public static IEdmModel BuildEdmModel(ODataModelBuilder builder) { if (builder == null) { throw Error.ArgumentNull("builder"); } EdmModel model = new EdmModel(); EdmEntityContainer container = new EdmEntityContainer(builder.Namespace, builder.ContainerName); // add types and sets, building an index on the way. IEnumerable <IEdmTypeConfiguration> configTypes = builder.StructuralTypes.Concat <IEdmTypeConfiguration>(builder.EnumTypes); EdmTypeMap edmMap = EdmTypeBuilder.GetTypesAndProperties(configTypes); Dictionary <Type, IEdmType> edmTypeMap = model.AddTypes(edmMap); // Add EntitySets and build the mapping between the EdmEntitySet and the NavigationSourceConfiguration NavigationSourceAndAnnotations[] entitySets = container.AddEntitySetAndAnnotations(builder, edmTypeMap); // Add Singletons and build the mapping between the EdmSingleton and the NavigationSourceConfiguration NavigationSourceAndAnnotations[] singletons = container.AddSingletonAndAnnotations(builder, edmTypeMap); // Merge EntitySets and Singletons together IEnumerable <NavigationSourceAndAnnotations> navigationSources = entitySets.Concat(singletons); // Build the navigation source map IDictionary <string, EdmNavigationSource> navigationSourceMap = model.GetNavigationSourceMap(edmMap, navigationSources); // Add the core vocabulary annotations model.AddCoreVocabularyAnnotations(navigationSources, edmMap); // TODO: support etags on contained nav props // Support for this in 5.x adds annotations to navigation properties. Ideally would add annotations to entity set/singleton for // containing type(s) with nav paths to the contained nav property. // model.AddNavPropAnnotations(builder, edmMap); // implemented in EdmModelHelperMethods.cs of 5.x branch // Add the capabilities vocabulary annotations model.AddCapabilitiesVocabularyAnnotations(navigationSources, edmMap); // add operations model.AddOperations(builder.Operations, container, edmTypeMap, navigationSourceMap); // finish up model.AddElement(container); // build the map from IEdmEntityType to IEdmFunctionImport model.SetAnnotationValue <BindableOperationFinder>(model, new BindableOperationFinder(model)); return(model); }
private static void AddClrEnumMemberInfoAnnotations(this EdmModel model, EdmTypeMap edmTypeMap) { if (edmTypeMap.EnumMembers == null || !edmTypeMap.EnumMembers.Any()) { return; } var enumGroupBy = edmTypeMap.EnumMembers.GroupBy(e => e.Key.GetType(), e => e); foreach (var enumGroup in enumGroupBy) { IEdmType edmType = edmTypeMap.EdmTypes[enumGroup.Key]; model.SetAnnotationValue(edmType, new ClrEnumMemberAnnotation(enumGroup.ToDictionary(e => e.Key, e => e.Value))); } }
private static Dictionary <Type, IEdmType> AddTypes(this EdmModel model, EdmTypeMap edmTypeMap) { // build types Dictionary <Type, IEdmType> edmTypes = edmTypeMap.EdmTypes; // Add an annotate types model.AddTypes(edmTypes); model.AddClrTypeAnnotations(edmTypes); // add annotation for properties Dictionary <PropertyInfo, IEdmProperty> edmProperties = edmTypeMap.EdmProperties; model.AddClrPropertyInfoAnnotations(edmProperties); model.AddPropertyRestrictionsAnnotations(edmTypeMap.EdmPropertiesRestrictions); model.AddPropertiesQuerySettings(edmTypeMap.EdmPropertiesQuerySettings); model.AddStructuredTypeQuerySettings(edmTypeMap.EdmStructuredTypeQuerySettings); // add dynamic dictionary property annotation for open types model.AddDynamicPropertyDictionaryAnnotations(edmTypeMap.OpenTypes); return(edmTypes); }
private static string ConvertBindingPath(EdmTypeMap edmMap, NavigationPropertyBindingConfiguration binding) { IList <string> bindings = new List <string>(); foreach (MemberInfo bindingInfo in binding.Path) { Type typeCast = TypeHelper.AsType(bindingInfo); PropertyInfo propertyInfo = bindingInfo as PropertyInfo; if (typeCast != null) { IEdmType edmType = edmMap.EdmTypes[typeCast]; bindings.Add(edmType.FullTypeName()); } else if (propertyInfo != null) { bindings.Add(edmMap.EdmProperties[propertyInfo].Name); } } return(String.Join("/", bindings)); }
private static Dictionary <Type, IEdmType> AddTypes(this EdmModel model, IEnumerable <StructuralTypeConfiguration> types, IEnumerable <EnumTypeConfiguration> enumTypes) { IEnumerable <IEdmTypeConfiguration> configTypes = types.Concat <IEdmTypeConfiguration>(enumTypes); // build types EdmTypeMap edmTypeMap = EdmTypeBuilder.GetTypesAndProperties(configTypes); Dictionary <Type, IEdmType> edmTypes = edmTypeMap.EdmTypes; // Add an annotate types model.AddTypes(edmTypes); model.AddClrTypeAnnotations(edmTypes); // add annotation for properties Dictionary <PropertyInfo, IEdmProperty> edmProperties = edmTypeMap.EdmProperties; model.AddClrPropertyInfoAnnotations(edmProperties); model.AddPropertyRestrictionsAnnotations(edmTypeMap.EdmPropertiesRestrictions); // add dynamic dictionary property annotation for open types model.AddDynamicPropertyDictionaryAnnotations(edmTypeMap.OpenTypes); return(edmTypes); }
private static void AddExpandRestrictionsAnnotation(this EdmModel model, IEdmEntitySet target, EntitySetConfiguration entitySetConfiguration, EdmTypeMap edmTypeMap) { EntityTypeConfiguration entityTypeConfig = entitySetConfiguration.EntityType; IEnumerable <PropertyConfiguration> nonExpandableProperties = entityTypeConfig.Properties.Where(property => property.NotExpandable); IList <IEdmNavigationProperty> properties = new List <IEdmNavigationProperty>(); foreach (PropertyConfiguration property in nonExpandableProperties) { IEdmProperty value; if (edmTypeMap.EdmProperties.TryGetValue(property.PropertyInfo, out value)) { if (value != null && value.PropertyKind == EdmPropertyKind.Navigation) { properties.Add((IEdmNavigationProperty)value); } } } if (properties.Any()) { model.SetExpandRestrictionsAnnotation(target, true, properties); } }
private static void AddSortRestrictionsAnnotation(this EdmModel model, IEdmEntitySet target, EntitySetConfiguration entitySetConfiguration, EdmTypeMap edmTypeMap) { EntityTypeConfiguration entityTypeConfig = entitySetConfiguration.EntityType; IEnumerable <PropertyConfiguration> nonSortableProperties = entityTypeConfig.Properties.Where(property => property.Unsortable); IList <IEdmProperty> properties = new List <IEdmProperty>(); foreach (PropertyConfiguration property in nonSortableProperties) { IEdmProperty value; if (edmTypeMap.EdmProperties.TryGetValue(property.PropertyInfo, out value)) { if (value != null) { properties.Add(value); } } } if (properties.Any()) { model.SetSortRestrictionsAnnotation(target, true, null, null, properties); } }
private static void AddNavigationRestrictionsAnnotation(this EdmModel model, IEdmEntitySet target, EntitySetConfiguration entitySetConfiguration, EdmTypeMap edmTypeMap) { EntityTypeConfiguration entityTypeConfig = entitySetConfiguration.EntityType; IEnumerable <PropertyConfiguration> notNavigableProperties = entityTypeConfig.Properties.Where(property => property.NotNavigable); IList <Tuple <IEdmNavigationProperty, CapabilitiesNavigationType> > properties = new List <Tuple <IEdmNavigationProperty, CapabilitiesNavigationType> >(); foreach (PropertyConfiguration property in notNavigableProperties) { IEdmProperty value; if (edmTypeMap.EdmProperties.TryGetValue(property.PropertyInfo, out value)) { if (value != null && value.PropertyKind == EdmPropertyKind.Navigation) { properties.Add(new Tuple <IEdmNavigationProperty, CapabilitiesNavigationType>( (IEdmNavigationProperty)value, CapabilitiesNavigationType.Recursive)); } } } if (properties.Any()) { model.SetNavigationRestrictionsAnnotation(target, CapabilitiesNavigationType.Recursive, properties); } }
private static void AddCapabilitiesVocabularyAnnotations(this EdmModel model, IEnumerable <NavigationSourceAndAnnotations> navigationSources, EdmTypeMap edmTypeMap) { Contract.Assert(model != null); Contract.Assert(edmTypeMap != null); if (navigationSources == null) { return; } foreach (NavigationSourceAndAnnotations source in navigationSources) { IEdmEntitySet entitySet = source.NavigationSource as IEdmEntitySet; if (entitySet == null) { continue; } EntitySetConfiguration entitySetConfig = source.Configuration as EntitySetConfiguration; if (entitySetConfig == null) { continue; } model.AddCountRestrictionsAnnotation(entitySet, entitySetConfig, edmTypeMap); model.AddNavigationRestrictionsAnnotation(entitySet, entitySetConfig, edmTypeMap); model.AddFilterRestrictionsAnnotation(entitySet, entitySetConfig, edmTypeMap); model.AddSortRestrictionsAnnotation(entitySet, entitySetConfig, edmTypeMap); model.AddExpandRestrictionsAnnotation(entitySet, entitySetConfig, edmTypeMap); } }
private static void AddOptimisticConcurrencyAnnotation(this EdmModel model, IEdmVocabularyAnnotatable target, NavigationSourceConfiguration navigationSourceConfiguration, EdmTypeMap edmTypeMap) { EntityTypeConfiguration entityTypeConfig = navigationSourceConfiguration.EntityType; IEnumerable <StructuralPropertyConfiguration> concurrencyPropertyies = entityTypeConfig.Properties.OfType <StructuralPropertyConfiguration>().Where(property => property.ConcurrencyToken); IList <IEdmStructuralProperty> edmProperties = new List <IEdmStructuralProperty>(); foreach (StructuralPropertyConfiguration property in concurrencyPropertyies) { IEdmProperty value; if (edmTypeMap.EdmProperties.TryGetValue(property.PropertyInfo, out value)) { var item = value as IEdmStructuralProperty; if (item != null) { edmProperties.Add(item); } } } if (edmProperties.Any()) { IEdmCollectionExpression collectionExpression = new EdmCollectionExpression(edmProperties.Select(p => new EdmPropertyPathExpression(p.Name)).ToArray()); IEdmTerm term = Microsoft.OData.Edm.Vocabularies.V1.CoreVocabularyModel.ConcurrencyTerm; EdmVocabularyAnnotation annotation = new EdmVocabularyAnnotation(target, term, collectionExpression); annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.Inline); model.SetVocabularyAnnotation(annotation); } }
private static void AddCoreVocabularyAnnotations(this EdmModel model, IEnumerable <NavigationSourceAndAnnotations> navigationSources, EdmTypeMap edmTypeMap) { Contract.Assert(model != null); Contract.Assert(edmTypeMap != null); if (navigationSources == null) { return; } foreach (NavigationSourceAndAnnotations source in navigationSources) { IEdmVocabularyAnnotatable navigationSource = source.NavigationSource as IEdmVocabularyAnnotatable; if (navigationSource == null) { continue; } NavigationSourceConfiguration navigationSourceConfig = source.Configuration as NavigationSourceConfiguration; if (navigationSourceConfig == null) { continue; } model.AddOptimisticConcurrencyAnnotation(navigationSource, navigationSourceConfig, edmTypeMap); } }
private static IDictionary <string, EdmNavigationSource> GetNavigationSourceMap(this EdmModel model, EdmTypeMap edmMap, IEnumerable <NavigationSourceAndAnnotations> navigationSourceAndAnnotations) { // index the navigation source by name Dictionary <string, EdmNavigationSource> edmNavigationSourceMap = navigationSourceAndAnnotations.ToDictionary(e => e.NavigationSource.Name, e => e.NavigationSource); // apply the annotations foreach (NavigationSourceAndAnnotations navigationSourceAndAnnotation in navigationSourceAndAnnotations) { EdmNavigationSource navigationSource = navigationSourceAndAnnotation.NavigationSource; model.SetAnnotationValue(navigationSource, navigationSourceAndAnnotation.Url); model.SetNavigationSourceLinkBuilder(navigationSource, navigationSourceAndAnnotation.LinkBuilder); AddNavigationBindings(edmMap, navigationSourceAndAnnotation.Configuration, navigationSource, navigationSourceAndAnnotation.LinkBuilder, edmNavigationSourceMap); } return(edmNavigationSourceMap); }