private static ApiPropertyConfiguration GetOrAddApiPropertyConfiguration(ApiMutableObjectType apiMutableObjectType, Type clrDeclaringType, string clrPropertyName, Type clrPropertyType, ApiPrecedenceLevel apiPrecedenceLevel, ApiPrecedenceStack apiPrecedenceStack) { Contract.Requires(apiMutableObjectType != null); Contract.Requires(clrDeclaringType != null); Contract.Requires(clrPropertyName.SafeHasContent()); Contract.Requires(clrPropertyType != null); Contract.Requires(apiPrecedenceStack != null); if (apiMutableObjectType.ApiPropertyConfigurationsIndex.TryGetValue(clrPropertyName, out var apiPropertyConfigurationIndex)) { var apiPropertyConfigurationExisting = apiMutableObjectType.ApiPropertyConfigurations[apiPropertyConfigurationIndex]; return(apiPropertyConfigurationExisting); } var apiPropertyConfigurationNew = new ApiPropertyConfiguration(clrDeclaringType, clrPropertyName, clrPropertyType, apiPrecedenceStack); var apiPropertyConfigurationIndexNew = apiMutableObjectType.ApiPropertyConfigurationsIndex.Count; apiMutableObjectType.ApiPropertyConfigurations.Add(apiPropertyConfigurationNew); apiMutableObjectType.ApiPropertyConfigurationsIndex.Add(clrPropertyName, apiPropertyConfigurationIndexNew); ApiFrameworkLog.Trace($"Added {nameof(ApiProperty)} [{nameof(ApiProperty.ClrName)}={clrPropertyName}] at {apiPrecedenceLevel} Level".Indent(IndentConstants.ApiMutableObjectTypeModifier)); return(apiPropertyConfigurationNew); }
private static IApiIdentity CreateApiIdentity(ApiMutableObjectType apiMutableObjectType, IEnumerable <IApiProperty> apiProperties) { Contract.Requires(apiMutableObjectType != null); Contract.Requires(apiProperties != null); var clrIdentityProperty = apiMutableObjectType.ClrIdentityProperty; if (clrIdentityProperty == null) { return(null); } var clrIdentityPropertyName = clrIdentityProperty.ClrPropertyName; if (String.IsNullOrWhiteSpace(clrIdentityPropertyName)) { return(null); } var apiIdentityProperty = (ApiProperty)apiProperties.SingleOrDefault(x => x.ClrName == clrIdentityPropertyName); if (apiIdentityProperty == null) { var clrTypeName = apiMutableObjectType.ClrObjectType.Name; var message = $"Unable to create API identity for an API object type [clrType={clrTypeName}] because the configured API identity property [clrName={clrIdentityPropertyName}] does not exist."; throw new ApiSchemaException(message); } var apiIdentity = ApiTypeFactory.CreateApiIdentity(apiIdentityProperty); ApiFrameworkLog.Debug($"Created {apiIdentity}".Indent(IndentConstants.ApiMutableObjectTypeIdentity)); return(apiIdentity); }
private Func <ApiMutableSchema, ApiMutableObjectType> CreateApiMutableObjectTypeFactory(Type clrObjectType) { Contract.Requires(clrObjectType != null); ApiMutableObjectType ApiMutableObjectTypeFactory(ApiMutableSchema apiMutableSchema) { Contract.Requires(apiMutableSchema != null); // Apply conventions this.ApiPrecedenceStack.Push(ApiPrecedenceLevel.Convention); var apiConventionSet = apiMutableSchema?.ApiConventionSet; var apiConventionSettings = apiMutableSchema?.ApiConventionSettings; this.ApplyApiObjectTypeNameConventions(clrObjectType, apiConventionSet, apiConventionSettings); this.ApplyApiObjectTypeConventions(apiConventionSet, apiConventionSettings); this.ApiPrecedenceStack.Pop(); // Create API mutable object type var apiDefaultName = clrObjectType.Name; var apiDefaultDescription = clrObjectType.ToString(); var apiMutableObjectType = new ApiMutableObjectType { ApiMutableSchema = apiMutableSchema, ApiName = apiDefaultName, ApiDescription = apiDefaultDescription, ClrObjectType = clrObjectType }; return(apiMutableObjectType); } return(ApiMutableObjectTypeFactory); }
private static IReadOnlyCollection <IApiProperty> CreateApiProperties(ApiMutableObjectType apiMutableObjectType, ApiSchemaProxy apiSchemaProxy) { Contract.Requires(apiMutableObjectType != null); Contract.Requires(apiSchemaProxy != null); // Create an ApiPropertyConfiguration query (LINQ to Objects). var apiMutableSchema = apiMutableObjectType.ApiMutableSchema; var apiPropertyConfigurations = apiMutableObjectType.ApiPropertyConfigurations; var apiPropertyConfigurationsQuery = apiPropertyConfigurations.AsEnumerable(); // Enhance query to remove explicit (by name) excluded properties for this API object type. var clrExplicitExcludedPropertyNames = apiMutableObjectType.ClrExcludedPropertyNames; if (clrExplicitExcludedPropertyNames.Any()) { var clrExplicitIncludedPropertyNames = apiPropertyConfigurations.Select(x => x.ClrName) .ToList(); var clrExplicitIncludedPropertyNameHashSet = new HashSet <string>(clrExplicitIncludedPropertyNames); clrExplicitIncludedPropertyNameHashSet.ExceptWith(clrExplicitExcludedPropertyNames); apiPropertyConfigurationsQuery = apiPropertyConfigurationsQuery.Where(x => clrExplicitIncludedPropertyNameHashSet.Contains(x.ClrName)); } // Enhance query to remove implicit (by type) excluded properties for this API object type. var clrExcludedTypes = apiMutableSchema.ClrExcludedTypes; if (clrExcludedTypes.Any()) { var clrImplicitExcludedPropertyNameHashSet = apiPropertyConfigurations .Where(x => { var clrLeafType = x.ClrType.GetClrLeafType(); return(clrExcludedTypes.Contains(clrLeafType)); }) .Select(x => x.ClrName) .ToList(); var clrImplicitIncludedPropertyNames = apiPropertyConfigurations.Select(x => x.ClrName) .ToList(); var clrImplicitIncludedPropertyNameHashSet = new HashSet <string>(clrImplicitIncludedPropertyNames); clrImplicitIncludedPropertyNameHashSet.ExceptWith(clrImplicitExcludedPropertyNameHashSet); apiPropertyConfigurationsQuery = apiPropertyConfigurationsQuery.Where(x => clrImplicitIncludedPropertyNameHashSet.Contains(x.ClrName)); } // Execute query to create API property objects for this API object type. var apiProperties = apiPropertyConfigurationsQuery.Select(x => x.CreateApiProperty(apiMutableSchema, apiMutableObjectType, apiSchemaProxy)) .ToList(); return(apiProperties); }
private static IApiObjectType CreateApiObjectType(ApiMutableObjectType apiMutableObjectType, ApiSchemaProxy apiSchemaProxy) { Contract.Requires(apiMutableObjectType != null); Contract.Requires(apiSchemaProxy != null); var apiName = apiMutableObjectType.ApiName; var apiDescription = apiMutableObjectType.ApiDescription; var apiProperties = CreateApiProperties(apiMutableObjectType, apiSchemaProxy); var apiIdentity = CreateApiIdentity(apiMutableObjectType, apiProperties); var apiRelationships = CreateApiRelationships(apiMutableObjectType, apiSchemaProxy, apiProperties, apiIdentity); var clrObjectType = apiMutableObjectType.ClrObjectType; var apiObjectType = ApiTypeFactory.CreateApiObjectType(apiName, apiDescription, apiProperties, apiIdentity, apiRelationships, clrObjectType); return(apiObjectType); }
// ReSharper disable once ReturnTypeCanBeEnumerable.Local private static IReadOnlyCollection <IApiRelationship> CreateApiRelationships(ApiMutableObjectType apiMutableObjectType, ApiSchemaProxy apiSchemaProxy, IEnumerable <IApiProperty> apiProperties, IApiIdentity apiIdentity) { Contract.Requires(apiMutableObjectType != null); Contract.Requires(apiSchemaProxy != null); Contract.Requires(apiProperties != null); // If this API object type has no identity, it may not contain any relationships. if (apiIdentity == null) { return(null); } var apiMutableSchema = apiMutableObjectType.ApiMutableSchema; var clrRelationshipPropertyCollection = apiMutableObjectType.ClrRelationshipPropertyCollection; var apiRelationships = clrRelationshipPropertyCollection .Where(x => { // Can not create an API relationship if the related API object type does not have identity (must be an API resource type). var clrPropertyType = x.ClrPropertyType; var apiPropertyTypeKind = clrPropertyType.GetApiTypeKind(out var clrPropertyItemType); switch (apiPropertyTypeKind) { case ApiTypeKind.Object: { var isApiResourceType = apiMutableSchema.ClrResourceTypes.Contains(clrPropertyType); if (!isApiResourceType) { return(false); } break; } case ApiTypeKind.Collection: { var apiItemTypeKind = clrPropertyItemType.GetApiTypeKind(); switch (apiItemTypeKind) { case ApiTypeKind.Collection: { // Unable to handle collections within collections. var message = $"Unable to create API relationship for an API property [{nameof(x.ClrPropertyName)}={x.ClrPropertyName}] that contains collections within collections"; throw new ApiSchemaException(message); } } var isApiResourceType = apiMutableSchema.ClrResourceTypes.Contains(clrPropertyItemType); if (!isApiResourceType) { return(false); } break; } default: { return(false); } } return(true); }) .Select(x => { var clrPropertyName = x.ClrPropertyName; var clrPropertyType = x.ClrPropertyType; var apiProperty = apiProperties.Single(y => y.ClrName == clrPropertyName); var apiPropertyTypeKind = clrPropertyType.GetApiTypeKind(out var clrPropertyItemType); ApiRelationshipCardinality apiCardinality; Type clrType; switch (apiPropertyTypeKind) { case ApiTypeKind.Object: { apiCardinality = ApiRelationshipCardinality.ToOne; clrType = clrPropertyType; break; } case ApiTypeKind.Collection: { apiCardinality = ApiRelationshipCardinality.ToMany; clrType = clrPropertyItemType; break; } default: { throw new ArgumentOutOfRangeException(); } } var apiRelatedTypeResolver = new ApiSchemaProxyTypeResolver(apiSchemaProxy, ApiTypeKind.Object, clrType); var apiRelationship = ApiTypeFactory.CreateApiRelationship(apiProperty, apiCardinality, apiRelatedTypeResolver); return(apiRelationship); }) .ToList(); foreach (var apiRelationship in apiRelationships) { ApiFrameworkLog.Debug($"Created {apiRelationship}".Indent(IndentConstants.ApiMutableObjectTypeRelationship)); } return(apiRelationships); }