예제 #1
0
        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);
                //}
            }
        }
예제 #2
0
        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.AddClrEnumMemberInfoAnnotations(edmTypeMap);
            model.AddPropertyRestrictionsAnnotations(edmTypeMap.EdmPropertiesRestrictions);
            model.AddPropertiesQuerySettings(edmTypeMap.EdmPropertiesQuerySettings);
            model.AddStructuredTypeQuerySettings(edmTypeMap.EdmStructuredTypeQuerySettings);

            // add dynamic dictionary property annotation for open types
            model.AddDynamicPropertyDictionaryAnnotations(edmTypeMap.OpenTypes);

            // add instance annotation dictionary property annotations
            model.AddInstanceAnnotationsContainer(edmTypeMap.InstanceAnnotatableTypes);

            return(edmTypes);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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)));
            }
        }
예제 #5
0
        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));
        }
예제 #6
0
        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);
            }
        }
예제 #7
0
        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);
            }
        }
예제 #8
0
        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);
            }
        }
예제 #9
0
        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);
            }
        }
예제 #10
0
        private static void AddOptimisticConcurrencyAnnotation(this EdmModel model, IEdmVocabularyAnnotatable target,
                                                               NavigationSourceConfiguration navigationSourceConfiguration, EdmTypeMap edmTypeMap)
        {
            EntityTypeConfiguration entityTypeConfig = navigationSourceConfiguration.EntityType;

            IEnumerable <StructuralPropertyConfiguration> concurrencyProperties =
                entityTypeConfig.Properties.OfType <StructuralPropertyConfiguration>().Where(property => property.ConcurrencyToken);

            foreach (var baseType in entityTypeConfig.BaseTypes())
            {
                concurrencyProperties = concurrencyProperties.Concat(
                    baseType.Properties.OfType <StructuralPropertyConfiguration>().Where(property => property.ConcurrencyToken));
            }

            IList <IEdmStructuralProperty> edmProperties = new List <IEdmStructuralProperty>();

            foreach (StructuralPropertyConfiguration property in concurrencyProperties)
            {
                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);
            }
        }
예제 #11
0
        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);
            }
        }
예제 #12
0
        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);
        }