private void VerifyFindDerivedType(IEnumerable <XElement> sourceCsdls, IEdmModel testModel) { Func <IEdmStructuredType, string> getFullName = (type) => { return(type as IEdmComplexType != null ? ((IEdmComplexType)type).FullName() : type as IEdmEntityType != null ? ((IEdmEntityType)type).FullName() : null); }; Func <IEdmStructuredType, string> getNamespace = (type) => { return(type as IEdmComplexType != null ? ((IEdmComplexType)type).Namespace : type as IEdmEntityType != null ? ((IEdmEntityType)type).Namespace : null); }; Action <IEdmStructuredType, string> checkFindAllDerivedFunction = (structuredType, structuralTypeElementName) => { var expectedResults = EdmLibCsdlContentGenerator.GetDerivedTypes(sourceCsdls, structuralTypeElementName, getFullName(structuredType)); var actualResults = testModel.FindAllDerivedTypes(structuredType).Select(n => getFullName(n)); Assert.IsTrue(expectedResults.Count() == actualResults.Count() && !expectedResults.Except(actualResults).Any(), "FindAllDerivedTypes returns unexpected results."); }; Action <IEdmStructuredType, string> checkFindDirectlyDerivedFunction = (structuredType, structuralTypeElementName) => { var expectedResults = EdmLibCsdlContentGenerator.GetDirectlyDerivedTypes(sourceCsdls, structuralTypeElementName, getFullName(structuredType)); var actualResults = testModel.FindDirectlyDerivedTypes(structuredType).Select(n => getFullName(n)); Assert.IsTrue(expectedResults.Count() == actualResults.Count() && !expectedResults.Except(actualResults).Any(), "FindDirectlyDerivedTypes returns unexpected results."); }; IEnumerable <EdmError> edmErrors; testModel.Validate(out edmErrors); var structuredTypes = testModel.SchemaElements.OfType <IEdmStructuredType>(); foreach (var structuredType in structuredTypes) { if (edmErrors.Any(n => n.ErrorCode == EdmErrorCode.BadCyclicEntity && n.ErrorMessage.Contains(getFullName(structuredType)))) { Assert.IsTrue(0 == testModel.FindDirectlyDerivedTypes(structuredType).Count(), "FindDirectlyDerivedTypes returns unexpected results."); Assert.IsTrue(0 == testModel.FindAllDerivedTypes(structuredType).Count(), "FindAllDerivedTypes returns unexpected results."); } else { if (structuredType is IEdmEntityType) { checkFindDirectlyDerivedFunction(structuredType, "EntityType"); checkFindAllDerivedFunction(structuredType, "EntityType"); } else if (structuredType is IEdmComplexType) { checkFindDirectlyDerivedFunction(structuredType, "ComplexType"); checkFindAllDerivedFunction(structuredType, "ComplexType"); } } } }
public void FullTest() { IEdmModel model = NewModel(); // Find a type (complex or entity or enum). var orderType = model.FindDeclaredType("Sample.NS.Order"); TestContext.WriteLine("{0} type '{1}' found.", orderType.TypeKind, orderType.FullName()); var addressType = model.FindDeclaredType("Sample.NS.Address"); TestContext.WriteLine("{0} type '{1}' found.", addressType.TypeKind, addressType); // Find derived type of some type. var workAddressType = model.FindAllDerivedTypes((IEdmStructuredType)addressType).Single(); TestContext.WriteLine("Type '{0}' is the derived from '{1}'.", ((IEdmSchemaType)workAddressType).Name, addressType.Name); // Find an operation. var rateAction = model.FindDeclaredOperations("Sample.NS.Rate").Single(); TestContext.WriteLine("{0} '{1}' found.", rateAction.SchemaElementKind, rateAction.Name); // Find an operation import. var mostValuableFunctionImport = model.FindDeclaredOperationImports("MostValuable").Single(); TestContext.WriteLine("{0} '{1}' found.", mostValuableFunctionImport.ContainerElementKind, mostValuableFunctionImport.Name); // Find an annotation and get its value. var customerSet = model.FindDeclaredEntitySet("Customers"); var maxCountAnnotation = model.FindDeclaredVocabularyAnnotations(customerSet).Single(); var maxCountValue = ((IEdmIntegerValue)maxCountAnnotation.Value).Value; TestContext.WriteLine("'{0}' = '{1}' on '{2}'", maxCountAnnotation.Term.Name, maxCountValue, ((IEdmEntitySet)maxCountAnnotation.Target).Name); }
internal EntitySetInfo(IEdmModel edmModel, IEdmEntitySet edmEntitySet, ITypeResolver typeResolver) { Contract.Assert(edmModel != null); Contract.Assert(edmEntitySet != null); Contract.Assert(typeResolver != null); Name = edmEntitySet.Name; ElementType = new EntityTypeInfo(edmModel, edmEntitySet.ElementType, typeResolver); var entityTypes = new List<EntityTypeInfo>(3) { ElementType }; // Create an EntityTypeInfo for any derived types in the model foreach (var edmDerivedType in edmModel.FindAllDerivedTypes(edmEntitySet.ElementType).OfType<IEdmEntityType>()) { entityTypes.Add(new EntityTypeInfo(edmModel, edmDerivedType, typeResolver)); } // Connect any derived types with their base class for (int i = 1; i < entityTypes.Count; ++i) { var baseEdmEntityType = entityTypes[i].EdmEntityType.BaseEntityType(); if (baseEdmEntityType != null) { var baseEntityTypeInfo = entityTypes.First(entityTypeInfo => entityTypeInfo.EdmEntityType == baseEdmEntityType); if (baseEntityTypeInfo != null) { entityTypes[i].BaseTypeInfo = baseEntityTypeInfo; } } } EntityTypes = entityTypes; }
public override string GetDerivedEntityTypeExactName(string collectionName, string entityTypeName) { IEdmEntityType entityType; if (TryGetEntitySet(collectionName, out var entitySet)) { entityType = (_model.FindAllDerivedTypes(entitySet.EntityType()) .BestMatch(x => (x as IEdmEntityType).Name, entityTypeName, NameMatchResolver)) as IEdmEntityType; if (entityType != null) { return(entityType.Name); } } else if (TryGetSingleton(collectionName, out var singleton)) { entityType = (_model.FindDirectlyDerivedTypes(singleton.EntityType()) .BestMatch(x => (x as IEdmEntityType).Name, entityTypeName, NameMatchResolver)) as IEdmEntityType; if (entityType != null) { return(entityType.Name); } } else if (TryGetEntityType(entityTypeName, out entityType)) { return(entityType.Name); } throw new UnresolvableObjectException(entityTypeName, $"Entity type [{entityTypeName}] not found"); }
public override string GetDerivedEntityTypeExactName(string collectionName, string entityTypeName) { IEdmEntitySet entitySet; IEdmSingleton singleton; IEdmEntityType entityType; if (TryGetEntitySet(collectionName, out entitySet)) { entityType = (_model.FindAllDerivedTypes(entitySet.EntityType()) .BestMatch(x => (x as IEdmEntityType).Name, entityTypeName, _session.Pluralizer)) as IEdmEntityType; if (entityType != null) { return(entityType.Name); } } else if (TryGetSingleton(collectionName, out singleton)) { entityType = (_model.FindDirectlyDerivedTypes(singleton.EntityType()) .BestMatch(x => (x as IEdmEntityType).Name, entityTypeName, _session.Pluralizer)) as IEdmEntityType; if (entityType != null) { return(entityType.Name); } } else if (TryGetEntityType(entityTypeName, out entityType)) { return(entityType.Name); } throw new UnresolvableObjectException(entityTypeName, string.Format("Entity type [{0}] not found", entityTypeName)); }
internal static bool TypeIndirectlyContainsTarget(IEdmEntityType source, IEdmEntityType target, HashSetInternal <IEdmEntityType> visited, IEdmModel context) { if (visited.Add(source)) { if (source.IsOrInheritsFrom(target)) { return(true); } foreach (IEdmNavigationProperty navProp in source.NavigationProperties()) { if (navProp.ContainsTarget && TypeIndirectlyContainsTarget(navProp.ToEntityType(), target, visited, context)) { return(true); } } foreach (IEdmStructuredType derived in context.FindAllDerivedTypes(source)) { IEdmEntityType derivedEntity = derived as IEdmEntityType; if (derivedEntity != null && TypeIndirectlyContainsTarget(derivedEntity, target, visited, context)) { return(true); } } } return(false); }
private static bool HasAutoExpandProperty(this IEdmModel edmModel, IEdmStructuredType structuredType, IEdmProperty pathProperty, ISet <IEdmStructuredType> visited) { if (visited.Contains(structuredType)) { return(false); } visited.Add(structuredType); List <IEdmStructuredType> structuredTypes = new List <IEdmStructuredType>(); structuredTypes.Add(structuredType); structuredTypes.AddRange(edmModel.FindAllDerivedTypes(structuredType)); foreach (IEdmStructuredType edmStructuredType in structuredTypes) { // for top type, let's retrieve its properties and the properties from base type of top type if has. // for derived type, let's retrieve the declared properties. IEnumerable <IEdmProperty> properties = edmStructuredType == structuredType ? edmStructuredType.Properties() : edmStructuredType.DeclaredProperties; foreach (IEdmProperty property in properties) { switch (property.PropertyKind) { case EdmPropertyKind.Structural: IEdmStructuralProperty structuralProperty = (IEdmStructuralProperty)property; IEdmTypeReference typeRef = property.Type.GetElementTypeOrSelf(); if (typeRef.IsComplex() && edmModel.CanExpand(typeRef.AsComplex().ComplexDefinition(), structuralProperty)) { IEdmStructuredType subStrucutredType = typeRef.AsStructured().StructuredDefinition(); if (edmModel.HasAutoExpandProperty(subStrucutredType, structuralProperty, visited)) { return(true); } } break; case EdmPropertyKind.Navigation: IEdmNavigationProperty navigationProperty = (IEdmNavigationProperty)property; if (IsAutoExpand(navigationProperty, pathProperty, edmStructuredType, edmModel)) { return(true); // find an auto-expand navigation property path } break; } } } return(false); }
/// <summary> /// Find the given type in a structured type inheritance, include itself. /// </summary> /// <param name="structuralType">The starting structural type.</param> /// <param name="model">The Edm model.</param> /// <param name="typeName">The searching type name.</param> /// <returns>The found type.</returns> public static IEdmStructuredType FindTypeInInheritance(this IEdmStructuredType structuralType, IEdmModel model, string typeName) { IEdmStructuredType baseType = structuralType; while (baseType != null) { if (GetName(baseType) == typeName) { return(baseType); } baseType = baseType.BaseType; } return(model.FindAllDerivedTypes(structuralType).FirstOrDefault(c => GetName(c) == typeName)); }
/// <summary> /// Gets the auto select paths. /// </summary> /// <param name="edmModel">The Edm model.</param> /// <param name="structuredType">The Edm structured type.</param> /// <param name="pathProperty">The property from path, it can be null.</param> /// <param name="querySettings">The query settings.</param> /// <returns>The auto select paths.</returns> public static IList <SelectModelPath> GetAutoSelectPaths(this IEdmModel edmModel, IEdmStructuredType structuredType, IEdmProperty pathProperty, ModelBoundQuerySettings querySettings = null) { if (edmModel == null) { throw Error.ArgumentNull(nameof(edmModel)); } if (structuredType == null) { throw Error.ArgumentNull(nameof(structuredType)); } List <SelectModelPath> autoSelectProperties = new List <SelectModelPath>(); List <IEdmStructuredType> structuredTypes = new List <IEdmStructuredType>(); structuredTypes.Add(structuredType); structuredTypes.AddRange(edmModel.FindAllDerivedTypes(structuredType)); foreach (IEdmStructuredType edmStructuredType in structuredTypes) { // for top type, let's retrieve its properties and the properties from base type of top type if has. // for derived type, let's retrieve the declared properties. IEnumerable <IEdmStructuralProperty> properties = (edmStructuredType == structuredType) ? edmStructuredType.StructuralProperties() : properties = edmStructuredType.DeclaredStructuralProperties(); foreach (IEdmStructuralProperty property in properties) { if (IsAutoSelect(property, pathProperty, edmStructuredType, edmModel, querySettings)) { if (edmStructuredType == structuredType) { autoSelectProperties.Add(new SelectModelPath(new[] { property })); } else { autoSelectProperties.Add(new SelectModelPath(new IEdmElement[] { edmStructuredType, property })); } } } } return(autoSelectProperties); }
/// <summary> /// Find the given type in a structured type inheritance, include itself. /// </summary> /// <param name="structuralType">The starting structural type.</param> /// <param name="model">The Edm model.</param> /// <param name="typeName">The searching type name.</param> /// <param name="caseInsensitive">If true, performs case insensitive search</param> /// <returns>The found type.</returns> public static IEdmStructuredType FindTypeInInheritance(this IEdmStructuredType structuralType, IEdmModel model, string typeName, bool caseInsensitive = false) { StringComparison typeStringComparison = caseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; IEdmStructuredType baseType = structuralType; while (baseType != null) { if (GetName(baseType).Equals(typeName, typeStringComparison)) { return(baseType); } baseType = baseType.BaseType; } return(model.FindAllDerivedTypes(structuralType).FirstOrDefault(c => GetName(c).Equals(typeName, typeStringComparison))); }
/// <summary> /// Initializes a new instance of the <see cref="NavigationSourceLinkBuilderAnnotation"/> class. /// </summary> /// <param name="navigationSource">The navigation source for which the link builder is being constructed.</param> /// <param name="model">The EDM model that this navigation source belongs to.</param> /// <remarks>This constructor creates a link builder that generates URL's that follow OData conventions for the given navigation source.</remarks> public NavigationSourceLinkBuilderAnnotation(IEdmNavigationSource navigationSource, IEdmModel model) { if (navigationSource == null) { throw Error.ArgumentNull("navigationSource"); } if (model == null) { throw Error.ArgumentNull("model"); } IEdmEntityType elementType = navigationSource.EntityType(); IEnumerable <IEdmEntityType> derivedTypes = model.FindAllDerivedTypes(elementType).Cast <IEdmEntityType>(); // Add navigation link builders for all navigation properties of entity. foreach (IEdmNavigationProperty navigationProperty in elementType.NavigationProperties()) { Func <EntityInstanceContext, IEdmNavigationProperty, Uri> navigationLinkFactory = (entityInstanceContext, navProperty) => entityInstanceContext.GenerateNavigationPropertyLink(navProperty, includeCast: false); AddNavigationPropertyLinkBuilder(navigationProperty, new NavigationLinkBuilder(navigationLinkFactory, followsConventions: true)); } // Add navigation link builders for all navigation properties in derived types. bool derivedTypesDefineNavigationProperty = false; foreach (IEdmEntityType derivedEntityType in derivedTypes) { foreach (IEdmNavigationProperty navigationProperty in derivedEntityType.DeclaredNavigationProperties()) { derivedTypesDefineNavigationProperty = true; Func <EntityInstanceContext, IEdmNavigationProperty, Uri> navigationLinkFactory = (entityInstanceContext, navProperty) => entityInstanceContext.GenerateNavigationPropertyLink(navProperty, includeCast: true); AddNavigationPropertyLinkBuilder(navigationProperty, new NavigationLinkBuilder(navigationLinkFactory, followsConventions: true)); } } _navigationSourceName = navigationSource.Name; Func <EntityInstanceContext, Uri> selfLinkFactory = (entityInstanceContext) => entityInstanceContext.GenerateSelfLink(includeCast: derivedTypesDefineNavigationProperty); _idLinkBuilder = new SelfLinkBuilder <Uri>(selfLinkFactory, followsConventions: true); }
/// <summary> /// Initializes a new instance of the <see cref="EntitySetLinkBuilderAnnotation"/> class. /// </summary> /// <param name="entitySet">The entity set for which the link builder is being constructed.</param> /// <param name="model">The EDM model that this entity set belongs to.</param> /// <remarks>This constructor creates a link builder that generates URL's that follow OData conventions for the given entity set.</remarks> public EntitySetLinkBuilderAnnotation(IEdmEntitySet entitySet, IEdmModel model) { if (entitySet == null) { throw Error.ArgumentNull("entitySet"); } if (model == null) { throw Error.ArgumentNull("model"); } IEdmEntityType elementType = entitySet.ElementType; IEnumerable <IEdmEntityType> derivedTypes = model.FindAllDerivedTypes(elementType).Cast <IEdmEntityType>(); bool derivedTypesDefineNavigationProperty = false; // Add navigation link builders for all navigation properties of entity. foreach (IEdmNavigationProperty navigationProperty in elementType.NavigationProperties()) { Func <EntityInstanceContext, IEdmNavigationProperty, Uri> navigationLinkFactory = (entityInstanceContext, navProperty) => entityInstanceContext.GenerateNavigationPropertyLink(navProperty, includeCast: false); AddNavigationPropertyLinkBuilder(navigationProperty, new NavigationLinkBuilder(navigationLinkFactory, followsConventions: true)); } // Add navigation link builders for all navigation properties in derived types. foreach (IEdmEntityType derivedEntityType in derivedTypes) { foreach (IEdmNavigationProperty navigationProperty in derivedEntityType.DeclaredNavigationProperties()) { derivedTypesDefineNavigationProperty = true; Func <EntityInstanceContext, IEdmNavigationProperty, Uri> navigationLinkFactory = (entityInstanceContext, navProperty) => entityInstanceContext.GenerateNavigationPropertyLink(navProperty, includeCast: true); AddNavigationPropertyLinkBuilder(navigationProperty, new NavigationLinkBuilder(navigationLinkFactory, followsConventions: true)); } } _entitySetName = entitySet.Name; _feedSelfLinkBuilder = (feedContext) => feedContext.GenerateFeedSelfLink(); Func <EntityInstanceContext, string> selfLinkFactory = (entityInstanceContext) => entityInstanceContext.GenerateSelfLink(includeCast: derivedTypesDefineNavigationProperty); _idLinkBuilder = new SelfLinkBuilder <string>(selfLinkFactory, followsConventions: true); }
/// <summary> /// Initializes a new instance of the <see cref="NavigationSourceLinkBuilderAnnotation"/> class. /// </summary> /// <param name="navigationSource">The navigation source for which the link builder is being constructed.</param> /// <param name="model">The EDM model that this navigation source belongs to.</param> /// <remarks>This constructor creates a link builder that generates URL's that follow OData conventions for the given navigation source.</remarks> public NavigationSourceLinkBuilderAnnotation(IEdmNavigationSource navigationSource, IEdmModel model) { if (navigationSource == null) { throw Error.ArgumentNull("navigationSource"); } if (model == null) { throw Error.ArgumentNull("model"); } IEdmEntityType elementType = navigationSource.EntityType(); IEnumerable<IEdmEntityType> derivedTypes = model.FindAllDerivedTypes(elementType).Cast<IEdmEntityType>(); // Add navigation link builders for all navigation properties of entity. foreach (IEdmNavigationProperty navigationProperty in elementType.NavigationProperties()) { Func<EntityInstanceContext, IEdmNavigationProperty, Uri> navigationLinkFactory = (entityInstanceContext, navProperty) => entityInstanceContext.GenerateNavigationPropertyLink(navProperty, includeCast: false); AddNavigationPropertyLinkBuilder(navigationProperty, new NavigationLinkBuilder(navigationLinkFactory, followsConventions: true)); } // Add navigation link builders for all navigation properties in derived types. bool derivedTypesDefineNavigationProperty = false; foreach (IEdmEntityType derivedEntityType in derivedTypes) { foreach (IEdmNavigationProperty navigationProperty in derivedEntityType.DeclaredNavigationProperties()) { derivedTypesDefineNavigationProperty = true; Func<EntityInstanceContext, IEdmNavigationProperty, Uri> navigationLinkFactory = (entityInstanceContext, navProperty) => entityInstanceContext.GenerateNavigationPropertyLink(navProperty, includeCast: true); AddNavigationPropertyLinkBuilder(navigationProperty, new NavigationLinkBuilder(navigationLinkFactory, followsConventions: true)); } } _navigationSourceName = navigationSource.Name; _feedSelfLinkBuilder = (feedContext) => feedContext.GenerateFeedSelfLink(); Func<EntityInstanceContext, string> selfLinkFactory = (entityInstanceContext) => entityInstanceContext.GenerateSelfLink(includeCast: derivedTypesDefineNavigationProperty); _idLinkBuilder = new SelfLinkBuilder<string>(selfLinkFactory, followsConventions: true); }
internal static bool TypeIndirectlyContainsTarget(IEdmEntityType source, IEdmEntityType target, HashSetInternal <IEdmEntityType> visited, IEdmModel context) { bool flag; if (visited.Add(source)) { if (!source.IsOrInheritsFrom(target)) { foreach (IEdmNavigationProperty edmNavigationProperty in source.NavigationProperties()) { if (!edmNavigationProperty.ContainsTarget || !ValidationHelper.TypeIndirectlyContainsTarget(edmNavigationProperty.ToEntityType(), target, visited, context)) { continue; } flag = true; return(flag); } IEnumerator <IEdmStructuredType> enumerator = context.FindAllDerivedTypes(source).GetEnumerator(); using (enumerator) { while (enumerator.MoveNext()) { IEdmStructuredType current = enumerator.Current; IEdmEntityType edmEntityType = current as IEdmEntityType; if (edmEntityType == null || !ValidationHelper.TypeIndirectlyContainsTarget(edmEntityType, target, visited, context)) { continue; } flag = true; return(flag); } return(false); } return(flag); } else { return(true); } } return(false); }
public override string GetDerivedEntityTypeExactName(string collectionName, string entityTypeName) { IEdmEntitySet entitySet; IEdmEntityType entityType; if (TryGetEntitySet(collectionName, out entitySet)) { entityType = (_model.FindAllDerivedTypes(entitySet.ElementType) .BestMatch(x => (x as IEdmEntityType).Name, entityTypeName, _session.Settings.NameMatchResolver) as IEdmEntityType); if (entityType != null) { return(entityType.Name); } } else if (TryGetEntityType(entityTypeName, out entityType)) { return(entityType.Name); } throw new UnresolvableObjectException(entityTypeName, string.Format("Entity type [{0}] not found", entityTypeName)); }
/// <summary> /// Tests whether there are auto select properties. /// So far, we only test one depth for auto select, shall we go through the deeper depth? /// </summary> /// <param name="edmModel">The Edm model.</param> /// <param name="structuredType">The type from value or from path.</param> /// <param name="property">The property from path, it can be null.</param> /// <returns>true if the structured type has auto select properties; otherwise false.</returns> public static bool HasAutoSelectProperty(this IEdmModel edmModel, IEdmStructuredType structuredType, IEdmProperty property) { if (edmModel == null) { throw Error.ArgumentNull(nameof(edmModel)); } if (structuredType == null) { throw Error.ArgumentNull(nameof(structuredType)); } List <IEdmStructuredType> structuredTypes = new List <IEdmStructuredType>(); structuredTypes.Add(structuredType); structuredTypes.AddRange(edmModel.FindAllDerivedTypes(structuredType)); foreach (IEdmStructuredType edmStructuredType in structuredTypes) { // for top type, let's retrieve its properties and the properties from base type of top type if has. // for derived type, let's retrieve the declared properties. IEnumerable <IEdmStructuralProperty> properties = edmStructuredType == structuredType ? edmStructuredType.StructuralProperties() : edmStructuredType.DeclaredStructuralProperties(); foreach (IEdmStructuralProperty subProperty in properties) { if (IsAutoSelect(subProperty, property, edmStructuredType, edmModel)) { return(true); } } } return(false); }
/// <summary> /// Function to find the name of the type/class being used by identifier that is the last item in the path collection. /// This function can make recursive calls /// </summary> /// <param name="definition"><see cref="IEdmType"/> that has properties to be searched into</param> /// <param name="searchPath">List of string that shows the depth of the search into the definition from the odataPath type definition</param> /// <param name="searchingParent">Denotes whether we are searching for the property in parent classes</param> /// <returns>pair of Edm type name and whether type is found as navigation property</returns> public (IEdmType type, bool isNavigationProperty) SearchForEdmType(IEdmType definition, ICollection <string> searchPath, bool searchingParent = false) { // if the type is a collection, use the type of the element of the collection var elementDefinition = GetEdmElementType(definition); // we are at the root of the search so just return the definition of the root item if (searchPath.Count <= 1) { return(elementDefinition, false); } // Find all derived types. This is required in cases where the path refers to a parent class, // but the searched propery belongs to the child class. // Example: "post/attachments" path refers to attachments as "Attachment", but one can have a "FileAttachment" // in post. "ContentBytes", which exists only on the derived class, doesn't show up if looked in "Attachment". // We are also checking if we are searching parent classes at the moment for inherited properties. If that is the case, // we don't go to derived types, because that would cause searching for properties in sibling classes. // It can cause infinite loop if the property is not found, because we have a way of both going up and down in the // class hierarchy. IEnumerable <IEdmStructuredType> derivedTypes = null; if (!searchingParent && elementDefinition is IEdmStructuredType structuredTypeDefinition) { derivedTypes = Model?.FindAllDerivedTypes(structuredTypeDefinition); } // the second element in the path is the property we are searching for var searchIdentifier = searchPath.ElementAt(1); // Loop through the properties of the entity if is structured if (elementDefinition is IEdmStructuredType structuredType) { foreach (var property in structuredType.DeclaredProperties) { if (property.Name.Equals(searchIdentifier, StringComparison.OrdinalIgnoreCase)) { elementDefinition = GetEdmElementType(property.Type.Definition); // check if we need to search deeper to search the properties of a nested item if (searchPath.Count > 2) { // get rid of the root item and do a deeper search var subList = searchPath.Where(x => !x.Equals(searchPath.First(), StringComparison.OrdinalIgnoreCase)).ToList(); return(SearchForEdmType(property.Type.Definition, subList)); } else { return(elementDefinition, property.PropertyKind == EdmPropertyKind.Navigation); } } } // search in derived types if (derivedTypes is object) { foreach (var derivedType in derivedTypes) { var(result, isNavigationProperty) = SearchForEdmType(derivedType, searchPath); if (result != null) { return(result, isNavigationProperty); } } } // check properties of the base type as it may be inherited return(SearchForEdmType(structuredType.BaseType, searchPath, searchingParent: true)); } // search failed so return null type return(null, false); }
internal static bool TypeIndirectlyContainsTarget(IEdmEntityType source, IEdmEntityType target, HashSetInternal<IEdmEntityType> visited, IEdmModel context) { if (visited.Add(source)) { if (source.IsOrInheritsFrom(target)) { return true; } foreach (IEdmNavigationProperty navProp in source.NavigationProperties()) { if (navProp.ContainsTarget && TypeIndirectlyContainsTarget(navProp.ToEntityType(), target, visited, context)) { return true; } } foreach (IEdmStructuredType derived in context.FindAllDerivedTypes(source)) { IEdmEntityType derivedEntity = derived as IEdmEntityType; if (derivedEntity != null && TypeIndirectlyContainsTarget(derivedEntity, target, visited, context)) { return true; } } } return false; }
public static IEnumerable <IEdmStructuredType> DerivedTypes(this IEdmStructuredType structuralType, IEdmModel model) { return(model.FindAllDerivedTypes(structuralType)); }
/// <summary> /// /// </summary> /// <param name="context"></param> public bool AppliesToAction(ODataControllerActionContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } // use the cached Debug.Assert(context.Singleton != null); Debug.Assert(context.Action != null); ActionModel action = context.Action; string singletonName = context.Singleton.Name; string prefix = context.Prefix; IEdmModel model = context.Model; string actionMethodName = action.ActionMethod.Name; if (IsSupportedActionName(actionMethodName, singletonName)) { ODataPathTemplate template = new ODataPathTemplate(new SingletonSegmentTemplate(context.Singleton)); action.AddSelector(context.Prefix, context.Model, template); // processed return(true); } // type cast // Get{SingletonName}From{EntityTypeName} or GetFrom{EntityTypeName} int index = actionMethodName.IndexOf("From", StringComparison.Ordinal); if (index == -1) { return(false); } string actionPrefix = actionMethodName.Substring(0, index); if (IsSupportedActionName(actionPrefix, singletonName)) { IEdmEntityType entityType = context.Singleton.EntityType(); string castTypeName = actionMethodName.Substring(index + 4); // Shall we cast to base type and the type itself? I think yes. IEdmEntityType baseType = entityType; while (baseType != null) { if (baseType.Name == castTypeName) { ODataPathTemplate template = new ODataPathTemplate(new SingletonSegmentTemplate(context.Singleton), new CastSegmentTemplate(baseType)); action.AddSelector(context.Prefix, context.Model, template); return(true); } baseType = baseType.BaseEntityType(); } // shall we cast to derived type IEdmEntityType castType = model.FindAllDerivedTypes(entityType).OfType <IEdmEntityType>().FirstOrDefault(c => c.Name == castTypeName); if (castType != null) { ODataPathTemplate template = new ODataPathTemplate(new SingletonSegmentTemplate(context.Singleton), new CastSegmentTemplate(castType)); action.AddSelector(context.Prefix, context.Model, template); return(true); } } return(false); }
private static void GetAutoExpandPaths(this IEdmModel edmModel, IEdmStructuredType structuredType, IEdmProperty pathProperty, Stack <IEdmElement> nodes, ISet <IEdmStructuredType> visited, IList <ExpandModelPath> results, bool isSelectPresent = false, ModelBoundQuerySettings querySettings = null) { if (visited.Contains(structuredType)) { return; } visited.Add(structuredType); List <IEdmStructuredType> structuredTypes = new List <IEdmStructuredType>(); structuredTypes.Add(structuredType); structuredTypes.AddRange(edmModel.FindAllDerivedTypes(structuredType)); foreach (IEdmStructuredType edmStructuredType in structuredTypes) { IEnumerable <IEdmProperty> properties; if (edmStructuredType == structuredType) { // for base type, let's retrieve its properties and the properties from base type of base type if have. properties = edmStructuredType.Properties(); } else { // for derived type, let's retrieve the declared properties. properties = edmStructuredType.DeclaredProperties; nodes.Push(edmStructuredType); // add a type cast for derived type } foreach (IEdmProperty property in properties) { switch (property.PropertyKind) { case EdmPropertyKind.Structural: IEdmStructuralProperty structuralProperty = (IEdmStructuralProperty)property; IEdmTypeReference typeRef = property.Type.GetElementTypeOrSelf(); if (typeRef.IsComplex() && edmModel.CanExpand(typeRef.AsComplex().ComplexDefinition(), structuralProperty)) { IEdmStructuredType subStructuredType = typeRef.AsStructured().StructuredDefinition(); nodes.Push(structuralProperty); edmModel.GetAutoExpandPaths(subStructuredType, structuralProperty, nodes, visited, results, isSelectPresent, querySettings); nodes.Pop(); } break; case EdmPropertyKind.Navigation: IEdmNavigationProperty navigationProperty = (IEdmNavigationProperty)property; if (IsAutoExpand(navigationProperty, pathProperty, edmStructuredType, edmModel, isSelectPresent, querySettings)) { nodes.Push(navigationProperty); results.Add(new ExpandModelPath(nodes.Reverse())); // found an auto-expand navigation property path nodes.Pop(); } break; } } if (edmStructuredType != structuredType) { nodes.Pop(); // pop the type cast for derived type } } }
internal static bool TypeIndirectlyContainsTarget(IEdmEntityType source, IEdmEntityType target, HashSetInternal<IEdmEntityType> visited, IEdmModel context) { bool flag; if (visited.Add(source)) { if (!source.IsOrInheritsFrom(target)) { foreach (IEdmNavigationProperty edmNavigationProperty in source.NavigationProperties()) { if (!edmNavigationProperty.ContainsTarget || !ValidationHelper.TypeIndirectlyContainsTarget(edmNavigationProperty.ToEntityType(), target, visited, context)) { continue; } flag = true; return flag; } IEnumerator<IEdmStructuredType> enumerator = context.FindAllDerivedTypes(source).GetEnumerator(); using (enumerator) { while (enumerator.MoveNext()) { IEdmStructuredType current = enumerator.Current; IEdmEntityType edmEntityType = current as IEdmEntityType; if (edmEntityType == null || !ValidationHelper.TypeIndirectlyContainsTarget(edmEntityType, target, visited, context)) { continue; } flag = true; return flag; } return false; } return flag; } else { return true; } } return false; }
/// <summary> /// Create OData type cast paths. /// </summary> /// <param name="currentPath">The current OData path.</param> /// <param name="convertSettings">The settings for the current conversion.</param> /// <param name="structuredType">The type that is being inherited from to which this method will add downcast path segments.</param> /// <param name="annotable">The annotable navigation source to read cast annotations from.</param> /// <param name="targetsMany">Whether the annotable navigation source targets many entities.</param> private void CreateTypeCastPaths(ODataPath currentPath, OpenApiConvertSettings convertSettings, IEdmStructuredType structuredType, IEdmVocabularyAnnotatable annotable, bool targetsMany) { if (currentPath == null) { throw Error.ArgumentNull(nameof(currentPath)); } if (convertSettings == null) { throw Error.ArgumentNull(nameof(convertSettings)); } if (structuredType == null) { throw Error.ArgumentNull(nameof(structuredType)); } if (annotable == null) { throw Error.ArgumentNull(nameof(annotable)); } if (!convertSettings.EnableODataTypeCast) { return; } var annotedTypeNames = GetDerivedTypeConstaintTypeNames(annotable); if (!annotedTypeNames.Any() && convertSettings.RequireDerivedTypesConstraintForODataTypeCastSegments) { return; // we don't want to generate any downcast path item if there is no type cast annotation. } var annotedTypeNamesSet = new HashSet <string>(annotedTypeNames, StringComparer.OrdinalIgnoreCase); bool filter(IEdmStructuredType x) => convertSettings.RequireDerivedTypesConstraintForODataTypeCastSegments && annotedTypeNames.Contains(x.FullTypeName()) || !convertSettings.RequireDerivedTypesConstraintForODataTypeCastSegments && ( !annotedTypeNames.Any() || annotedTypeNames.Contains(x.FullTypeName()) ); var targetTypes = _model .FindAllDerivedTypes(structuredType) .Where(x => (x.TypeKind == EdmTypeKind.Entity || x.TypeKind == EdmTypeKind.Complex) && filter(x)) .OfType <IEdmStructuredType>() .ToArray(); foreach (var targetType in targetTypes) { var castPath = currentPath.Clone(); var targetTypeSegment = new ODataTypeCastSegment(targetType); castPath.Push(targetTypeSegment); AppendPath(castPath); if (targetsMany) { CreateCountPath(castPath, convertSettings); } else { if (convertSettings.ExpandDerivedTypesNavigationProperties) { foreach (var declaredNavigationProperty in targetType.DeclaredNavigationProperties()) { RetrieveNavigationPropertyPaths(declaredNavigationProperty, null, castPath, convertSettings); } } } } }